Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
duyuefeng0708
GitHub Repository: duyuefeng0708/Cryptography-From-First-Principle
Path: blob/main/foundations/02-rings-fields-polynomials/rust/src/lib.rs
483 views
unlisted
1
//! # Module 02: Rings, Fields, and Polynomials — Exercises
2
//!
3
//! Polynomials are `Vec<u64>` where index = degree: `vec![3, 0, 2]` = 2x² + 3.
4
//! All arithmetic is mod `p`.
5
//!
6
//! ## Progression
7
//! 1. `poly_eval` — Guided (Horner's method skeleton)
8
//! 2. `poly_add` — Guided (zip/pad approach)
9
//! 3. `poly_mul` — Scaffolded (convolution hint)
10
//! 4. `poly_div_rem` — Scaffolded (long division outline)
11
//! 5. `is_irreducible_mod_p` — Independent
12
13
/// Evaluate polynomial at `x` mod `p` using Horner's method.
14
///
15
/// # Example
16
/// ```
17
/// # use rings_fields_poly::poly_eval;
18
/// assert_eq!(poly_eval(&[1, 2, 3], 5, 7), 2); // 1 + 10 + 75 = 86 ≡ 2 mod 7
19
/// ```
20
pub fn poly_eval(coeffs: &[u64], x: u64, p: u64) -> u64 {
21
// Horner's method: iterate from highest degree to lowest.
22
// result = 0
23
// for coeff in coeffs.iter().rev():
24
// result = (result * x + coeff) % p
25
let mut result: u64 = 0;
26
for &coeff in coeffs.iter().rev() {
27
// TODO: result = (result * x + coeff) % p
28
// Use u128 to avoid overflow.
29
todo!("Horner step")
30
}
31
result
32
}
33
34
/// Add two polynomials coefficient-wise mod `p`. Trim trailing zeros.
35
pub fn poly_add(a: &[u64], b: &[u64], p: u64) -> Vec<u64> {
36
// Hint: result length = max(a.len(), b.len())
37
// Add corresponding coefficients mod p, then trim.
38
todo!("Add polynomials mod p")
39
}
40
41
/// Multiply two polynomials mod `p` via convolution.
42
///
43
/// Coefficient of x^k = Σ a[i] * b[k-i] mod p for valid indices.
44
pub fn poly_mul(a: &[u64], b: &[u64], p: u64) -> Vec<u64> {
45
todo!("Polynomial convolution mod p")
46
}
47
48
/// Polynomial long division: returns (quotient, remainder) mod `p`.
49
///
50
/// You'll need modular inverse of the leading coefficient of `b`.
51
pub fn poly_div_rem(a: &[u64], b: &[u64], p: u64) -> (Vec<u64>, Vec<u64>) {
52
todo!("Polynomial long division mod p")
53
}
54
55
/// Check if polynomial is irreducible over Z/pZ by trial division.
56
///
57
/// Try all monic polynomials of degree 1..=deg/2. If none divide evenly,
58
/// the polynomial is irreducible.
59
pub fn is_irreducible_mod_p(coeffs: &[u64], p: u64) -> bool {
60
todo!("Brute-force irreducibility check")
61
}
62
63
fn trim_poly(v: &mut Vec<u64>) {
64
while v.len() > 1 && *v.last().unwrap() == 0 {
65
v.pop();
66
}
67
}
68
69
#[cfg(test)]
70
mod tests {
71
use super::*;
72
73
#[test]
74
#[ignore]
75
fn test_poly_eval_basic() {
76
assert_eq!(poly_eval(&[1, 2, 3], 5, 7), 2);
77
}
78
79
#[test]
80
#[ignore]
81
fn test_poly_eval_constant() {
82
assert_eq!(poly_eval(&[42], 999, 7), 0);
83
}
84
85
#[test]
86
#[ignore]
87
fn test_poly_add_same_degree() {
88
assert_eq!(poly_add(&[1, 2, 3], &[4, 5, 6], 7), vec![5, 0, 2]);
89
}
90
91
#[test]
92
#[ignore]
93
fn test_poly_add_different_degree() {
94
assert_eq!(poly_add(&[1, 2], &[3, 0, 1], 7), vec![4, 2, 1]);
95
}
96
97
#[test]
98
#[ignore]
99
fn test_poly_mul_linear() {
100
assert_eq!(poly_mul(&[1, 1], &[1, 1], 7), vec![1, 2, 1]);
101
}
102
103
#[test]
104
#[ignore]
105
fn test_poly_mul_mod() {
106
assert_eq!(poly_mul(&[3, 4], &[2, 5], 7), vec![6, 2, 6]);
107
}
108
109
#[test]
110
#[ignore]
111
fn test_poly_div_rem_exact() {
112
let (q, r) = poly_div_rem(&[1, 2, 1], &[1, 1], 7);
113
assert_eq!(q, vec![1, 1]);
114
assert_eq!(r, vec![0]);
115
}
116
117
#[test]
118
#[ignore]
119
fn test_irreducible_true() {
120
assert!(is_irreducible_mod_p(&[1, 1, 1], 2));
121
}
122
123
#[test]
124
#[ignore]
125
fn test_irreducible_false() {
126
assert!(!is_irreducible_mod_p(&[1, 0, 1], 2));
127
}
128
}
129
130