qfall_math/integer_mod_q/mat_ntt_polynomial_ring_zq/
cmp.rs

1// Copyright © 2025 Niklas Siemer
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//! This module contains implementations for comparison of [`MatPolynomialRingZq`].
10
11use super::MatNTTPolynomialRingZq;
12use crate::{
13    error::MathError,
14    integer::{MatPolyOverZ, MatZ, PolyOverZ, Z},
15    integer_mod_q::{MatPolynomialRingZq, MatZq, PolyOverZq, PolynomialRingZq, Zq},
16    macros::compare_base::{
17        compare_base_default, compare_base_get_mod, compare_base_get_mod_get_q, compare_base_impl,
18    },
19    traits::CompareBase,
20};
21
22compare_base_get_mod!(MatNTTPolynomialRingZq for MatNTTPolynomialRingZq MatPolynomialRingZq PolynomialRingZq);
23compare_base_get_mod_get_q!(MatNTTPolynomialRingZq for Zq MatZq PolyOverZq);
24
25compare_base_default!(MatNTTPolynomialRingZq for MatZ PolyOverZ MatPolyOverZ);
26impl<Integer: Into<Z>> CompareBase<Integer> for MatNTTPolynomialRingZq {}
27
28/// Test that the [`CompareBase`] trait uses an actual implementation.
29#[cfg(test)]
30mod test_compare_base {
31    use crate::{
32        integer::{MatPolyOverZ, MatZ, PolyOverZ, Z},
33        integer_mod_q::{
34            MatPolynomialRingZq, MatZq, ModulusPolynomialRingZq, PolyOverZq, PolynomialRingZq, Zq,
35        },
36        traits::CompareBase,
37    };
38    use std::str::FromStr;
39
40    /// Ensures that the [`CompareBase`] is available for all types it would be checked against
41    /// where no comparison is needed
42    #[test]
43    fn availability_without_comparisons() {
44        let mut modulus = ModulusPolynomialRingZq::from_str("3  1 0 1 mod 17").unwrap();
45        modulus.set_ntt_unchecked(4);
46        let one_1 = MatPolynomialRingZq::identity(10, 7, &modulus);
47        let one_1 = one_1.ntt();
48
49        assert!(one_1.compare_base(&MatZ::new(1, 1)));
50        assert!(one_1.compare_base(&MatPolyOverZ::new(1, 1)));
51        assert!(one_1.compare_base(&Z::ONE));
52        assert!(one_1.compare_base(&PolyOverZ::from_str("1  3").unwrap()));
53        assert!(one_1.compare_base(&0_i8));
54        assert!(one_1.compare_base(&0_i16));
55        assert!(one_1.compare_base(&0_i32));
56        assert!(one_1.compare_base(&0_i64));
57        assert!(one_1.compare_base(&0_u8));
58        assert!(one_1.compare_base(&0_u16));
59        assert!(one_1.compare_base(&0_u32));
60        assert!(one_1.compare_base(&0_u64));
61
62        assert!(one_1.call_compare_base_error(&MatZ::new(1, 1)).is_none());
63        assert!(
64            one_1
65                .call_compare_base_error(&MatPolyOverZ::new(1, 1))
66                .is_none()
67        );
68        assert!(one_1.call_compare_base_error(&Z::ONE).is_none());
69        assert!(
70            one_1
71                .call_compare_base_error(&PolyOverZ::from_str("1  3").unwrap())
72                .is_none()
73        );
74        assert!(one_1.call_compare_base_error(&0_i8).is_none());
75        assert!(one_1.call_compare_base_error(&0_i16).is_none());
76        assert!(one_1.call_compare_base_error(&0_i32).is_none());
77        assert!(one_1.call_compare_base_error(&0_i64).is_none());
78        assert!(one_1.call_compare_base_error(&0_u8).is_none());
79        assert!(one_1.call_compare_base_error(&0_u16).is_none());
80        assert!(one_1.call_compare_base_error(&0_u32).is_none());
81        assert!(one_1.call_compare_base_error(&0_u64).is_none());
82    }
83
84    /// Ensures that the [`CompareBase`] is available for all types it would be checked against
85    /// where comparison is needed
86    #[test]
87    fn availability_with_comparisons() {
88        let mut modulus = ModulusPolynomialRingZq::from_str("3  1 0 1 mod 17").unwrap();
89        modulus.set_ntt_unchecked(4);
90        let modulus_other = ModulusPolynomialRingZq::from_str("3  1 0 1 mod 18").unwrap();
91        let one_1 = MatPolynomialRingZq::identity(10, 7, &modulus);
92        let one_1 = one_1.ntt();
93
94        assert!(one_1.compare_base(&one_1));
95        assert!(!one_1.compare_base(&MatPolynomialRingZq::identity(10, 7, &modulus_other)));
96        assert!(one_1.compare_base(&Zq::from((3, 17))));
97        assert!(!one_1.compare_base(&Zq::from((3, 18))));
98        assert!(one_1.compare_base(&PolyOverZq::from_str("1  3 mod 17").unwrap()));
99        assert!(!one_1.compare_base(&PolyOverZq::from_str("1  3 mod 18").unwrap()));
100        assert!(one_1.compare_base(&MatZq::new(1, 1, 17)));
101        assert!(!one_1.compare_base(&MatZq::new(1, 1, 18)));
102        assert!(one_1.compare_base(&PolynomialRingZq::from(&modulus)));
103        assert!(!one_1.compare_base(&PolynomialRingZq::from(&modulus_other)));
104
105        assert!(
106            one_1
107                .call_compare_base_error(&MatPolynomialRingZq::identity(10, 7, &modulus_other))
108                .is_some()
109        );
110        assert!(one_1.call_compare_base_error(&Zq::from((3, 18))).is_some());
111        assert!(
112            one_1
113                .call_compare_base_error(&PolyOverZq::from_str("1  3 mod 18").unwrap())
114                .is_some()
115        );
116        assert!(
117            one_1
118                .call_compare_base_error(&MatZq::new(1, 1, 18))
119                .is_some()
120        );
121        assert!(
122            one_1
123                .call_compare_base_error(&PolynomialRingZq::from(&modulus_other))
124                .is_some()
125        );
126    }
127}