use super::MatPolyOverZ;
use crate::{
error::MathError,
integer::PolyOverZ,
macros::for_others::implement_for_owned,
traits::{MatrixDimensions, MatrixSetEntry, MatrixSetSubmatrix, MatrixSwaps},
utils::index::{evaluate_index_for_vector, evaluate_indices_for_matrix},
};
use flint_sys::{
fmpz_poly::{fmpz_poly_set, fmpz_poly_swap},
fmpz_poly_mat::{
fmpz_poly_mat_entry, fmpz_poly_mat_set, fmpz_poly_mat_window_clear,
fmpz_poly_mat_window_init,
},
};
use std::{fmt::Display, mem::MaybeUninit};
impl MatrixSetEntry<&PolyOverZ> for MatPolyOverZ {
unsafe fn set_entry_unchecked(&mut self, row: i64, column: i64, value: &PolyOverZ) {
unsafe {
let entry = fmpz_poly_mat_entry(&self.matrix, row, column);
fmpz_poly_set(entry, &value.poly)
};
}
}
implement_for_owned!(PolyOverZ, MatPolyOverZ, MatrixSetEntry);
impl MatrixSetSubmatrix for MatPolyOverZ {
unsafe fn set_submatrix_unchecked(
&mut self,
row_self_start: i64,
col_self_start: i64,
row_self_end: i64,
col_self_end: i64,
other: &Self,
row_other_start: i64,
col_other_start: i64,
row_other_end: i64,
col_other_end: i64,
) {
{
let mut window_self = MaybeUninit::uninit();
unsafe {
fmpz_poly_mat_window_init(
window_self.as_mut_ptr(),
&self.matrix,
row_self_start,
col_self_start,
row_self_end,
col_self_end,
)
};
let mut window_other = MaybeUninit::uninit();
unsafe {
fmpz_poly_mat_window_init(
window_other.as_mut_ptr(),
&other.matrix,
row_other_start,
col_other_start,
row_other_end,
col_other_end,
)
};
unsafe {
fmpz_poly_mat_set(window_self.as_mut_ptr(), window_other.as_mut_ptr());
fmpz_poly_mat_window_clear(window_self.as_mut_ptr());
fmpz_poly_mat_window_clear(window_other.as_mut_ptr());
}
}
}
}
impl MatrixSwaps for MatPolyOverZ {
fn swap_entries(
&mut self,
row_0: impl TryInto<i64> + Display,
col_0: impl TryInto<i64> + Display,
row_1: impl TryInto<i64> + Display,
col_1: impl TryInto<i64> + Display,
) -> Result<(), MathError> {
let (row_0, col_0) = evaluate_indices_for_matrix(self, row_0, col_0)?;
let (row_1, col_1) = evaluate_indices_for_matrix(self, row_1, col_1)?;
unsafe {
fmpz_poly_swap(
fmpz_poly_mat_entry(&self.matrix, row_0, col_0),
fmpz_poly_mat_entry(&self.matrix, row_1, col_1),
)
};
Ok(())
}
fn swap_columns(
&mut self,
col_0: impl TryInto<i64> + Display,
col_1: impl TryInto<i64> + Display,
) -> Result<(), MathError> {
let num_cols = self.get_num_columns();
let col_0 = evaluate_index_for_vector(col_0, num_cols)?;
let col_1 = evaluate_index_for_vector(col_1, num_cols)?;
if col_0 >= num_cols || col_1 >= num_cols {
return Err(MathError::OutOfBounds(
format!("smaller than {num_cols}"),
if col_0 > col_1 {
col_0.to_string()
} else {
col_1.to_string()
},
));
}
for row in 0..self.get_num_rows() {
unsafe {
let entry_0 = fmpz_poly_mat_entry(&self.matrix, row, col_0);
let entry_1 = fmpz_poly_mat_entry(&self.matrix, row, col_1);
fmpz_poly_swap(entry_0, entry_1);
}
}
Ok(())
}
fn swap_rows(
&mut self,
row_0: impl TryInto<i64> + Display,
row_1: impl TryInto<i64> + Display,
) -> Result<(), MathError> {
let num_rows = self.get_num_rows();
let row_0 = evaluate_index_for_vector(row_0, num_rows)?;
let row_1 = evaluate_index_for_vector(row_1, num_rows)?;
if row_0 >= num_rows || row_1 >= num_rows {
return Err(MathError::OutOfBounds(
format!("smaller than {num_rows}"),
if row_0 > row_1 {
row_0.to_string()
} else {
row_1.to_string()
},
));
}
for col in 0..self.get_num_columns() {
unsafe {
let entry_0 = fmpz_poly_mat_entry(&self.matrix, row_0, col);
let entry_1 = fmpz_poly_mat_entry(&self.matrix, row_1, col);
fmpz_poly_swap(entry_0, entry_1);
}
}
Ok(())
}
}
impl MatPolyOverZ {
pub fn reverse_columns(&mut self) {
let num_cols = self.get_num_columns();
for col in 0..(num_cols / 2) {
self.swap_columns(col, num_cols - col - 1).unwrap();
}
}
pub fn reverse_rows(&mut self) {
let num_rows = self.get_num_rows();
for row in 0..(num_rows / 2) {
self.swap_rows(row, num_rows - row - 1).unwrap();
}
}
}
#[cfg(test)]
mod test_setter {
use crate::{
integer::{MatPolyOverZ, PolyOverZ},
traits::{MatrixGetEntry, MatrixSetEntry, MatrixSetSubmatrix},
};
use std::str::FromStr;
#[test]
fn standard_value() {
let mut matrix = MatPolyOverZ::new(5, 10);
let value = PolyOverZ::from_str("2 889 1").unwrap();
matrix.set_entry(4, 7, &value).unwrap();
let entry = matrix.get_entry(4, 7).unwrap();
assert_eq!("2 889 1", entry.to_string());
}
#[test]
fn max_int_positive() {
let mut matrix = MatPolyOverZ::new(5, 10);
let value = PolyOverZ::from_str(&format!("2 {} 1", i64::MAX)).unwrap();
matrix.set_entry(4, 7, &value).unwrap();
let entry = matrix.get_entry(4, 7).unwrap();
assert_eq!(format!("2 {} 1", i64::MAX), entry.to_string());
}
#[test]
fn large_positive() {
let mut matrix = MatPolyOverZ::new(5, 10);
let value = PolyOverZ::from_str(&format!("2 {} 1", u64::MAX)).unwrap();
matrix.set_entry(4, 7, &value).unwrap();
let entry = matrix.get_entry(4, 7).unwrap();
assert_eq!(format!("2 {} 1", u64::MAX), entry.to_string());
}
#[test]
fn large_positive_ref() {
let mut matrix = MatPolyOverZ::new(5, 10);
let value_1 = PolyOverZ::from_str(&format!("2 {} 1", u64::MAX)).unwrap();
let value_2 = PolyOverZ::from_str("2 8 1").unwrap();
matrix.set_entry(1, 1, &value_1).unwrap();
matrix.set_entry(0, 0, value_2).unwrap();
let entry_1 = matrix.get_entry(1, 1).unwrap();
let entry_2 = matrix.get_entry(0, 0).unwrap();
assert_eq!(format!("2 {} 1", u64::MAX), entry_1.to_string());
assert_eq!("2 8 1", entry_2.to_string());
}
#[test]
fn max_int_negative() {
let mut matrix = MatPolyOverZ::new(5, 10);
let value = PolyOverZ::from_str(&format!("2 {} 1", i64::MIN)).unwrap();
matrix.set_entry(4, 7, &value).unwrap();
let entry = matrix.get_entry(4, 7).unwrap();
assert_eq!(format!("2 {} 1", i64::MIN), entry.to_string());
}
#[test]
fn large_negative() {
let mut matrix = MatPolyOverZ::new(5, 10);
let value_str = &format!("2 -{} 1", u64::MAX);
let value = PolyOverZ::from_str(value_str).unwrap();
matrix.set_entry(4, 7, &value).unwrap();
let entry = matrix.get_entry(4, 7).unwrap();
assert_eq!(PolyOverZ::from_str(value_str).unwrap(), entry);
}
#[test]
fn setting_at_zero() {
let mut matrix = MatPolyOverZ::new(5, 10);
let value = PolyOverZ::from_str(&format!("2 {} 1", u64::MAX)).unwrap();
matrix.set_entry(0, 0, &value).unwrap();
let entry = matrix.get_entry(0, 0).unwrap();
assert_eq!(format!("2 {} 1", u64::MAX), entry.to_string());
}
#[test]
fn error_wrong_row() {
let mut matrix = MatPolyOverZ::new(5, 10);
let value = PolyOverZ::default();
assert!(matrix.set_entry(5, 1, &value).is_err());
assert!(matrix.set_entry(-6, 1, value).is_err());
}
#[test]
fn error_wrong_column() {
let mut matrix = MatPolyOverZ::new(5, 10);
let value = PolyOverZ::default();
assert!(matrix.set_entry(1, 100, &value).is_err());
assert!(matrix.set_entry(1, -11, value).is_err());
}
#[test]
fn negative_indexing() {
let mut matrix = MatPolyOverZ::new(3, 3);
matrix.set_entry(-1, -1, &PolyOverZ::from(9)).unwrap();
matrix.set_entry(-1, -2, &PolyOverZ::from(8)).unwrap();
matrix.set_entry(-3, -3, &PolyOverZ::from(1)).unwrap();
let matrix_cmp =
MatPolyOverZ::from_str("[[1 1, 0, 0],[0, 0, 0],[0, 1 8, 1 9]]").unwrap();
assert_eq!(matrix_cmp, matrix);
}
#[test]
fn column_small_entries() {
let mut mat_1 = MatPolyOverZ::from_str("[[0, 1 2, 0],[0, 1 5, 1 6]]").unwrap();
let mat_2 = MatPolyOverZ::from_str("[[0],[1 -1]]").unwrap();
let cmp = MatPolyOverZ::from_str("[[0, 0, 0],[0, 1 -1, 1 6]]").unwrap();
mat_1.set_column(1, &mat_2, 0).unwrap();
assert_eq!(cmp, mat_1);
}
#[test]
fn column_large_entries() {
let mut mat_1 = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]]",
i64::MIN,
i64::MAX,
u64::MAX
))
.unwrap();
let mat_2 = MatPolyOverZ::from_str(&format!(
"[[1 1, 1 {}],[1 {}, 0],[1 7, 1 -1]]",
i64::MIN,
i64::MAX
))
.unwrap();
let cmp = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[0, 1 4, 1 {}, 1 5],[1 -1, 1 6, 2 8 9, 0]]",
i64::MIN,
u64::MAX
))
.unwrap();
mat_1.set_column(0, &mat_2, 1).unwrap();
assert_eq!(cmp, mat_1);
}
#[test]
fn column_swap_same_entry() {
let mut mat_1 = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]]",
i64::MIN,
i64::MAX,
u64::MAX
))
.unwrap();
let cmp = mat_1.clone();
mat_1.set_column(0, &cmp, 0).unwrap();
mat_1.set_column(1, &cmp, 1).unwrap();
assert_eq!(cmp, mat_1);
}
#[test]
fn column_out_of_bounds() {
let mut mat_1 = MatPolyOverZ::new(5, 2);
let mat_2 = mat_1.clone();
assert!(mat_1.set_column(-3, &mat_2, 0).is_err());
assert!(mat_1.set_column(2, &mat_2, 0).is_err());
assert!(mat_1.set_column(1, &mat_2, -3).is_err());
assert!(mat_1.set_column(1, &mat_2, 2).is_err());
}
#[test]
fn column_mismatching_columns() {
let mut mat_1 = MatPolyOverZ::new(5, 2);
let mat_2 = MatPolyOverZ::new(2, 2);
assert!(mat_1.set_column(0, &mat_2, 0).is_err());
assert!(mat_1.set_column(1, &mat_2, 1).is_err());
}
#[test]
fn row_small_entries() {
let mut mat_1 = MatPolyOverZ::from_str("[[0, 1 2, 0],[0, 2 5 6, 0]]").unwrap();
let mat_2 = MatPolyOverZ::from_str("[[0, 1 -1, 1 2]]").unwrap();
let cmp = MatPolyOverZ::from_str("[[0, 1 2, 0],[0, 1 -1, 1 2]]").unwrap();
let _ = mat_1.set_row(1, &mat_2, 0);
assert_eq!(cmp, mat_1);
}
#[test]
fn row_large_entries() {
let mut mat_1 = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]]",
i64::MIN,
i64::MAX,
u64::MAX
))
.unwrap();
let mat_2 = MatPolyOverZ::from_str(&format!(
"[[0, 0, 0, 0],[1 {}, 0, 1 {}, 0]]",
i64::MIN,
i64::MAX
))
.unwrap();
let cmp = MatPolyOverZ::from_str(&format!(
"[[1 {}, 0, 1 {}, 0],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]]",
i64::MIN,
i64::MAX,
i64::MAX,
u64::MAX
))
.unwrap();
let _ = mat_1.set_row(0, &mat_2, 1);
assert_eq!(cmp, mat_1);
}
#[test]
fn row_swap_same_entry() {
let mut mat_1 = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]]",
i64::MIN,
i64::MAX,
u64::MAX
))
.unwrap();
let cmp = mat_1.clone();
let _ = mat_1.set_row(0, &cmp, 0);
let _ = mat_1.set_row(1, &cmp, 1);
assert_eq!(cmp, mat_1);
}
#[test]
fn row_out_of_bounds() {
let mut mat_1 = MatPolyOverZ::new(5, 2);
let mat_2 = mat_1.clone();
assert!(mat_1.set_row(-6, &mat_2, 0).is_err());
assert!(mat_1.set_row(5, &mat_2, 0).is_err());
assert!(mat_1.set_row(2, &mat_2, -6).is_err());
assert!(mat_1.set_row(2, &mat_2, 5).is_err());
}
#[test]
fn row_mismatching_columns() {
let mut mat_1 = MatPolyOverZ::new(3, 2);
let mat_2 = MatPolyOverZ::new(3, 3);
assert!(mat_1.set_row(0, &mat_2, 0).is_err());
assert!(mat_1.set_row(1, &mat_2, 1).is_err());
}
#[test]
fn negative_indexing_row_column() {
let mut matrix = MatPolyOverZ::identity(3, 3);
let matrix2 = MatPolyOverZ::identity(3, 3);
matrix.set_column(-1, &matrix2, -2).unwrap();
matrix.set_row(-1, &matrix2, -2).unwrap();
let matrix_cmp =
MatPolyOverZ::from_str("[[1 1, 0, 0],[0, 1 1, 1 1],[0, 1 1, 0]]").unwrap();
assert_eq!(matrix_cmp, matrix);
}
}
#[cfg(test)]
mod test_swaps {
use super::MatPolyOverZ;
use crate::traits::{MatrixGetSubmatrix, MatrixSwaps};
use std::str::FromStr;
#[test]
fn entries_small_entries() {
let mut matrix = MatPolyOverZ::from_str("[[1 1, 1 2, 1 3],[1 4, 2 5 6, 0]]").unwrap();
let cmp = MatPolyOverZ::from_str("[[1 1, 2 5 6, 1 3],[1 4, 1 2, 0]]").unwrap();
let _ = matrix.swap_entries(1, 1, 0, 1);
assert_eq!(cmp, matrix);
}
#[test]
fn entries_large_entries() {
let mut matrix = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]]",
i64::MIN,
i64::MAX,
u64::MAX
))
.unwrap();
let cmp = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]]",
u64::MAX,
i64::MAX,
i64::MIN
))
.unwrap();
let _ = matrix.swap_entries(0, 0, 1, 2);
assert_eq!(cmp, matrix);
}
#[test]
fn entries_swap_same_entry() {
let mut matrix = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]]",
i64::MIN,
i64::MAX,
u64::MAX
))
.unwrap();
let cmp = matrix.clone();
let _ = matrix.swap_entries(0, 0, 0, 0);
let _ = matrix.swap_entries(1, 1, 1, 1);
assert_eq!(cmp, matrix);
}
#[test]
fn entries_out_of_bounds() {
let mut matrix = MatPolyOverZ::new(5, 2);
assert!(matrix.swap_entries(-6, 0, 0, 0).is_err());
assert!(matrix.swap_entries(0, -3, 0, 0).is_err());
assert!(matrix.swap_entries(0, 0, 5, 0).is_err());
assert!(matrix.swap_entries(0, 5, 0, 0).is_err());
}
#[test]
fn entries_negative_indexing() {
let mut matrix = MatPolyOverZ::identity(2, 2);
matrix.swap_entries(-2, -2, -2, -1).unwrap();
assert_eq!("[[0, 1 1],[0, 1 1]]", matrix.to_string());
}
#[test]
fn columns_small_entries() {
let mut matrix = MatPolyOverZ::from_str("[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]]").unwrap();
let cmp_vec_0 = MatPolyOverZ::from_str("[[1 1],[1 4]]").unwrap();
let cmp_vec_1 = MatPolyOverZ::from_str("[[1 3],[1 6]]").unwrap();
let cmp_vec_2 = MatPolyOverZ::from_str("[[1 2],[1 5]]").unwrap();
let _ = matrix.swap_columns(1, 2);
assert_eq!(cmp_vec_0, matrix.get_column(0).unwrap());
assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
assert_eq!(cmp_vec_2, matrix.get_column(2).unwrap());
}
#[test]
fn columns_large_entries() {
let mut matrix = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 7, 0]]",
i64::MIN,
i64::MAX,
u64::MAX
))
.unwrap();
let cmp_vec_0 =
MatPolyOverZ::from_str(&format!("[[1 3],[1 {}],[2 8 7]]", u64::MAX)).unwrap();
let cmp_vec_1 = MatPolyOverZ::from_str("[[1 1],[1 4],[1 6]]").unwrap();
let cmp_vec_2 =
MatPolyOverZ::from_str(&format!("[[1 {}],[1 {}],[1 7]]", i64::MIN, i64::MAX))
.unwrap();
let cmp_vec_3 = MatPolyOverZ::from_str("[[1 4],[1 5],[0]]").unwrap();
let _ = matrix.swap_columns(0, 2);
assert_eq!(cmp_vec_0, matrix.get_column(0).unwrap());
assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
assert_eq!(cmp_vec_2, matrix.get_column(2).unwrap());
assert_eq!(cmp_vec_3, matrix.get_column(3).unwrap());
}
#[test]
fn columns_swap_same_col() {
let mut matrix = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 1 8, 1 9]]",
i64::MIN,
i64::MAX,
u64::MAX
))
.unwrap();
let cmp = matrix.clone();
let _ = matrix.swap_columns(0, 0);
assert_eq!(cmp, matrix);
}
#[test]
fn column_out_of_bounds() {
let mut matrix = MatPolyOverZ::new(5, 2);
assert!(matrix.swap_columns(-6, 0).is_err());
assert!(matrix.swap_columns(0, -6).is_err());
assert!(matrix.swap_columns(5, 0).is_err());
assert!(matrix.swap_columns(0, 5).is_err());
}
#[test]
fn rows_small_entries() {
let mut matrix = MatPolyOverZ::from_str("[[1 1, 1 2],[1 3, 2 4 5]]").unwrap();
let cmp_vec_0 = MatPolyOverZ::from_str("[[1 3, 2 4 5]]").unwrap();
let cmp_vec_1 = MatPolyOverZ::from_str("[[1 1, 1 2]]").unwrap();
let _ = matrix.swap_rows(1, 0);
assert_eq!(cmp_vec_0, matrix.get_row(0).unwrap());
assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
}
#[test]
fn rows_large_entries() {
let mut matrix = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 7, 1 6, 1 8, 0],[1 {}, 1 4, 1 {}, 1 5]]",
i64::MIN,
i64::MAX,
u64::MAX
))
.unwrap();
let cmp_vec_0 =
MatPolyOverZ::from_str(&format!("[[1 {}, 1 4, 1 {}, 1 5]]", i64::MAX, u64::MAX))
.unwrap();
let cmp_vec_1 = MatPolyOverZ::from_str("[[1 7, 1 6, 1 8, 0]]").unwrap();
let cmp_vec_2 =
MatPolyOverZ::from_str(&format!("[[1 {}, 1 1, 1 3, 1 4]]", i64::MIN)).unwrap();
let _ = matrix.swap_rows(0, 2);
assert_eq!(cmp_vec_0, matrix.get_row(0).unwrap());
assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
assert_eq!(cmp_vec_2, matrix.get_row(2).unwrap());
}
#[test]
fn rows_swap_same_row() {
let mut matrix = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 1 8, 1 9]]",
i64::MIN,
i64::MAX,
u64::MAX
))
.unwrap();
let cmp = matrix.clone();
let _ = matrix.swap_rows(1, 1);
assert_eq!(cmp, matrix);
}
#[test]
fn row_out_of_bounds() {
let mut matrix = MatPolyOverZ::new(2, 4);
assert!(matrix.swap_rows(-3, 0).is_err());
assert!(matrix.swap_rows(0, -3).is_err());
assert!(matrix.swap_rows(4, 0).is_err());
assert!(matrix.swap_rows(0, 4).is_err());
}
#[test]
fn negative_indexing_row_column() {
let mut matrix = MatPolyOverZ::identity(3, 3);
let mut matrix2 = MatPolyOverZ::identity(3, 3);
matrix.swap_columns(-1, -2).unwrap();
matrix2.swap_rows(-1, -2).unwrap();
let matrix_cmp =
MatPolyOverZ::from_str("[[1 1, 0, 0],[0, 0, 1 1],[0, 1 1, 0]]").unwrap();
assert_eq!(matrix_cmp, matrix);
assert_eq!(matrix_cmp, matrix2);
}
}
#[cfg(test)]
mod test_reverses {
use super::MatPolyOverZ;
use crate::traits::MatrixGetSubmatrix;
use std::str::FromStr;
#[test]
fn columns_small_entries() {
let mut matrix = MatPolyOverZ::from_str("[[1 1, 1 2, 2 3 4],[0, 1 5, 1 6]]").unwrap();
let cmp_vec_0 = MatPolyOverZ::from_str("[[1 1],[0]]").unwrap();
let cmp_vec_1 = MatPolyOverZ::from_str("[[1 2],[1 5]]").unwrap();
let cmp_vec_2 = MatPolyOverZ::from_str("[[2 3 4],[1 6]]").unwrap();
matrix.reverse_columns();
assert_eq!(cmp_vec_2, matrix.get_column(0).unwrap());
assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
assert_eq!(cmp_vec_0, matrix.get_column(2).unwrap());
}
#[test]
fn columns_large_entries() {
let mut matrix = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]]",
i64::MIN,
i64::MAX,
u64::MAX
))
.unwrap();
let cmp_vec_0 =
MatPolyOverZ::from_str(&format!("[[1 {}],[1 {}],[1 7]]", i64::MIN, i64::MAX))
.unwrap();
let cmp_vec_1 = MatPolyOverZ::from_str("[[1 1],[1 4],[1 6]]").unwrap();
let cmp_vec_2 =
MatPolyOverZ::from_str(&format!("[[1 3],[1 {}],[2 8 9]]", u64::MAX)).unwrap();
let cmp_vec_3 = MatPolyOverZ::from_str("[[1 4],[1 5],[0]]").unwrap();
matrix.reverse_columns();
assert_eq!(cmp_vec_3, matrix.get_column(0).unwrap());
assert_eq!(cmp_vec_2, matrix.get_column(1).unwrap());
assert_eq!(cmp_vec_1, matrix.get_column(2).unwrap());
assert_eq!(cmp_vec_0, matrix.get_column(3).unwrap());
}
#[test]
fn rows_small_entries() {
let mut matrix = MatPolyOverZ::from_str("[[1 1, 1 2],[2 3 4, 0]]").unwrap();
let cmp_vec_0 = MatPolyOverZ::from_str("[[1 1, 1 2]]").unwrap();
let cmp_vec_1 = MatPolyOverZ::from_str("[[2 3 4, 0]]").unwrap();
matrix.reverse_rows();
assert_eq!(cmp_vec_1, matrix.get_row(0).unwrap());
assert_eq!(cmp_vec_0, matrix.get_row(1).unwrap());
}
#[test]
fn rows_large_entries() {
let mut matrix = MatPolyOverZ::from_str(&format!(
"[[1 {}, 1 1, 1 3, 1 4],[1 7, 1 6, 2 8 9, 0],[1 {}, 1 4, 1 {}, 1 5]]",
i64::MIN,
i64::MAX,
u64::MAX
))
.unwrap();
let cmp_vec_0 =
MatPolyOverZ::from_str(&format!("[[1 {}, 1 1, 1 3, 1 4]]", i64::MIN)).unwrap();
let cmp_vec_1 = MatPolyOverZ::from_str("[[1 7, 1 6, 2 8 9, 0]]").unwrap();
let cmp_vec_2 =
MatPolyOverZ::from_str(&format!("[[1 {}, 1 4, 1 {}, 1 5]]", i64::MAX, u64::MAX))
.unwrap();
matrix.reverse_rows();
assert_eq!(cmp_vec_2, matrix.get_row(0).unwrap());
assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
assert_eq!(cmp_vec_0, matrix.get_row(2).unwrap());
}
}
#[cfg(test)]
mod test_set_submatrix {
use crate::{integer::MatPolyOverZ, traits::MatrixSetSubmatrix};
use std::str::FromStr;
#[test]
fn entire_matrix() {
let mut mat = MatPolyOverZ::sample_uniform(10, 10, 5, -100, 100).unwrap();
let identity = MatPolyOverZ::identity(10, 10);
mat.set_submatrix(0, 0, &identity, 0, 0, 9, 9).unwrap();
assert_eq!(identity, mat);
}
#[test]
fn out_of_bounds() {
let mut mat = MatPolyOverZ::identity(10, 10);
assert!(mat.set_submatrix(10, 0, &mat.clone(), 0, 0, 9, 9).is_err());
assert!(mat.set_submatrix(0, 10, &mat.clone(), 0, 0, 9, 9).is_err());
assert!(mat.set_submatrix(0, 0, &mat.clone(), 10, 0, 9, 9).is_err());
assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 10, 9, 9).is_err());
assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 10, 9).is_err());
assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 9, 10).is_err());
assert!(mat.set_submatrix(-11, 0, &mat.clone(), 0, 0, 9, 9).is_err());
assert!(mat.set_submatrix(0, -11, &mat.clone(), 0, 0, 9, 9).is_err());
assert!(mat.set_submatrix(0, 0, &mat.clone(), -11, 0, 9, 9).is_err());
assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, -11, 9, 9).is_err());
assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, -11, 9).is_err());
assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 9, -11).is_err());
}
#[test]
fn submatrix_too_large() {
let mut mat = MatPolyOverZ::sample_uniform(10, 10, 5, -100, 100).unwrap();
assert!(
mat.set_submatrix(0, 0, &MatPolyOverZ::identity(11, 11), 0, 0, 10, 10)
.is_err()
);
assert!(mat.set_submatrix(1, 2, &mat.clone(), 0, 0, 9, 9).is_err());
}
#[test]
fn large_values() {
let mut mat = MatPolyOverZ::from_str(&format!(
"[[1 1, 2 1 {}],[1 -{}, 0]]",
u64::MAX,
u64::MAX
))
.unwrap();
let cmp_mat =
MatPolyOverZ::from_str(&format!("[[1 -{}, 0],[1 -{}, 0]]", u64::MAX, u64::MAX))
.unwrap();
mat.set_submatrix(0, 0, &mat.clone(), 1, 0, 1, 1).unwrap();
assert_eq!(cmp_mat, mat);
}
#[test]
#[should_panic]
fn submatrix_negative() {
let mut mat = MatPolyOverZ::identity(10, 10);
let _ = mat.set_submatrix(0, 0, &mat.clone(), 0, 9, 9, 5);
}
}