use super::super::MatZ;
use crate::{
error::MathError,
integer::{Z, fmpz_helpers::find_max_abs},
rational::Q,
traits::MatrixDimensions,
};
use flint_sys::fmpz::fmpz_addmul;
impl MatZ {
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 entries = self.collect_entries();
let mut result = Z::ZERO;
for entry in entries {
unsafe { fmpz_addmul(&mut result.value, &entry, &entry) }
}
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 entries = self.collect_entries();
Ok(find_max_abs(&entries))
}
}
#[cfg(test)]
mod test_norm_eucl_sqrd {
use super::{MatZ, Z};
use std::str::FromStr;
#[test]
fn row_vector_small_entries() {
let vec_1 = MatZ::from_str("[[1]]").unwrap();
let vec_2 = MatZ::from_str("[[1, 10, 100]]").unwrap();
let vec_3 = MatZ::from_str("[[1, 10, 100, 1000]]").unwrap();
assert_eq!(vec_1.norm_eucl_sqrd().unwrap(), Z::ONE);
assert_eq!(vec_2.norm_eucl_sqrd().unwrap(), Z::from(10101));
assert_eq!(vec_3.norm_eucl_sqrd().unwrap(), Z::from(1010101));
}
#[test]
fn row_vector_large_entries() {
let vec = MatZ::from_str(&format!("[[{}, {}, 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(4);
assert_eq!(vec.norm_eucl_sqrd().unwrap(), cmp);
}
#[test]
fn column_vector_small_entries() {
let vec_1 = MatZ::from_str("[[1],[10],[100]]").unwrap();
let vec_2 = MatZ::from_str("[[1],[10],[100],[1000]]").unwrap();
assert_eq!(vec_1.norm_eucl_sqrd().unwrap(), Z::from(10101));
assert_eq!(vec_2.norm_eucl_sqrd().unwrap(), Z::from(1010101));
}
#[test]
fn column_vector_large_entries() {
let vec = MatZ::from_str(&format!("[[{}],[{}],[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(4);
assert_eq!(vec.norm_eucl_sqrd().unwrap(), cmp);
}
#[test]
fn non_vector_yield_error() {
let mat = MatZ::from_str("[[1, 1],[10, 2]]").unwrap();
assert!(mat.norm_eucl_sqrd().is_err());
}
}
#[cfg(test)]
mod test_norm_infty {
use super::{MatZ, Z};
use std::str::FromStr;
#[test]
fn row_vector_small_entries() {
let vec_1 = MatZ::from_str("[[1]]").unwrap();
let vec_2 = MatZ::from_str("[[1, 10, 100]]").unwrap();
let vec_3 = MatZ::from_str("[[1, 10, 100, 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 = MatZ::from_str(&format!("[[{}, {}, 2]]", i64::MAX, i64::MIN)).unwrap();
let cmp = Z::from(-1) * Z::from(i64::MIN);
assert_eq!(vec.norm_infty().unwrap(), cmp);
}
#[test]
fn column_vector_small_entries() {
let vec_1 = MatZ::from_str("[[1],[10],[100]]").unwrap();
let vec_2 = MatZ::from_str("[[1],[10],[100],[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 = MatZ::from_str(&format!("[[{}],[{}],[2]]", i64::MAX, i64::MIN)).unwrap();
let cmp = Z::from(-1) * Z::from(i64::MIN);
assert_eq!(vec.norm_infty().unwrap(), cmp);
}
#[test]
fn non_vector_yield_error() {
let mat = MatZ::from_str("[[1, 1],[10, 2]]").unwrap();
assert!(mat.norm_infty().is_err());
}
}