qfall_math/integer_mod_q/poly_over_zq/norm.rs
1// Copyright © 2023 Phil Milewski
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 includes functionality to compute several norms
10//! defined on polynomials.
11
12use crate::{
13 integer::Z,
14 integer_mod_q::{PolyOverZq, fmpz_mod_helpers::length},
15 traits::{GetCoefficient, Pow},
16};
17use std::cmp::max;
18
19impl PolyOverZq {
20 /// Returns the squared Euclidean norm or squared 2-norm of the given polynomial.
21 /// The squared Euclidean norm for a polynomial is obtained by treating the coefficients
22 /// of the polynomial as a vector and then applying the standard squared Euclidean norm.
23 ///
24 /// Each length of an entry in this vector is defined as the shortest distance
25 /// to the next zero representative modulo q.
26 ///
27 /// # Examples
28 /// ```
29 /// use qfall_math::{integer::Z, integer_mod_q::PolyOverZq};
30 /// use std::str::FromStr;
31 ///
32 /// let poly = PolyOverZq::from_str("3 1 2 3 mod 11").unwrap();
33 ///
34 /// let sqrd_2_norm = poly.norm_eucl_sqrd();
35 ///
36 /// // 1*1 + 2*2 + 3*3 = 14
37 /// assert_eq!(Z::from(14), sqrd_2_norm);
38 /// ```
39 pub fn norm_eucl_sqrd(&self) -> Z {
40 let mut res = Z::ZERO;
41 for i in 0..=self.get_degree() {
42 let coeff: Z = unsafe { self.get_coeff_unchecked(i) };
43 res += length(&coeff.value, &self.modulus.get_fmpz_mod_ctx_struct().n[0])
44 .pow(2)
45 .unwrap();
46 }
47 res
48 }
49
50 /// Returns the infinity norm or the maximal absolute value of a
51 /// coefficient of the given polynomial.
52 /// The infinity norm for a polynomial is obtained by treating the coefficients
53 /// of the polynomial as a vector and then applying the standard infinity norm.
54 ///
55 /// Each length of an entry in this vector is defined as the shortest distance
56 /// to the next zero representative modulo q.
57 ///
58 /// # Examples
59 /// ```
60 /// use qfall_math::{integer::Z, integer_mod_q::PolyOverZq};
61 /// use std::str::FromStr;
62 ///
63 /// let poly = PolyOverZq::from_str("3 1 2 4 mod 7").unwrap();
64 ///
65 /// let infty_norm = poly.norm_infty();
66 ///
67 /// // max coefficient is 4 = -3
68 /// assert_eq!(Z::from(3), infty_norm);
69 /// ```
70 pub fn norm_infty(&self) -> Z {
71 let mut res = Z::ZERO;
72
73 for i in 0..=self.get_degree() {
74 let coeff: Z = unsafe { self.get_coeff_unchecked(i) };
75 let len = length(&coeff.value, &self.modulus.get_fmpz_mod_ctx_struct().n[0]);
76 res = max(res, len);
77 }
78 res
79 }
80}
81
82#[cfg(test)]
83mod test_norm_eucl_sqrd {
84 use super::{PolyOverZq, Z};
85 use std::str::FromStr;
86
87 /// Check whether the squared euclidean norm for polynomials
88 /// with small coefficients is calculated correctly
89 #[test]
90 fn poly_small_coefficient() {
91 let poly_1 = PolyOverZq::from_str("0 mod 11").unwrap();
92 let poly_2 = PolyOverZq::from_str("3 1 2 3 mod 11").unwrap();
93 let poly_3 = PolyOverZq::from_str("3 1 20 194 mod 195").unwrap();
94
95 assert_eq!(poly_1.norm_eucl_sqrd(), Z::ZERO);
96 assert_eq!(poly_2.norm_eucl_sqrd(), Z::from(14));
97 assert_eq!(poly_3.norm_eucl_sqrd(), Z::from(402));
98 }
99
100 /// Check whether the squared euclidean norm for polynomials
101 /// with small coefficients is calculated correctly
102 #[test]
103 fn poly_large_coefficient() {
104 let poly_1 = PolyOverZq::from_str(&format!("1 {} mod {}", u64::MAX, u128::MAX)).unwrap();
105 let poly_2 = PolyOverZq::from_str(&format!(
106 "3 {} {} {} mod {}",
107 u64::MAX,
108 i64::MIN,
109 i64::MAX,
110 u64::MAX - 58
111 ))
112 .unwrap();
113
114 assert_eq!(
115 poly_1.norm_eucl_sqrd(),
116 Z::from(u64::MAX) * Z::from(u64::MAX)
117 );
118 assert_eq!(
119 poly_2.norm_eucl_sqrd(),
120 Z::from(58) * Z::from(58)
121 + Z::from((u64::MAX - 1) / 2 - 57) * Z::from((u64::MAX - 1) / 2 - 57)
122 + Z::from((u64::MAX - 1) / 2 - 58) * Z::from((u64::MAX - 1) / 2 - 58)
123 );
124 }
125}
126
127#[cfg(test)]
128mod test_norm_infty {
129 use super::{PolyOverZq, Z};
130 use std::str::FromStr;
131
132 /// Check whether the infinity norm for polynomials
133 /// with small coefficients is calculated correctly
134 #[test]
135 fn poly_small_coefficient() {
136 let poly_1 = PolyOverZq::from_str("0 mod 3").unwrap();
137 let poly_2 = PolyOverZq::from_str("3 1 2 3 mod 5").unwrap();
138 let poly_3 = PolyOverZq::from_str("3 1 2010 90 mod 100").unwrap();
139
140 assert_eq!(poly_1.norm_infty(), Z::ZERO);
141 assert_eq!(poly_2.norm_infty(), Z::from(2));
142 assert_eq!(poly_3.norm_infty(), Z::from(10));
143 }
144
145 /// Check whether the infinity norm for polynomials
146 /// with small coefficients is calculated correctly
147 #[test]
148 fn poly_large_coefficient() {
149 let poly_1 = PolyOverZq::from_str(&format!("1 {} mod {}", u64::MAX, u128::MAX)).unwrap();
150 let poly_2 = PolyOverZq::from_str(&format!(
151 "3 {} {} {} mod {}",
152 u64::MAX,
153 i64::MIN,
154 i64::MAX,
155 u64::MAX - 58
156 ))
157 .unwrap();
158
159 assert_eq!(poly_1.norm_infty(), Z::from(u64::MAX));
160 assert_eq!(poly_2.norm_infty(), Z::from((u64::MAX - 1) / 2 - 57));
161 }
162}