use qfall_math::{integer::MatZ, traits::*};
pub fn rot_minus(vec: &MatZ) -> MatZ {
let vec = if vec.is_column_vector() {
vec.clone()
} else if vec.is_row_vector() {
vec.transpose()
} else {
panic!("The input must be a vector.")
};
let mut out = MatZ::new(vec.get_num_rows(), vec.get_num_rows());
for i in 0..out.get_num_rows() {
let entry = vec.get_entry(i, 0).unwrap();
for j in 0..out.get_num_columns() {
let (row, sign) = match i + j {
k if k >= out.get_num_rows() => ((k) % out.get_num_rows(), -1),
k => (k, 1),
};
out.set_entry(row, j, sign * &entry).unwrap();
}
}
out
}
pub fn rot_minus_matrix(matrix: &MatZ) -> MatZ {
let mut vec = Vec::new();
for i in 0..matrix.get_num_columns() {
vec.push(rot_minus(&matrix.get_column(i).unwrap()));
}
let mut out = vec.first().unwrap().clone();
for mat in vec.iter().skip(1) {
out = out.concat_horizontal(mat).unwrap();
}
out
}
#[cfg(test)]
mod test_rot_minus {
use crate::utils::rotation_matrix::{rot_minus, rot_minus_matrix};
use qfall_math::integer::MatZ;
use std::str::FromStr;
#[test]
fn correct_rotation_matrix_vec() {
let vec = MatZ::from_str("[[1],[5],[-1],[9]]").unwrap();
let row_vec = MatZ::from_str("[[1,5,-1,9]]").unwrap();
let rot_col = rot_minus(&vec);
let rot_row = rot_minus(&row_vec);
let cmp_rot =
MatZ::from_str("[[1, -9, 1, -5],[5, 1, -9, 1],[-1, 5, 1, -9],[9, -1, 5, 1]]").unwrap();
assert_eq!(rot_col, rot_row);
assert_eq!(cmp_rot, rot_col)
}
#[test]
fn correct_rotation_matrix_mat() {
let mat = MatZ::from_str(&format!("[[1,5,-1,9],[{}, 1, 2, 3]]", u64::MAX)).unwrap();
let rot_mat = rot_minus_matrix(&mat);
let cmp_rot = MatZ::from_str(&format!(
"[[1, -{}, 5, -1, -1, -2, 9, -3],\
[{}, 1, 1, 5, 2, -1, 3, 9]]",
u64::MAX,
u64::MAX
))
.unwrap();
assert_eq!(cmp_rot, rot_mat);
}
#[test]
#[should_panic]
fn not_vector() {
let mat = MatZ::from_str("[[1,5,-1,9],[1,2,3,4]]").unwrap();
let _ = rot_minus(&mat);
}
}