ps_ecc/polynomial/methods/
eval_coefficient_iter_at.rs1use crate::{
2 finite_field::{add, mul},
3 Polynomial,
4};
5
6impl Polynomial {
7 #[must_use]
12 pub fn eval_coefficient_iter_at<I>(coefficients: I, x: u8) -> u8
13 where
14 I: DoubleEndedIterator<Item = u8>,
15 {
16 let mut result = 0u8;
17
18 for coef in coefficients.rev() {
19 result = add(mul(result, x), coef);
20 }
21
22 result
23 }
24}
25
26#[cfg(test)]
27mod tests {
28 use crate::{
29 finite_field::{add, mul},
30 Polynomial,
31 };
32
33 fn naive_eval(coefficients: impl Iterator<Item = u8>, x: u8) -> u8 {
35 let mut result = 0u8;
36 let mut x_pow = 1u8;
37
38 for c in coefficients {
39 result = add(result, mul(c, x_pow));
40 x_pow = mul(x_pow, x);
41 }
42
43 result
44 }
45
46 fn assert_exhaustive(coefficients: &[u8]) {
48 for x in 0..=255u8 {
49 assert_eq!(
50 Polynomial::eval_coefficient_iter_at(coefficients.iter().copied(), x),
51 naive_eval(coefficients.iter().copied(), x)
52 );
53 }
54 }
55
56 fn assert_exhaustive_chained(low: &[u8], high: &[u8]) {
58 for x in 0..=255u8 {
59 let iter = low.iter().chain(high.iter()).copied();
60
61 assert_eq!(
62 Polynomial::eval_coefficient_iter_at(low.iter().chain(high.iter()).copied(), x),
63 naive_eval(iter, x)
64 );
65 }
66 }
67
68 #[test]
69 fn empty_iterator() {
70 assert_exhaustive(&[]);
71 }
72
73 #[test]
74 fn zero_polynomial() {
75 assert_exhaustive(&[0]);
76 }
77
78 #[test]
79 fn constant_polynomial() {
80 assert_exhaustive(&[1]);
81 assert_exhaustive(&[42]);
82 assert_exhaustive(&[128]);
83 assert_exhaustive(&[255]);
84 }
85
86 #[test]
87 fn linear_polynomial() {
88 assert_exhaustive(&[5, 3]);
89 assert_exhaustive(&[0, 1]);
90 assert_exhaustive(&[255, 255]);
91 }
92
93 #[test]
94 fn quadratic_polynomial() {
95 assert_exhaustive(&[1, 0, 1]);
96 assert_exhaustive(&[0, 0, 1]);
97 assert_exhaustive(&[255, 128, 64]);
98 }
99
100 #[test]
101 fn cubic_polynomial() {
102 assert_exhaustive(&[0x12, 0x34, 0x56, 0x78]);
103 assert_exhaustive(&[1, 1, 1, 1]);
104 assert_exhaustive(&[0, 0, 0, 1]);
105 }
106
107 #[test]
108 fn high_degree_polynomial() {
109 assert_exhaustive(&[1, 2, 3, 4, 5, 6, 7, 8]);
110 assert_exhaustive(&[0, 0, 0, 0, 0, 0, 0, 1]);
111 }
112
113 #[test]
114 fn sparse_polynomial() {
115 assert_exhaustive(&[1, 0, 0, 0, 1]);
116 assert_exhaustive(&[0, 1, 0, 1, 0]);
117 }
118
119 #[test]
120 fn all_coefficients_max() {
121 assert_exhaustive(&[255, 255, 255, 255]);
122 }
123
124 #[test]
125 fn max_degree_monomial() {
126 let mut coefficients = [0u8; Polynomial::MAX_COEFFICIENTS as usize];
127
128 coefficients[Polynomial::MAX_DEGREE as usize] = 1;
129
130 assert_exhaustive(&coefficients);
131 }
132
133 #[test]
134 fn max_degree_all_ones() {
135 let coefficients = [1u8; Polynomial::MAX_COEFFICIENTS as usize];
136
137 assert_exhaustive(&coefficients);
138 }
139
140 #[test]
141 fn max_degree_all_max() {
142 let coefficients = [255u8; Polynomial::MAX_COEFFICIENTS as usize];
143
144 assert_exhaustive(&coefficients);
145 }
146
147 #[test]
148 fn chained_empty_slices() {
149 assert_exhaustive_chained(&[], &[]);
150 }
151
152 #[test]
153 fn chained_one_empty() {
154 assert_exhaustive_chained(&[1, 2, 3], &[]);
155 assert_exhaustive_chained(&[], &[1, 2, 3]);
156 }
157
158 #[test]
159 fn chained_equal_length() {
160 assert_exhaustive_chained(&[1, 2, 3], &[4, 5, 6]);
161 assert_exhaustive_chained(&[0, 0, 0], &[0, 0, 1]);
162 assert_exhaustive_chained(&[255, 255], &[255, 255]);
163 }
164
165 #[test]
166 fn chained_unequal_length() {
167 assert_exhaustive_chained(&[1], &[2, 3, 4, 5]);
168 assert_exhaustive_chained(&[1, 2, 3, 4], &[5]);
169 }
170
171 #[test]
172 fn matches_eval_coefficients_at() {
173 let coefficients = [0x12u8, 0x34, 0x56, 0x78];
174
175 for x in 0..=255u8 {
176 assert_eq!(
177 Polynomial::eval_coefficient_iter_at(coefficients.iter().copied(), x),
178 Polynomial::eval_coefficients_at(&coefficients, x)
179 );
180 }
181 }
182}