qfall_math/integer/poly_over_z/
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::{PolyOverZ, Z},
14    traits::{GetCoefficient, Pow},
15};
16use std::cmp::max;
17
18impl PolyOverZ {
19    /// Returns the squared Euclidean norm or squared 2-norm of the given polynomial.
20    /// The squared Euclidean norm for a polynomial is obtained by treating the coefficients
21    /// of the polynomial as a vector and then applying the standard squared Euclidean norm.
22    ///
23    /// # Examples
24    /// ```
25    /// use qfall_math::integer::{PolyOverZ, Z};
26    /// use std::str::FromStr;
27    ///
28    /// let poly = PolyOverZ::from_str("3  1 2 3").unwrap();
29    ///
30    /// let sqrd_2_norm = poly.norm_eucl_sqrd();
31    ///
32    /// // 1*1 + 2*2 + 3*3 = 14
33    /// assert_eq!(Z::from(14), sqrd_2_norm);
34    /// ```
35    pub fn norm_eucl_sqrd(&self) -> Z {
36        let mut res = Z::ZERO;
37
38        for i in 0..=self.get_degree() {
39            let coeff = unsafe { self.get_coeff_unchecked(i) };
40            res += coeff.pow(2).unwrap();
41        }
42        res
43    }
44
45    /// Returns the infinity norm or the maximal absolute value of a
46    /// coefficient of the given polynomial.
47    /// The infinity norm for a polynomial is obtained by treating the coefficients
48    /// of the polynomial as a vector and then applying the standard infinity norm.
49    ///
50    /// # Examples
51    /// ```
52    /// use qfall_math::integer::{PolyOverZ, Z};
53    /// use std::str::FromStr;
54    ///
55    /// let poly = PolyOverZ::from_str("3  1 2 3").unwrap();
56    ///
57    /// let infty_norm = poly.norm_infty();
58    ///
59    /// // max coefficient is 3
60    /// assert_eq!(Z::from(3), infty_norm);
61    /// ```
62    pub fn norm_infty(&self) -> Z {
63        let mut res = Z::ZERO;
64        for i in 0..=self.get_degree() {
65            if res < unsafe { self.get_coeff_unchecked(i).abs() } {
66                res = max(res, unsafe { self.get_coeff_unchecked(i).abs() });
67            }
68        }
69        res
70    }
71}
72
73#[cfg(test)]
74mod test_norm_eucl_sqrd {
75    use super::{PolyOverZ, Z};
76    use std::str::FromStr;
77
78    /// Check whether the squared euclidean norm for polynomials
79    /// with small coefficients is calculated correctly
80    #[test]
81    fn poly_small_coefficient() {
82        let poly_1 = PolyOverZ::default();
83        let poly_2 = PolyOverZ::from_str("3  1 2 3").unwrap();
84        let poly_3 = PolyOverZ::from_str("3  1 20 90").unwrap();
85
86        assert_eq!(poly_1.norm_eucl_sqrd(), Z::ZERO);
87        assert_eq!(poly_2.norm_eucl_sqrd(), Z::from(14));
88        assert_eq!(poly_3.norm_eucl_sqrd(), Z::from(8501));
89    }
90
91    /// Check whether the squared euclidean norm for polynomials
92    /// with small coefficients is calculated correctly
93    #[test]
94    fn poly_large_coefficient() {
95        let poly_1 = PolyOverZ::from(u64::MAX);
96        let poly_2 =
97            PolyOverZ::from_str(&format!("3  {} {} {}", u64::MAX, i64::MIN, i64::MAX)).unwrap();
98
99        assert_eq!(
100            poly_1.norm_eucl_sqrd(),
101            Z::from(u64::MAX) * Z::from(u64::MAX)
102        );
103        assert_eq!(
104            poly_2.norm_eucl_sqrd(),
105            Z::from(u64::MAX) * Z::from(u64::MAX)
106                + Z::from(i64::MAX) * Z::from(i64::MAX)
107                + Z::from(i64::MIN) * Z::from(i64::MIN)
108        );
109    }
110}
111
112#[cfg(test)]
113mod test_norm_infty {
114    use super::{PolyOverZ, Z};
115    use std::str::FromStr;
116
117    /// Check whether the infinity norm for polynomials
118    /// with small coefficients is calculated correctly
119    #[test]
120    fn poly_small_coefficient() {
121        let poly_1 = PolyOverZ::default();
122        let poly_2 = PolyOverZ::from_str("3  1 2 3").unwrap();
123        let poly_3 = PolyOverZ::from_str("3  1 2010 90").unwrap();
124
125        assert_eq!(poly_1.norm_infty(), Z::ZERO);
126        assert_eq!(poly_2.norm_infty(), Z::from(3));
127        assert_eq!(poly_3.norm_infty(), Z::from(2010));
128    }
129
130    /// Check whether the infinity norm for polynomials
131    /// with small coefficients is calculated correctly
132    #[test]
133    fn poly_large_coefficient() {
134        let poly_1 = PolyOverZ::from(u64::MAX);
135        let poly_2 =
136            PolyOverZ::from_str(&format!("3  {} {} {}", u64::MAX, i64::MIN, i64::MAX)).unwrap();
137
138        assert_eq!(poly_1.norm_infty(), Z::from(u64::MAX));
139        assert_eq!(poly_2.norm_infty(), Z::from(u64::MAX));
140    }
141}