Skip to main content

ps_ecc/polynomial/methods/
set_coefficients.rs

1use crate::{error::PolynomialSetCoefficientsError, Polynomial};
2
3impl Polynomial {
4    /// Sets coefficients starting at degree `offset` from a slice.
5    ///
6    /// Copies `values` into the coefficient array at `offset..offset + values.len()`,
7    /// then adjusts the degree accordingly.
8    ///
9    /// Empty slices are a no-op.
10    ///
11    /// # Errors
12    ///
13    /// Returns `OutOfBounds` if `offset + values.len()` exceeds 255.
14    pub fn set_coefficients(
15        &mut self,
16        offset: u8,
17        values: &[u8],
18    ) -> Result<(), PolynomialSetCoefficientsError> {
19        if values.is_empty() {
20            return Ok(());
21        }
22
23        let start = offset as usize;
24        let end = start + values.len();
25
26        if end > Self::MAX_COEFFICIENTS as usize {
27            return Err(PolynomialSetCoefficientsError::OutOfBounds { offset, end });
28        }
29
30        self.coefficients[start..end].copy_from_slice(values);
31
32        #[allow(clippy::cast_possible_truncation)]
33        let last = (end - 1) as u8;
34
35        if last > self.degree {
36            self.degree = last;
37        }
38
39        self.trim_degree();
40
41        Ok(())
42    }
43}
44
45#[cfg(test)]
46#[allow(clippy::expect_used)]
47mod tests {
48    use crate::{error::PolynomialSetCoefficientsError, Polynomial};
49
50    #[test]
51    fn below_degree() {
52        let mut p = Polynomial::try_from(&[1u8, 2, 3, 4, 5][..]).expect("valid polynomial");
53
54        p.set_coefficients(1, &[10, 20]).expect("in bounds");
55
56        assert_eq!(p.coefficients(), &[1, 10, 20, 4, 5]);
57    }
58
59    #[test]
60    fn extends_degree() {
61        let mut p = Polynomial::try_from(&[1u8, 2][..]).expect("valid polynomial");
62
63        p.set_coefficients(2, &[3, 4, 5]).expect("in bounds");
64
65        assert_eq!(p.coefficients(), &[1, 2, 3, 4, 5]);
66    }
67
68    #[test]
69    fn trims_degree() {
70        let mut p = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
71
72        p.set_coefficients(1, &[0, 0]).expect("in bounds");
73
74        assert_eq!(p.coefficients(), &[1]);
75        assert_eq!(p.degree(), 0);
76    }
77
78    #[test]
79    fn trims_to_zero_polynomial() {
80        let mut p = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
81
82        p.set_coefficients(0, &[0, 0, 0]).expect("in bounds");
83
84        assert_eq!(p.coefficients(), &[0]);
85        assert_eq!(p.degree(), 0);
86    }
87
88    #[test]
89    fn empty_is_noop() {
90        let mut p = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
91        let before = p;
92
93        p.set_coefficients(0, &[]).expect("in bounds");
94
95        assert_eq!(p, before);
96    }
97
98    #[test]
99    fn at_offset_zero() {
100        let mut p = Polynomial::try_from(&[0u8, 0, 5][..]).expect("valid polynomial");
101
102        p.set_coefficients(0, &[1, 2]).expect("in bounds");
103
104        assert_eq!(p.coefficients(), &[1, 2, 5]);
105    }
106
107    #[test]
108    fn single_element() {
109        let mut p = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
110
111        p.set_coefficients(1, &[99]).expect("in bounds");
112
113        assert_eq!(p.coefficients(), &[1, 99, 3]);
114    }
115
116    #[test]
117    fn overwrites_entire_polynomial() {
118        let mut p = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
119
120        p.set_coefficients(0, &[10, 20, 30]).expect("in bounds");
121
122        assert_eq!(p.coefficients(), &[10, 20, 30]);
123    }
124
125    #[test]
126    fn gap_between_old_and_new() {
127        let mut p = Polynomial::try_from(&[1u8][..]).expect("valid polynomial");
128
129        p.set_coefficients(3, &[5, 6]).expect("in bounds");
130
131        assert_eq!(p.coefficients(), &[1, 0, 0, 5, 6]);
132    }
133
134    #[test]
135    fn extends_with_trailing_zeros() {
136        let mut p = Polynomial::try_from(&[1u8, 2][..]).expect("valid polynomial");
137
138        p.set_coefficients(3, &[5, 0]).expect("in bounds");
139
140        assert_eq!(p.coefficients(), &[1, 2, 0, 5]);
141        assert_eq!(p.degree(), 3);
142    }
143
144    #[test]
145    fn overwrites_leading_coefficient() {
146        let mut p = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
147
148        p.set_coefficients(2, &[99]).expect("in bounds");
149
150        assert_eq!(p.coefficients(), &[1, 2, 99]);
151        assert_eq!(p.degree(), 2);
152    }
153
154    #[test]
155    fn out_of_bounds_returns_error() {
156        let mut p = Polynomial::default();
157
158        let result = p.set_coefficients(250, &[1, 2, 3, 4, 5, 6]);
159
160        assert_eq!(
161            result,
162            Err(PolynomialSetCoefficientsError::OutOfBounds {
163                offset: 250,
164                end: 256
165            })
166        );
167    }
168}