use super::super::MatPolyOverZ;
use crate::{
error::MathError,
integer::Z,
rational::Q,
traits::{MatrixDimensions, MatrixGetEntry},
};
impl MatPolyOverZ {
pub fn norm_eucl_sqrd(&self) -> Result<Z, MathError> {
if !self.is_vector() {
return Err(MathError::VectorFunctionCalledOnNonVector(
String::from("norm_eucl_sqrd"),
self.get_num_rows(),
self.get_num_columns(),
));
}
let mut result = Z::ZERO;
for row in 0..self.get_num_rows() {
for column in 0..self.get_num_columns() {
result += unsafe { self.get_entry_unchecked(row, column) }.norm_eucl_sqrd();
}
}
Ok(result)
}
pub fn norm_eucl(&self) -> Result<Q, MathError> {
Ok(self.norm_eucl_sqrd()?.sqrt())
}
pub fn norm_infty(&self) -> Result<Z, MathError> {
if !self.is_vector() {
return Err(MathError::VectorFunctionCalledOnNonVector(
String::from("norm_infty"),
self.get_num_rows(),
self.get_num_columns(),
));
}
let mut result = Z::ZERO;
for row in 0..self.get_num_rows() {
for column in 0..self.get_num_columns() {
let entry_norm = unsafe { self.get_entry_unchecked(row, column) }
.norm_infty()
.abs();
if result < entry_norm {
result = entry_norm;
}
}
}
Ok(result)
}
}
#[cfg(test)]
mod test_norm_eucl_sqrd {
use crate::integer::{MatPolyOverZ, Z};
use std::str::FromStr;
#[test]
fn row_vector_small_entries() {
let vec_1 = MatPolyOverZ::from_str("[[1 1]]").unwrap();
let vec_2 = MatPolyOverZ::from_str("[[1 1, 2 10 3, 3 1 2 100]]").unwrap();
let vec_3 = MatPolyOverZ::from_str("[[2 1 3, 1 10, 3 1 2 100, 1 1000]]").unwrap();
assert_eq!(vec_1.norm_eucl_sqrd().unwrap(), Z::ONE);
assert_eq!(vec_2.norm_eucl_sqrd().unwrap(), Z::from(10115));
assert_eq!(vec_3.norm_eucl_sqrd().unwrap(), Z::from(1010115));
}
#[test]
fn row_vector_large_entries() {
let vec =
MatPolyOverZ::from_str(&format!("[[1 {}, 2 {} 2, 2 2 1]]", i64::MAX, i64::MIN))
.unwrap();
let max = Z::from(i64::MAX);
let min = Z::from(i64::MIN);
let cmp = &min * &min + &max * &max + Z::from(9);
assert_eq!(vec.norm_eucl_sqrd().unwrap(), cmp);
}
#[test]
fn column_vector_small_entries() {
let vec_1 = MatPolyOverZ::from_str("[[1 1],[2 10 3],[3 1 2 100]]").unwrap();
let vec_2 = MatPolyOverZ::from_str("[[2 1 3],[1 10],[3 1 2 100],[1 1000]]").unwrap();
assert_eq!(vec_1.norm_eucl_sqrd().unwrap(), Z::from(10115));
assert_eq!(vec_2.norm_eucl_sqrd().unwrap(), Z::from(1010115));
}
#[test]
fn column_vector_large_entries() {
let vec =
MatPolyOverZ::from_str(&format!("[[2 2 {}],[1 {}],[1 2]]", i64::MAX, i64::MIN))
.unwrap();
let max = Z::from(i64::MAX);
let min = Z::from(i64::MIN);
let cmp = &min * &min + &max * &max + Z::from(8);
assert_eq!(vec.norm_eucl_sqrd().unwrap(), cmp);
}
#[test]
fn non_vector_yield_error() {
let mat = MatPolyOverZ::from_str("[[2 1 20, 1 1],[1 10, 2 1 2]]").unwrap();
assert!(mat.norm_eucl_sqrd().is_err());
}
}
#[cfg(test)]
mod test_norm_infty {
use crate::integer::{MatPolyOverZ, Z};
use std::str::FromStr;
#[test]
fn row_vector_small_entries() {
let vec_1 = MatPolyOverZ::from_str("[[1 1]]").unwrap();
let vec_2 = MatPolyOverZ::from_str("[[1 1, 2 10 3, 3 1 2 100]]").unwrap();
let vec_3 = MatPolyOverZ::from_str("[[2 1 3, 1 10, 3 1 2 100, 1 1000]]").unwrap();
assert_eq!(vec_1.norm_infty().unwrap(), Z::ONE);
assert_eq!(vec_2.norm_infty().unwrap(), Z::from(100));
assert_eq!(vec_3.norm_infty().unwrap(), Z::from(1000));
}
#[test]
fn row_vector_large_entries() {
let vec =
MatPolyOverZ::from_str(&format!("[[1 {}, 2 {} 2, 2 2 1]]", i64::MAX, i64::MIN))
.unwrap();
assert_eq!(vec.norm_infty().unwrap(), Z::from(i64::MIN).abs());
}
#[test]
fn column_vector_small_entries() {
let vec_1 = MatPolyOverZ::from_str("[[1 1],[2 10 3],[3 1 2 100]]").unwrap();
let vec_2 = MatPolyOverZ::from_str("[[2 1 3],[1 10],[3 1 2 100],[1 1000]]").unwrap();
assert_eq!(vec_1.norm_infty().unwrap(), Z::from(100));
assert_eq!(vec_2.norm_infty().unwrap(), Z::from(1000));
}
#[test]
fn column_vector_large_entries() {
let vec =
MatPolyOverZ::from_str(&format!("[[2 2 {}],[1 {}],[1 2]]", i64::MAX, i64::MIN))
.unwrap();
assert_eq!(vec.norm_infty().unwrap(), Z::from(i64::MIN).abs());
}
#[test]
fn non_vector_yield_error() {
let mat = MatPolyOverZ::from_str("[[2 1 20, 1 1],[1 10, 2 1 2]]").unwrap();
assert!(mat.norm_infty().is_err());
}
}