use super::MatQ;
use crate::traits::MatrixDimensions;
use flint_sys::fmpq_mat::fmpq_mat_gso;
impl MatQ {
pub fn gso(&self) -> Self {
let mut out = MatQ::new(self.get_num_rows(), self.get_num_columns());
unsafe {
fmpq_mat_gso(&mut out.matrix, &self.matrix);
}
out
}
}
#[cfg(test)]
mod test_gso {
use crate::{
rational::{MatQ, Q},
traits::{MatrixGetEntry, MatrixGetSubmatrix},
};
use std::str::FromStr;
#[test]
fn gso_works() {
let mat = MatQ::from_str(
"[[-1, 2/7, 3/9, 4, 5/2],[-123/1000, 235/5, 123, 643/7172721, 123],[124/8981, 212, 452/2140, 12/5, 1],[0, 0, 0, 1, 1],[1, 2, 3, 4/3, 1]]",
)
.unwrap();
let mat_gso = mat.gso();
let cmp = Q::ZERO;
for i in 0..5 {
let vec_i = mat_gso.get_column(i).unwrap();
assert_ne!(cmp, vec_i.dot_product(&vec_i).unwrap());
for j in i + 1..5 {
let vec_j = mat_gso.get_column(j).unwrap();
assert_eq!(cmp, vec_i.dot_product(&vec_j).unwrap());
}
}
}
#[test]
fn gso_correct_values() {
let mat = MatQ::from_str("[[1, -1, 1],[1, 0, 1],[1, 1, 2]]").unwrap();
let mat_gso = mat.gso();
assert_eq!(
MatQ::from_str("[[1, -1, 1/6],[1, 0, -1/3],[1, 1, 1/6]]").unwrap(),
mat_gso
);
}
#[test]
fn gso_dependent_columns() {
let mat = MatQ::from_str("[[1, 2, 3, 4, 4],[1, 2, 3, 4, 5]]").unwrap();
let mat_gso = mat.gso();
let cmp = Q::ZERO;
for i in 0..5 {
let vec_i = mat_gso.get_column(i).unwrap();
for j in i + 1..5 {
let vec_j = mat_gso.get_column(j).unwrap();
assert_eq!(cmp, vec_i.dot_product(&vec_j).unwrap());
}
}
let vec_1 = mat_gso.get_column(0).unwrap();
assert_ne!(cmp, vec_1.dot_product(&vec_1).unwrap());
}
#[test]
fn gso_dependent_rows() {
let mat = MatQ::from_str("[[1, 2/7],[1, 2/7],[10, -2],[0, 4],[0, 0]]").unwrap();
let mat_gso = mat.gso();
let cmp = Q::ZERO;
for i in 0..2 {
let vec_i = mat_gso.get_column(i).unwrap();
assert_ne!(cmp, vec_i.dot_product(&vec_i).unwrap());
for j in i + 1..2 {
let vec_j = mat_gso.get_column(j).unwrap();
assert_eq!(cmp, vec_i.dot_product(&vec_j).unwrap());
}
}
}
#[test]
fn gso_large_values() {
let mat = MatQ::from_str(&format!(
"[[1, {}/7, 2],[1, 2/{}, 10],[10, -2, 8]]",
i64::MAX,
i64::MAX
))
.unwrap();
let mat_gso = mat.gso();
let cmp = Q::ZERO;
for i in 0..3 {
let vec_i = mat_gso.get_column(i).unwrap();
assert_ne!(cmp, vec_i.dot_product(&vec_i).unwrap());
for j in i + 1..3 {
let vec_j = mat_gso.get_column(j).unwrap();
assert_eq!(cmp, vec_i.dot_product(&vec_j).unwrap());
}
}
}
#[test]
fn gso_edge_cases() {
let mat_1 = MatQ::from_str("[[1]]").unwrap();
let mat_2 = MatQ::from_str("[[1, 2/2, 3/7]]").unwrap();
let mat_3 = MatQ::from_str("[[1],[2/2],[3/7]]").unwrap();
let mat_1_gso = mat_1.gso();
let mat_2_gso = mat_2.gso();
let mat_3_gso = mat_3.gso();
assert_eq!(Q::ONE, mat_1_gso.get_entry(0, 0).unwrap());
let cmp = Q::ZERO;
for i in 0..3 {
for j in i + 1..3 {
let vec_i = mat_2_gso.get_column(i).unwrap();
let vec_j = mat_2_gso.get_column(j).unwrap();
assert_eq!(cmp, vec_i.dot_product(&vec_j).unwrap());
}
}
let vec_1 = mat_2_gso.get_column(0).unwrap();
assert_ne!(cmp, vec_1.dot_product(&vec_1).unwrap());
assert_eq!(mat_3, mat_3_gso);
}
}