Skip to main content

ps_ecc/polynomial/implementations/
sub.rs

1use std::{
2    borrow::Borrow,
3    ops::{BitXor, Sub},
4};
5
6use crate::{error::PolynomialXorError, Polynomial};
7
8impl<B: Borrow<u8>, I: IntoIterator<Item = B>> Sub<I> for Polynomial {
9    type Output = Result<Self, PolynomialXorError>;
10
11    /// Subtracts coefficients from an iterator from this polynomial.
12    ///
13    /// In GF(256), subtraction is equivalent to addition, which is XOR.
14    /// This delegates to `BitXor`.
15    ///
16    /// # Errors
17    ///
18    /// Returns `TooManyCoefficients` if the iterator yields more than 255 elements.
19    fn sub(self, rhs: I) -> Self::Output {
20        BitXor::bitxor(self, rhs)
21    }
22}
23
24impl<B: Borrow<u8>, I: IntoIterator<Item = B>> Sub<I> for &Polynomial {
25    type Output = Result<Polynomial, PolynomialXorError>;
26
27    fn sub(self, rhs: I) -> Self::Output {
28        BitXor::bitxor(*self, rhs)
29    }
30}
31
32#[cfg(test)]
33#[allow(clippy::expect_used)]
34mod tests {
35    use std::ops::Sub;
36
37    use crate::{error::PolynomialXorError, Polynomial};
38
39    #[test]
40    fn sub_two_polynomials() {
41        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
42        let b = Polynomial::try_from(&[4u8, 5, 6][..]).expect("valid polynomial");
43
44        let result = a.sub(b).expect("polynomials are bounded");
45
46        assert_eq!(result.coefficients(), &[1 ^ 4, 2 ^ 5, 3 ^ 6]);
47    }
48
49    #[test]
50    fn sub_different_degrees() {
51        let a = Polynomial::try_from(&[1u8, 2][..]).expect("valid polynomial");
52        let b = Polynomial::try_from(&[3u8, 4, 5, 6][..]).expect("valid polynomial");
53
54        let result = a.sub(b).expect("polynomials are bounded");
55
56        assert_eq!(result.coefficients(), &[1 ^ 3, 2 ^ 4, 5, 6]);
57    }
58
59    #[test]
60    fn sub_cancels_to_zero() {
61        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
62        let b = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
63
64        let result = a.sub(b).expect("polynomials are bounded");
65
66        assert_eq!(result.degree(), 0);
67        assert_eq!(result.coefficients(), &[0]);
68    }
69
70    #[test]
71    fn sub_with_references() {
72        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
73        let b = Polynomial::try_from(&[4u8, 5, 6][..]).expect("valid polynomial");
74
75        let result = (&a).sub(&b).expect("polynomials are bounded");
76
77        assert_eq!(result.coefficients(), &[1 ^ 4, 2 ^ 5, 3 ^ 6]);
78    }
79
80    #[test]
81    fn sub_slice_via_iter() {
82        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
83        let slice: &[u8] = &[4, 5, 6];
84
85        let result = a.sub(slice.iter()).expect("valid slice");
86
87        assert_eq!(result.coefficients(), &[1 ^ 4, 2 ^ 5, 3 ^ 6]);
88    }
89
90    #[test]
91    fn sub_slice_different_lengths() {
92        let a = Polynomial::try_from(&[1u8, 2][..]).expect("valid polynomial");
93        let slice: &[u8] = &[3, 4, 5, 6];
94
95        let result = a.sub(slice.iter()).expect("valid slice");
96
97        assert_eq!(result.coefficients(), &[1 ^ 3, 2 ^ 4, 5, 6]);
98    }
99
100    #[test]
101    fn sub_iterator() {
102        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
103        let iter = [4u8, 5, 6].into_iter();
104
105        let result = a.sub(iter).expect("valid iterator");
106
107        assert_eq!(result.coefficients(), &[1 ^ 4, 2 ^ 5, 3 ^ 6]);
108    }
109
110    #[test]
111    fn sub_vec() {
112        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
113        let vec = vec![4u8, 5, 6, 7];
114
115        let result = a.sub(vec).expect("valid vec");
116
117        assert_eq!(result.coefficients(), &[1 ^ 4, 2 ^ 5, 3 ^ 6, 7]);
118    }
119
120    #[test]
121    fn sub_iterator_too_long_returns_error() {
122        let a = Polynomial::default();
123        let iter = std::iter::repeat_n(1u8, 256);
124
125        let result = a.sub(iter);
126
127        assert_eq!(result, Err(PolynomialXorError::TooManyCoefficients));
128    }
129
130    #[test]
131    fn sub_equals_add() {
132        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
133        let b = Polynomial::try_from(&[4u8, 5, 6][..]).expect("valid polynomial");
134
135        let sub_result = a.sub(&b).expect("polynomials are bounded");
136
137        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
138
139        let add_result = std::ops::Add::add(a, &b).expect("polynomials are bounded");
140
141        assert_eq!(sub_result, add_result);
142    }
143}