Skip to main content

qfall_math/integer_mod_q/polynomial_ring_zq/arithmetic/
add.rs

1// Copyright © 2023 Phil Milewski, Marcel Luca Schmidt
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! Implementation of the [`Add`] trait for [`PolynomialRingZq`] values.
10
11use super::super::PolynomialRingZq;
12use crate::{
13    error::MathError,
14    integer::PolyOverZ,
15    integer_mod_q::PolyOverZq,
16    macros::arithmetics::{
17        arithmetic_assign_trait_borrowed_to_owned, arithmetic_trait_borrowed_to_owned,
18        arithmetic_trait_mixed_borrowed_owned, arithmetic_trait_reverse,
19    },
20    traits::CompareBase,
21};
22use std::ops::{Add, AddAssign};
23
24impl AddAssign<&PolynomialRingZq> for PolynomialRingZq {
25    /// Computes the addition of `self` and `other` reusing
26    /// the memory of `self`.
27    /// [`AddAssign`] can be used on [`PolynomialRingZq`] in combination with
28    /// [`PolynomialRingZq`], [`PolyOverZ`] and [`PolyOverZq`].
29    ///
30    /// Parameters:
31    /// - `other`: specifies the polynomial to add to `self`
32    ///
33    /// Returns the sum of both polynomials modulo `Z_q[X]` as a [`PolynomialRingZq`].
34    ///
35    /// # Examples
36    /// ```
37    /// use qfall_math::integer_mod_q::{PolynomialRingZq, ModulusPolynomialRingZq, PolyOverZq};
38    /// use qfall_math::integer::PolyOverZ;
39    /// use std::str::FromStr;
40    ///
41    /// let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
42    /// let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
43    /// let mut a = PolynomialRingZq::from((&poly_1, &modulus));
44    /// let c = PolyOverZ::from_str("4  2 0 3 1").unwrap();
45    /// let b = PolynomialRingZq::from((&c, &modulus));
46    /// let d = PolyOverZq::from((&c, 17));
47    ///
48    /// a += &b;
49    /// a += b;
50    /// a += &c;
51    /// a += c;
52    /// a += &d;
53    /// a += d;
54    /// ```
55    ///
56    /// # Panics ...
57    /// - if the moduli of both [`PolynomialRingZq`] mismatch.
58    fn add_assign(&mut self, other: &Self) {
59        if !self.compare_base(other) {
60            panic!("{}", self.call_compare_base_error(other).unwrap());
61        }
62
63        self.poly += &other.poly;
64        self.reduce();
65    }
66}
67impl AddAssign<&PolyOverZ> for PolynomialRingZq {
68    /// Documentation at [`PolynomialRingZq::add_assign`].
69    fn add_assign(&mut self, other: &PolyOverZ) {
70        self.poly += other;
71        self.reduce();
72    }
73}
74impl AddAssign<&PolyOverZq> for PolynomialRingZq {
75    /// Documentation at [`PolynomialRingZq::add_assign`].
76    ///
77    /// # Panics ...
78    /// - if the moduli are different.
79    fn add_assign(&mut self, other: &PolyOverZq) {
80        if !self.compare_base(other) {
81            panic!("{}", self.call_compare_base_error(other).unwrap())
82        }
83
84        self.poly += &other.get_representative_least_nonnegative_residue();
85        self.reduce();
86    }
87}
88
89arithmetic_assign_trait_borrowed_to_owned!(
90    AddAssign,
91    add_assign,
92    PolynomialRingZq,
93    PolynomialRingZq
94);
95arithmetic_assign_trait_borrowed_to_owned!(AddAssign, add_assign, PolynomialRingZq, PolyOverZ);
96arithmetic_assign_trait_borrowed_to_owned!(AddAssign, add_assign, PolynomialRingZq, PolyOverZq);
97
98impl Add for &PolynomialRingZq {
99    type Output = PolynomialRingZq;
100    /// Implements the [`Add`] trait for two [`PolynomialRingZq`] values.
101    /// [`Add`] is implemented for any combination of [`PolynomialRingZq`] and borrowed [`PolynomialRingZq`].
102    ///
103    /// Parameters:
104    /// - `other`: specifies the polynomial to add to `self`
105    ///
106    /// Returns the sum of both polynomials as a [`PolynomialRingZq`].
107    ///
108    /// # Examples
109    /// ```
110    /// use qfall_math::integer_mod_q::PolynomialRingZq;
111    /// use qfall_math::integer_mod_q::ModulusPolynomialRingZq;
112    /// use qfall_math::integer::PolyOverZ;
113    /// use std::str::FromStr;
114    ///
115    /// let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
116    /// let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
117    /// let a = PolynomialRingZq::from((&poly_1, &modulus));
118    /// let poly_2 = PolyOverZ::from_str("4  2 0 3 1").unwrap();
119    /// let b = PolynomialRingZq::from((&poly_2, &modulus));
120    ///
121    /// let c: PolynomialRingZq = &a + &b;
122    /// let d: PolynomialRingZq = a + b;
123    /// let e: PolynomialRingZq = &c + d;
124    /// let f: PolynomialRingZq = c + &e;
125    /// ```
126    ///
127    /// # Panics ...
128    /// - if the moduli of both [`PolynomialRingZq`] mismatch.
129    fn add(self, other: Self) -> Self::Output {
130        self.add_safe(other).unwrap()
131    }
132}
133
134impl Add<&PolyOverZ> for &PolynomialRingZq {
135    type Output = PolynomialRingZq;
136    /// Implements the [`Add`] trait for [`PolynomialRingZq`] and [`PolyOverZ`].
137    /// [`Add`] is implemented for any combination of owned and borrowed values.
138    ///
139    /// Parameters:
140    /// - `other`: specifies the polynomial to add to `self`
141    ///
142    /// Returns the addition of both polynomials as a [`PolynomialRingZq`].
143    ///
144    /// # Examples
145    /// ```
146    /// use qfall_math::integer_mod_q::PolynomialRingZq;
147    /// use qfall_math::integer_mod_q::ModulusPolynomialRingZq;
148    /// use qfall_math::integer::PolyOverZ;
149    /// use std::str::FromStr;
150    ///
151    /// let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
152    /// let poly = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
153    /// let a = PolynomialRingZq::from((&poly, &modulus));
154    /// let b = PolyOverZ::from_str("4  2 0 3 1").unwrap();
155    ///
156    /// let c: PolynomialRingZq = &a + &b;
157    /// ```
158    fn add(self, other: &PolyOverZ) -> Self::Output {
159        let mut out = self.clone();
160        out += other;
161        out
162    }
163}
164
165arithmetic_trait_reverse!(Add, add, PolyOverZ, PolynomialRingZq, PolynomialRingZq);
166
167arithmetic_trait_borrowed_to_owned!(Add, add, PolynomialRingZq, PolyOverZ, PolynomialRingZq);
168arithmetic_trait_borrowed_to_owned!(Add, add, PolyOverZ, PolynomialRingZq, PolynomialRingZq);
169arithmetic_trait_mixed_borrowed_owned!(Add, add, PolynomialRingZq, PolyOverZ, PolynomialRingZq);
170arithmetic_trait_mixed_borrowed_owned!(Add, add, PolyOverZ, PolynomialRingZq, PolynomialRingZq);
171
172impl Add<&PolyOverZq> for &PolynomialRingZq {
173    type Output = PolynomialRingZq;
174    /// Implements the [`Add`] trait for [`PolynomialRingZq`] and [`PolyOverZq`].
175    /// [`Add`] is implemented for any combination of owned and borrowed values.
176    ///
177    /// Parameters:
178    /// - `other`: specifies the polynomial to add to `self`
179    ///
180    /// Returns the addition of both polynomials as a [`PolynomialRingZq`].
181    ///
182    /// # Examples
183    /// ```
184    /// use qfall_math::integer_mod_q::{PolyOverZq, PolynomialRingZq};
185    /// use qfall_math::integer_mod_q::ModulusPolynomialRingZq;
186    /// use qfall_math::integer::PolyOverZ;
187    /// use std::str::FromStr;
188    ///
189    /// let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
190    /// let poly = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
191    /// let a = PolynomialRingZq::from((&poly, &modulus));
192    /// let b = PolyOverZq::from_str("4  2 0 3 1 mod 17").unwrap();
193    ///
194    /// let c: PolynomialRingZq = &a + &b;
195    /// ```
196    ///
197    /// # Panics ...
198    /// - if the moduli mismatch.
199    fn add(self, other: &PolyOverZq) -> Self::Output {
200        if !self.compare_base(other) {
201            panic!("{}", self.call_compare_base_error(other).unwrap())
202        }
203
204        let mut out = self.clone();
205        out.poly += &other.get_representative_least_nonnegative_residue();
206        out
207    }
208}
209
210arithmetic_trait_reverse!(Add, add, PolyOverZq, PolynomialRingZq, PolynomialRingZq);
211
212arithmetic_trait_borrowed_to_owned!(Add, add, PolynomialRingZq, PolyOverZq, PolynomialRingZq);
213arithmetic_trait_borrowed_to_owned!(Add, add, PolyOverZq, PolynomialRingZq, PolynomialRingZq);
214arithmetic_trait_mixed_borrowed_owned!(Add, add, PolynomialRingZq, PolyOverZq, PolynomialRingZq);
215arithmetic_trait_mixed_borrowed_owned!(Add, add, PolyOverZq, PolynomialRingZq, PolynomialRingZq);
216
217impl PolynomialRingZq {
218    /// Implements addition for two [`PolynomialRingZq`] values.
219    ///
220    /// Parameters:
221    /// - `other`: specifies the polynomial to add to `self`
222    ///
223    /// Returns the sum of both polynomials as a [`PolynomialRingZq`] or an error if the moduli
224    /// mismatch.
225    ///
226    /// # Examples
227    /// ```
228    /// use qfall_math::integer_mod_q::PolynomialRingZq;
229    /// use qfall_math::integer_mod_q::ModulusPolynomialRingZq;
230    /// use qfall_math::integer::PolyOverZ;
231    /// use std::str::FromStr;
232    ///
233    /// let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
234    /// let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
235    /// let a = PolynomialRingZq::from((&poly_1, &modulus));
236    /// let poly_2 = PolyOverZ::from_str("4  2 0 3 1").unwrap();
237    /// let b = PolynomialRingZq::from((&poly_2, &modulus));
238    ///
239    /// let c: PolynomialRingZq = a.add_safe(&b).unwrap();
240    /// ```
241    /// # Errors and Failures
242    /// - Returns a [`MathError`] of type [`MathError::MismatchingModulus`] if the moduli of
243    ///   both [`PolynomialRingZq`] mismatch.
244    pub fn add_safe(&self, other: &Self) -> Result<PolynomialRingZq, MathError> {
245        if !self.compare_base(other) {
246            return Err(self.call_compare_base_error(other).unwrap());
247        }
248        let mut out = self.clone();
249        out += other;
250        Ok(out)
251    }
252}
253
254arithmetic_trait_borrowed_to_owned!(
255    Add,
256    add,
257    PolynomialRingZq,
258    PolynomialRingZq,
259    PolynomialRingZq
260);
261arithmetic_trait_mixed_borrowed_owned!(
262    Add,
263    add,
264    PolynomialRingZq,
265    PolynomialRingZq,
266    PolynomialRingZq
267);
268
269#[cfg(test)]
270mod test_add_assign {
271    use super::PolyOverZ;
272    use crate::integer_mod_q::{ModulusPolynomialRingZq, PolyOverZq, PolynomialRingZq};
273    use std::str::FromStr;
274
275    /// Ensure that `add_assign` works for small numbers.
276    #[test]
277    fn correct_small() {
278        let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
279        let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
280        let mut a = PolynomialRingZq::from((&poly_1, &modulus));
281        let poly_2 = PolyOverZ::from_str("4  2 0 3 -1").unwrap();
282        let b = PolynomialRingZq::from((&poly_2, &modulus));
283        let cmp = PolynomialRingZq::from((&PolyOverZ::from_str("3  1 0 4").unwrap(), &modulus));
284
285        a += b;
286
287        assert_eq!(cmp, a);
288    }
289
290    /// Ensure that `add_assign` works for large numbers.
291    #[test]
292    fn correct_large() {
293        let modulus = ModulusPolynomialRingZq::from_str(&format!(
294            "4  {} 0 0 1 mod {}",
295            u64::MAX,
296            u64::MAX - 58
297        ))
298        .unwrap();
299        let poly_1 = PolyOverZ::from_str(&format!("4  {} 0 1 {}", u64::MAX, i64::MIN)).unwrap();
300        let mut a = PolynomialRingZq::from((&poly_1, &modulus));
301        let poly_2 = PolyOverZ::from_str(&format!("4  {} 0 -1 {}", i64::MAX, i64::MAX)).unwrap();
302        let b = PolynomialRingZq::from((&poly_2, &modulus));
303        let cmp = PolynomialRingZq::from((
304            &PolyOverZ::from_str(&format!("4  {} 0 0 {}", (u64::MAX - 1) / 2 + 58, -1)).unwrap(),
305            &modulus,
306        ));
307
308        a += b;
309
310        assert_eq!(cmp, a);
311    }
312
313    /// Ensure that `add_assign` is available for all types.
314    #[test]
315    fn availability() {
316        let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
317        let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
318        let mut a = PolynomialRingZq::from((&poly_1, &modulus));
319        let poly_2 = PolyOverZ::from_str("4  2 0 3 1").unwrap();
320        let b = PolynomialRingZq::from((&poly_2, &modulus));
321        let c = PolyOverZq::from((poly_2, 17));
322
323        a += &b;
324        a += b;
325        a += &poly_1;
326        a += poly_1;
327        a += &c;
328        a += c;
329    }
330
331    /// Ensures that mismatching moduli result in a panic.
332    #[test]
333    #[should_panic]
334    fn mismatching_moduli() {
335        let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
336        let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
337        let mut a = PolynomialRingZq::from((&poly_1, &modulus));
338        let modulus = ModulusPolynomialRingZq::from_str("4  2 0 0 1 mod 17").unwrap();
339        let poly_2 = PolyOverZ::from_str("4  2 0 3 1").unwrap();
340        let b = PolynomialRingZq::from((&poly_2, &modulus));
341
342        a += b;
343    }
344}
345
346#[cfg(test)]
347mod test_add {
348    use crate::integer::PolyOverZ;
349    use crate::integer_mod_q::ModulusPolynomialRingZq;
350    use crate::integer_mod_q::PolynomialRingZq;
351    use std::str::FromStr;
352
353    /// Testing addition for two [`PolynomialRingZq`]
354    #[test]
355    fn add() {
356        let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
357        let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
358        let a = PolynomialRingZq::from((&poly_1, &modulus));
359        let poly_2 = PolyOverZ::from_str("4  2 0 3 1").unwrap();
360        let b = PolynomialRingZq::from((&poly_2, &modulus));
361        let c = a + b;
362        assert_eq!(
363            c,
364            PolynomialRingZq::from((&PolyOverZ::from_str("4  1 0 4 2").unwrap(), &modulus))
365        );
366    }
367
368    /// Testing addition for two borrowed [`PolynomialRingZq`]
369    #[test]
370    fn add_borrow() {
371        let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
372        let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
373        let a = PolynomialRingZq::from((&poly_1, &modulus));
374        let poly_2 = PolyOverZ::from_str("4  2 0 3 1").unwrap();
375        let b = PolynomialRingZq::from((&poly_2, &modulus));
376        let c = &a + &b;
377        assert_eq!(
378            c,
379            PolynomialRingZq::from((&PolyOverZ::from_str("4  1 0 4 2").unwrap(), &modulus))
380        );
381    }
382
383    /// Testing addition for borrowed [`PolynomialRingZq`] and [`PolynomialRingZq`]
384    #[test]
385    fn add_first_borrowed() {
386        let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
387        let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
388        let a = PolynomialRingZq::from((&poly_1, &modulus));
389        let poly_2 = PolyOverZ::from_str("4  2 0 3 1").unwrap();
390        let b = PolynomialRingZq::from((&poly_2, &modulus));
391        let c = &a + b;
392        assert_eq!(
393            c,
394            PolynomialRingZq::from((&PolyOverZ::from_str("4  1 0 4 2").unwrap(), &modulus))
395        );
396    }
397
398    /// Testing addition for [`PolynomialRingZq`] and borrowed [`PolynomialRingZq`]
399    #[test]
400    fn add_second_borrowed() {
401        let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
402        let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
403        let a = PolynomialRingZq::from((&poly_1, &modulus));
404        let poly_2 = PolyOverZ::from_str("4  2 0 3 1").unwrap();
405        let b = PolynomialRingZq::from((&poly_2, &modulus));
406        let c = a + &b;
407        assert_eq!(
408            c,
409            PolynomialRingZq::from((&PolyOverZ::from_str("4  1 0 4 2").unwrap(), &modulus))
410        );
411    }
412
413    /// Testing addition for [`PolynomialRingZq`] reduces `0` coefficients
414    #[test]
415    fn add_reduce() {
416        let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
417        let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
418        let a = PolynomialRingZq::from((&poly_1, &modulus));
419        let poly_2 = PolyOverZ::from_str("4  2 0 3 -1").unwrap();
420        let b = PolynomialRingZq::from((&poly_2, &modulus));
421        let c = a + &b;
422        assert_eq!(
423            c,
424            PolynomialRingZq::from((&PolyOverZ::from_str("3  1 0 4").unwrap(), &modulus))
425        );
426    }
427
428    /// Testing addition for large [`PolynomialRingZq`]
429    #[test]
430    fn add_large_numbers() {
431        let modulus = ModulusPolynomialRingZq::from_str(&format!(
432            "4  {} 0 0 1 mod {}",
433            u64::MAX,
434            u64::MAX - 58
435        ))
436        .unwrap();
437
438        let poly_1 = PolyOverZ::from_str(&format!("4  {} 0 1 {}", u64::MAX, i64::MIN)).unwrap();
439        let a = PolynomialRingZq::from((&poly_1, &modulus));
440
441        let poly_2 = PolyOverZ::from_str(&format!("4  {} 0 -1 {}", i64::MAX, i64::MAX)).unwrap();
442        let b = PolynomialRingZq::from((&poly_2, &modulus));
443
444        let c = a + b;
445        assert_eq!(
446            c,
447            PolynomialRingZq::from((
448                &PolyOverZ::from_str(&format!("4  {} 0 0 {}", (u64::MAX - 1) / 2 + 58, -1))
449                    .unwrap(),
450                &modulus
451            ))
452        );
453    }
454
455    /// Testing addition for [`PolynomialRingZq`] with different moduli does not work
456    #[test]
457    #[should_panic]
458    fn add_mismatching_modulus() {
459        let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
460        let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
461        let a = PolynomialRingZq::from((&poly_1, &modulus));
462        let modulus = ModulusPolynomialRingZq::from_str("4  2 0 0 1 mod 17").unwrap();
463        let poly_2 = PolyOverZ::from_str("4  2 0 3 1").unwrap();
464        let b = PolynomialRingZq::from((&poly_2, &modulus));
465        let _ = a + b;
466    }
467
468    /// Testing whether add_safe throws an error for mismatching moduli
469    #[test]
470    fn add_safe_is_err() {
471        let modulus = ModulusPolynomialRingZq::from_str("4  1 0 0 1 mod 17").unwrap();
472        let poly_1 = PolyOverZ::from_str("4  -1 0 1 1").unwrap();
473        let a = PolynomialRingZq::from((&poly_1, &modulus));
474        let modulus = ModulusPolynomialRingZq::from_str("4  2 0 0 1 mod 17").unwrap();
475        let poly_2 = PolyOverZ::from_str("4  2 0 3 1").unwrap();
476        let b = PolynomialRingZq::from((&poly_2, &modulus));
477
478        assert!(&a.add_safe(&b).is_err());
479    }
480}
481
482#[cfg(test)]
483mod test_add_poly_over_z {
484    use super::PolynomialRingZq;
485    use crate::integer::PolyOverZ;
486    use std::str::FromStr;
487
488    /// Checks if polynomial addition works fine for both borrowed
489    #[test]
490    fn borrowed_correctness() {
491        let poly_1 =
492            PolynomialRingZq::from_str(&format!("2  2 {} / 4  1 2 3 1 mod {}", i64::MAX, u64::MAX))
493                .unwrap();
494        let poly_2 = PolynomialRingZq::from_str(&format!(
495            "2  3 {} / 4  1 2 3 1 mod {}",
496            i64::MAX as u64 + 2,
497            u64::MAX
498        ))
499        .unwrap();
500        let poly = PolyOverZ::from_str("2  1 2").unwrap();
501
502        let poly_1 = &poly_1 + &poly;
503
504        assert_eq!(poly_2, poly_1);
505    }
506
507    /// Checks if addition works fine for different types
508    #[test]
509    fn availability() {
510        let poly = PolynomialRingZq::from_str("3  1 2 3 / 4  1 2 3 1 mod 17").unwrap();
511        let z = PolyOverZ::from(2);
512
513        _ = poly.clone() + z.clone();
514        _ = z.clone() + poly.clone();
515        _ = &poly + &z;
516        _ = &z + &poly;
517        _ = &poly + z.clone();
518        _ = z.clone() + &poly;
519        _ = &z + poly.clone();
520        _ = poly.clone() + &z;
521    }
522}
523
524#[cfg(test)]
525mod test_add_poly_over_zq {
526    use super::PolynomialRingZq;
527    use crate::integer_mod_q::PolyOverZq;
528    use std::str::FromStr;
529
530    /// Checks if polynomial addition works fine for both borrowed
531    #[test]
532    fn borrowed_correctness() {
533        let poly_1 =
534            PolynomialRingZq::from_str(&format!("2  2 {} / 4  1 2 3 1 mod {}", i64::MAX, u64::MAX))
535                .unwrap();
536        let poly_2 = PolynomialRingZq::from_str(&format!(
537            "2  3 {} / 4  1 2 3 1 mod {}",
538            i64::MAX as u64 + 1,
539            u64::MAX
540        ))
541        .unwrap();
542        let poly = PolyOverZq::from_str(&format!("2  1 1 mod {}", u64::MAX)).unwrap();
543
544        let poly_1 = &poly_1 + &poly;
545
546        assert_eq!(poly_2, poly_1);
547    }
548
549    /// Checks if addition works fine for different types
550    #[test]
551    fn availability() {
552        let poly = PolynomialRingZq::from_str("3  1 2 3 / 4  1 2 3 1 mod 17").unwrap();
553        let zq = PolyOverZq::from((2, 17));
554
555        _ = poly.clone() + zq.clone();
556        _ = zq.clone() + poly.clone();
557        _ = &poly + &zq;
558        _ = &zq + &poly;
559        _ = &poly + zq.clone();
560        _ = zq.clone() + &poly;
561        _ = &zq + poly.clone();
562        _ = poly.clone() + &zq;
563    }
564
565    /// Checks if addition panics if the moduli mismatch
566    #[test]
567    #[should_panic]
568    fn different_moduli_panic() {
569        let poly = PolynomialRingZq::from_str("3  1 2 3 / 4  1 2 3 1 mod 17").unwrap();
570        let zq = PolyOverZq::from((2, 16));
571
572        _ = &poly + &zq;
573    }
574}