1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright © 2023 Phil Milewski
//
// This file is part of qFALL-math.
//
// qFALL-math is free software: you can redistribute it and/or modify it under
// the terms of the Mozilla Public License Version 2.0 as published by the
// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
//! This module includes functionality to compute several norms
//! defined on polynomials.
use crate::{
rational::{PolyOverQ, Q},
traits::{GetCoefficient, Pow},
};
use std::cmp::max;
impl PolyOverQ {
/// Returns the squared Euclidean norm or squared 2-norm of the given polynomial.
/// The squared Euclidean norm for a polynomial is obtained by treating the coefficients
/// of the polynomial as a vector and then applying the standard squared Euclidean norm.
///
/// # Examples
/// ```
/// use qfall_math::rational::{PolyOverQ, Q};
/// use std::str::FromStr;
///
/// let poly = PolyOverQ::from_str("3 1/7 2/7 3/7").unwrap();
///
/// let sqrd_2_norm = poly.norm_eucl_sqrd();
///
/// // (1*1 + 2*2 + 3*3)/49 = 14/49 = 2/7
/// assert_eq!(Q::from((2, 7)), sqrd_2_norm);
/// ```
pub fn norm_eucl_sqrd(&self) -> Q {
let mut res = Q::ZERO;
for i in 0..=self.get_degree() {
let coeff = unsafe { self.get_coeff_unchecked(i) };
res += coeff.pow(2).unwrap();
}
res
}
}
impl PolyOverQ {
/// Returns the infinity norm or the maximal absolute value of a
/// coefficient of the given polynomial.
/// The infinity norm for a polynomial is obtained by treating the coefficients
/// of the polynomial as a vector and then applying the standard infinity norm.
///
/// # Examples
/// ```
/// use qfall_math::rational::{PolyOverQ, Q};
/// use std::str::FromStr;
///
/// let poly = PolyOverQ::from_str("3 1/7 2/7 3/7").unwrap();
///
/// let infty_norm = poly.norm_infty();
///
/// // max coefficient is 3/7
/// assert_eq!(Q::from((3, 7)), infty_norm);
/// ```
pub fn norm_infty(&self) -> Q {
let mut res = Q::ZERO;
for i in 0..=self.get_degree() {
res = max(res, unsafe { self.get_coeff_unchecked(i).abs() });
}
res
}
}
#[cfg(test)]
mod test_norm_eucl_sqrd {
use super::{PolyOverQ, Q};
use std::str::FromStr;
/// Check whether the squared euclidean norm for polynomials
/// with small coefficients is calculated correctly
#[test]
fn poly_small_coefficient() {
let poly_1 = PolyOverQ::default();
let poly_2 = PolyOverQ::from_str("3 1/7 2/7 3/7").unwrap();
let poly_3 = PolyOverQ::from_str("3 1/8 2010/19 90/29").unwrap();
assert_eq!(poly_1.norm_eucl_sqrd(), Q::ZERO);
assert_eq!(poly_2.norm_eucl_sqrd(), Q::from((2, 7)));
assert_eq!(
poly_3.norm_eucl_sqrd(),
Q::from((1, 64)) + Q::from((2010, 19)) * Q::from((2010, 19)) + Q::from((8100, 841))
);
}
/// Check whether the squared euclidean norm for polynomials
/// with small coefficients is calculated correctly
#[test]
fn poly_large_coefficient() {
let poly_1 = PolyOverQ::from_str(&format!("1 {}", u64::MAX)).unwrap();
let poly_2 =
PolyOverQ::from_str(&format!("3 {} {} 1/{}", u64::MAX, i64::MIN, i64::MAX)).unwrap();
assert_eq!(
poly_1.norm_eucl_sqrd(),
Q::from(u64::MAX) * Q::from(u64::MAX)
);
assert_eq!(
poly_2.norm_eucl_sqrd(),
Q::from(u64::MAX) * Q::from(u64::MAX)
+ Q::from(i64::MIN) * Q::from(i64::MIN)
+ Q::from((1, i64::MAX)) * Q::from((1, i64::MAX))
);
}
}
#[cfg(test)]
mod test_norm_infty {
use super::{PolyOverQ, Q};
use std::str::FromStr;
/// Check whether the infinity norm for polynomials
/// with small coefficients is calculated correctly
#[test]
fn poly_small_coefficient() {
let poly_1 = PolyOverQ::default();
let poly_2 = PolyOverQ::from_str("3 1/7 2/7 3/7").unwrap();
let poly_3 = PolyOverQ::from_str("3 1/8 2010/19 90/29").unwrap();
assert_eq!(poly_1.norm_infty(), Q::ZERO);
assert_eq!(poly_2.norm_infty(), Q::from((3, 7)));
assert_eq!(poly_3.norm_infty(), Q::from((2010, 19)));
}
/// Check whether the infinity norm for polynomials
/// with small coefficients is calculated correctly
#[test]
fn poly_large_coefficient() {
let poly_1 = PolyOverQ::from_str(&format!("1 {}", u64::MAX)).unwrap();
let poly_2 =
PolyOverQ::from_str(&format!("3 1/{} {}/7 {}", u64::MAX, i64::MIN, i64::MAX)).unwrap();
assert_eq!(poly_1.norm_infty(), Q::from(u64::MAX));
assert_eq!(poly_2.norm_infty(), Q::from(i64::MAX));
}
}