use super::super::MatZq;
use crate::{
error::MathError, integer::Z, integer_mod_q::fmpz_mod_helpers::length, rational::Q,
traits::MatrixDimensions,
};
use flint_sys::fmpz::fmpz_addmul;
impl MatZq {
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 entry_lengths = self.collect_lengths();
let mut result = Z::ZERO;
for entry in entry_lengths {
unsafe { fmpz_addmul(&mut result.value, &entry.value, &entry.value) }
}
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 fmpz_entries = self.collect_entries();
let modulus = self.matrix.mod_[0];
let mut max = Z::ZERO;
for fmpz_entry in fmpz_entries {
let length = length(&fmpz_entry, &modulus);
if length > max {
max = length;
}
}
Ok(max)
}
}
#[cfg(test)]
mod test_norm_eucl_sqrd {
use super::{MatZq, Z};
use std::str::FromStr;
#[test]
fn row_vector_small_entries() {
let vec_1 = MatZq::from_str("[[1]] mod 10").unwrap();
let vec_2 = MatZq::from_str("[[1, 10, 100]] mod 10").unwrap();
let vec_3 = MatZq::from_str("[[1, 10, 100, 1000]] mod 10000").unwrap();
assert_eq!(vec_1.norm_eucl_sqrd().unwrap(), Z::ONE);
assert_eq!(vec_2.norm_eucl_sqrd().unwrap(), Z::ONE);
assert_eq!(vec_3.norm_eucl_sqrd().unwrap(), Z::from(1010101));
}
#[test]
fn row_vector_large_entries() {
let vec = MatZq::from_str(&format!(
"[[{}, {}, 2]] mod {}",
i64::MAX,
i64::MIN,
u64::MAX
))
.unwrap();
let max = Z::from(i64::MAX);
let cmp = Z::from(2) * &max * &max + Z::from(4);
assert_eq!(vec.norm_eucl_sqrd().unwrap(), cmp);
}
#[test]
fn column_vector_small_entries() {
let vec_1 = MatZq::from_str("[[1],[10],[100]] mod 10").unwrap();
let vec_2 = MatZq::from_str("[[1],[10],[100],[1000]] mod 10000").unwrap();
assert_eq!(vec_1.norm_eucl_sqrd().unwrap(), Z::ONE);
assert_eq!(vec_2.norm_eucl_sqrd().unwrap(), Z::from(1010101));
}
#[test]
fn column_vector_large_entries() {
let vec = MatZq::from_str(&format!(
"[[{}],[{}],[2]] mod {}",
i64::MAX,
i64::MIN,
u64::MAX
))
.unwrap();
let max = Z::from(i64::MAX);
let cmp = Z::from(2) * &max * &max + Z::from(4);
assert_eq!(vec.norm_eucl_sqrd().unwrap(), cmp);
}
#[test]
fn non_vector_yield_error() {
let mat = MatZq::from_str("[[1, 1],[10, 2]] mod 3").unwrap();
assert!(mat.norm_eucl_sqrd().is_err());
}
}
#[cfg(test)]
mod test_norm_infty {
use super::{MatZq, Z};
use std::str::FromStr;
#[test]
fn row_vector_small_entries() {
let vec_1 = MatZq::from_str("[[6]] mod 10").unwrap();
let vec_2 = MatZq::from_str("[[1, 10, 100]] mod 1000").unwrap();
let vec_3 = MatZq::from_str("[[1, 10, 100, 1000]] mod 1000").unwrap();
assert_eq!(vec_1.norm_infty().unwrap(), Z::from(4));
assert_eq!(vec_2.norm_infty().unwrap(), Z::from(100));
assert_eq!(vec_3.norm_infty().unwrap(), Z::from(100));
}
#[test]
fn row_vector_large_entries() {
let vec = MatZq::from_str(&format!(
"[[{}, {}, 2]] mod {}",
i64::MAX,
i64::MIN,
u64::MAX
))
.unwrap();
let cmp = Z::from(i64::MAX);
assert_eq!(vec.norm_infty().unwrap(), cmp);
}
#[test]
fn column_vector_small_entries() {
let vec_1 = MatZq::from_str("[[1],[10],[100]] mod 50").unwrap();
let vec_2 = MatZq::from_str("[[1],[10],[100],[1000]] mod 1999").unwrap();
assert_eq!(vec_1.norm_infty().unwrap(), Z::from(10));
assert_eq!(vec_2.norm_infty().unwrap(), Z::from(999));
}
#[test]
fn column_vector_large_entries() {
let vec = MatZq::from_str(&format!(
"[[{}],[{}],[2]] mod {}",
i64::MAX,
i64::MIN,
u64::MAX
))
.unwrap();
let cmp = Z::from(i64::MAX);
assert_eq!(vec.norm_infty().unwrap(), cmp);
}
#[test]
fn non_vector_yield_error() {
let mat = MatZq::from_str("[[1, 1],[10, 2]] mod 3").unwrap();
assert!(mat.norm_infty().is_err());
}
}