#![cfg(feature = "mat2")]
use gemath::*;
use crate::vec2::{Vec2, Meters, Pixels, World, Local, Screen};
#[cfg(test)]
mod tests {
use super::*;
const EPSILON: f32 = 1e-6;
#[test]
fn test_mat2_new() {
let m: Mat2<(), ()> = Mat2::new(Vec2::<(), ()>::new(1.0, 2.0), Vec2::<(), ()>::new(3.0, 4.0));
assert_eq!(m.x_col, Vec2::<(), ()>::new(1.0, 2.0));
assert_eq!(m.y_col, Vec2::<(), ()>::new(3.0, 4.0));
}
#[test]
fn test_mat2_zero() {
let m: Mat2<(), ()> = Mat2::ZERO;
assert_eq!(m.x_col, Vec2::<(), ()>::ZERO);
assert_eq!(m.y_col, Vec2::<(), ()>::ZERO);
}
#[test]
fn test_mat2_identity() {
let m: Mat2<(), ()> = Mat2::IDENTITY;
assert_eq!(m.x_col, Vec2::<(), ()>::new(1.0, 0.0));
assert_eq!(m.y_col, Vec2::<(), ()>::new(0.0, 1.0));
}
#[test]
fn test_mat2_from_cols_array() {
let m: Mat2<(), ()> = Mat2::from_cols_array(&[1.0, 2.0, 3.0, 4.0]);
assert_eq!(m.x_col, Vec2::<(), ()>::new(1.0, 2.0));
assert_eq!(m.y_col, Vec2::<(), ()>::new(3.0, 4.0));
}
#[test]
fn test_mat2_from_rows() {
let m: Mat2<(), ()> = Mat2::from_rows(1.0, 3.0, 2.0, 4.0);
assert_eq!(m.x_col, Vec2::<(), ()>::new(1.0, 2.0));
assert_eq!(m.y_col, Vec2::<(), ()>::new(3.0, 4.0));
}
#[test]
fn test_mat2_determinant() {
let m: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 3.0, 4.0);
assert_eq!(m.determinant(), 1.0 * 4.0 - 2.0 * 3.0);
let m_singular: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 2.0, 4.0);
assert_eq!(m_singular.determinant(), 0.0);
}
#[test]
fn test_mat2_transpose() {
let m: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 3.0, 4.0);
let mt = m.transpose();
assert_eq!(mt.x_col, Vec2::<(), ()>::new(1.0, 2.0));
assert_eq!(mt.y_col, Vec2::<(), ()>::new(3.0, 4.0));
}
#[test]
fn test_mat2_inverse() {
let m: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 3.0, 4.0);
let m_inv = m.inverse().unwrap();
assert!((m_inv.x_col.x - -2.0).abs() < 1e-6);
assert!((m_inv.x_col.y - 1.5).abs() < 1e-6);
assert!((m_inv.y_col.x - 1.0).abs() < 1e-6);
assert!((m_inv.y_col.y - -0.5).abs() < 1e-6);
let m_singular: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 2.0, 4.0);
assert!(m_singular.inverse().is_none());
}
#[test]
fn test_mat2_try_inverse_alias() {
let m: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 3.0, 4.0);
assert_eq!(m.try_inverse(), m.inverse());
let m_singular: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 2.0, 4.0);
assert_eq!(m_singular.try_inverse(), None);
}
#[test]
fn test_mat2_eq() {
let m1: Mat2<(), ()> = Mat2::new(Vec2::<(), ()>::new(1.0, 2.0), Vec2::<(), ()>::new(3.0, 4.0));
let m2: Mat2<(), ()> = Mat2::new(Vec2::<(), ()>::new(1.0, 2.0), Vec2::<(), ()>::new(3.0, 4.0));
let m3: Mat2<(), ()> = Mat2::new(Vec2::<(), ()>::new(5.0, 6.0), Vec2::<(), ()>::new(7.0, 8.0));
assert_eq!(m1, m2);
assert_ne!(m1, m3);
}
#[test]
fn test_mat2_add() {
let m1: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 3.0, 4.0);
let m2: Mat2<(), ()> = Mat2::from_rows(5.0, 6.0, 7.0, 8.0);
let expected: Mat2<(), ()> = Mat2::from_rows(6.0, 8.0, 10.0, 12.0);
assert_eq!(m1 + m2, expected);
}
#[test]
fn test_mat2_sub() {
let m1: Mat2<(), ()> = Mat2::from_rows(5.0, 6.0, 7.0, 8.0);
let m2: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 3.0, 4.0);
let expected: Mat2<(), ()> = Mat2::from_rows(4.0, 4.0, 4.0, 4.0);
assert_eq!(m1 - m2, expected);
}
#[test]
fn test_mat2_mul_scalar() {
let m: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 3.0, 4.0);
let expected: Mat2<(), ()> = Mat2::from_rows(2.0, 4.0, 6.0, 8.0);
assert_eq!(m * 2.0, expected);
assert_eq!(2.0 * m, expected);
}
#[test]
fn test_mat2_mul_vec2() {
let m: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 3.0, 4.0); let v: Vec2<(), ()> = Vec2::new(5.0, 6.0);
let expected: Vec2<(), ()> = Vec2::new(17.0, 39.0);
assert_eq!(m * v, expected);
}
#[test]
fn test_mat2_mul_mat2() {
let m1: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 3.0, 4.0); let m2: Mat2<(), ()> = Mat2::from_rows(5.0, 6.0, 7.0, 8.0); let expected: Mat2<(), ()> = Mat2::new(Vec2::new(19.0, 43.0), Vec2::new(22.0, 50.0));
assert_eq!(m1 * m2, expected);
}
#[test]
fn test_mat2_row_col_accessors() {
let mut m: Mat2<(), ()> = Mat2::from_rows(1.0, 2.0, 3.0, 4.0);
assert_eq!(m.col(0), Some(Vec2::<(), ()>::new(1.0, 3.0)));
assert_eq!(m.col(1), Some(Vec2::<(), ()>::new(2.0, 4.0)));
assert_eq!(m.row(0), Some(Vec2::<(), ()>::new(1.0, 2.0)));
assert_eq!(m.row(1), Some(Vec2::<(), ()>::new(3.0, 4.0)));
m.set_col(0, Vec2::<(), ()>::new(9.0, 8.0));
assert_eq!(m.col(0), Some(Vec2::<(), ()>::new(9.0, 8.0)));
m.set_row(1, Vec2::<(), ()>::new(7.0, 6.0));
assert_eq!(m.row(1), Some(Vec2::<(), ()>::new(7.0, 6.0)));
}
#[test]
fn test_mat2_is_orthonormal() {
let m: Mat2<(), ()> = Mat2::IDENTITY;
assert!(m.is_orthonormal());
let m2: Mat2<(), ()> = Mat2::from_rows(1.0, 0.0, 0.0, -1.0); assert!(m2.is_orthonormal());
let m3: Mat2<(), ()> = Mat2::from_rows(2.0, 0.0, 0.0, 2.0); assert!(!m3.is_orthonormal());
}
#[test]
fn test_mat2_from_shear() {
let shx = 2.0;
let shy = 3.0;
let m: Mat2<(), ()> = Mat2::from_shear(shx, shy);
assert_eq!(m.x_col, Vec2::<(), ()>::new(1.0, 3.0));
assert_eq!(m.y_col, Vec2::<(), ()>::new(2.0, 1.0));
}
#[test]
fn test_mat2_from_rotation() {
let m: Mat2<(), ()> = Mat2::from_rotation(Radians(core::f32::consts::FRAC_PI_2));
assert!(m.is_orthonormal());
let v = Vec2::<(), ()>::new(1.0, 0.0);
let v_rot = m * v;
assert!((v_rot.x - 0.0).abs() < EPSILON);
assert!((v_rot.y - 1.0).abs() < EPSILON);
}
#[test]
fn test_mat2_from_rotation_deg() {
let m: Mat2<(), ()> = Mat2::from_rotation_deg(Degrees(90.0));
let v = Vec2::<(), ()>::new(1.0, 0.0);
let v_rot = m * v;
assert!((v_rot.x - 0.0).abs() < EPSILON);
assert!((v_rot.y - 1.0).abs() < EPSILON);
}
#[test]
fn test_mat2_from_scale() {
let m: Mat2<(), ()> = Mat2::from_scale(Vec2::new(2.0, 3.0));
let v = Vec2::<(), ()>::new(4.0, 5.0);
let v_scaled = m * v;
assert_eq!(v_scaled, Vec2::new(8.0, 15.0));
assert_eq!(m.determinant(), 6.0);
}
#[test]
fn test_mat2_from_scale_preserves_unit_and_space() {
let m: Mat2<Meters, World> = Mat2::from_scale(Vec2::new(2.0, 3.0));
let v: Vec2<Meters, World> = Vec2::new(4.0, 5.0);
let out = m * v;
assert_eq!(out, Vec2::new(8.0, 15.0));
}
}
const _CONST_MAT2_ID: Mat2<(), ()> = Mat2::IDENTITY;
const _CONST_MAT2_ZERO: Mat2<(), ()> = Mat2::ZERO;
const _CONST_MAT2_NEW: Mat2<(), ()> = Mat2::new(Vec2::<(), ()>::new(1.0, 2.0), Vec2::<(), ()>::new(3.0, 4.0));
const _CONST_MAT2_COLS: Mat2<(), ()> = Mat2::from_cols_array(&[1.0, 2.0, 3.0, 4.0]);
const _CONST_MAT2_ROWS: Mat2<(), ()> = Mat2::from_rows(1.0, 3.0, 2.0, 4.0);
const _CONST_MAT2_DET: f32 = _CONST_MAT2_COLS.determinant();
const _CONST_MAT2_TRANSPOSE: Mat2<(), ()> = _CONST_MAT2_COLS.transpose();
const _CONST_MAT2_SHEAR: Mat2<(), ()> = Mat2::from_shear(2.0, 3.0);
const _CONST_MAT2_ROW0: Option<Vec2<(), ()>> = _CONST_MAT2_COLS.row(0);
const _CONST_MAT2_ROW1: Option<Vec2<(), ()>> = _CONST_MAT2_COLS.row(1);
const _CONST_MAT2_COL0: Option<Vec2<(), ()>> = _CONST_MAT2_COLS.col(0);
const _CONST_MAT2_COL1: Option<Vec2<(), ()>> = _CONST_MAT2_COLS.col(1);
const _: () = {
assert!(_CONST_MAT2_ID.x_col.x == 1.0 && _CONST_MAT2_ID.y_col.y == 1.0);
assert!(_CONST_MAT2_ZERO.x_col.x == 0.0 && _CONST_MAT2_ZERO.y_col.y == 0.0);
assert!(_CONST_MAT2_NEW.x_col.x == 1.0 && _CONST_MAT2_NEW.x_col.y == 2.0);
assert!(_CONST_MAT2_NEW.y_col.x == 3.0 && _CONST_MAT2_NEW.y_col.y == 4.0);
assert!(_CONST_MAT2_COLS.x_col.x == 1.0 && _CONST_MAT2_COLS.x_col.y == 2.0);
assert!(_CONST_MAT2_COLS.y_col.x == 3.0 && _CONST_MAT2_COLS.y_col.y == 4.0);
assert!(_CONST_MAT2_ROWS.x_col.x == 1.0 && _CONST_MAT2_ROWS.x_col.y == 2.0);
assert!(_CONST_MAT2_ROWS.y_col.x == 3.0 && _CONST_MAT2_ROWS.y_col.y == 4.0);
assert!(_CONST_MAT2_DET == -2.0);
assert!(_CONST_MAT2_TRANSPOSE.x_col.x == 1.0 && _CONST_MAT2_TRANSPOSE.x_col.y == 3.0);
assert!(_CONST_MAT2_TRANSPOSE.y_col.x == 2.0 && _CONST_MAT2_TRANSPOSE.y_col.y == 4.0);
assert!(_CONST_MAT2_SHEAR.x_col.x == 1.0 && _CONST_MAT2_SHEAR.x_col.y == 3.0);
assert!(_CONST_MAT2_SHEAR.y_col.x == 2.0 && _CONST_MAT2_SHEAR.y_col.y == 1.0);
match _CONST_MAT2_ROW0 { Some(v) => assert!(v.x == 1.0 && v.y == 3.0), None => panic!("row0") }
match _CONST_MAT2_ROW1 { Some(v) => assert!(v.x == 2.0 && v.y == 4.0), None => panic!("row1") }
match _CONST_MAT2_COL0 { Some(v) => assert!(v.x == 1.0 && v.y == 2.0), None => panic!("col0") }
match _CONST_MAT2_COL1 { Some(v) => assert!(v.x == 3.0 && v.y == 4.0), None => panic!("col1") }
};
const _CONST_MAT2_METERS: Mat2<Meters, ()> = Mat2::new(
Vec2::<Meters, ()>::new(1.0, 2.0),
Vec2::<Meters, ()>::new(3.0, 4.0),
);
const _CONST_MAT2_PIXELS: Mat2<Pixels, ()> = Mat2::new(
Vec2::<Pixels, ()>::new(10.0, 20.0),
Vec2::<Pixels, ()>::new(30.0, 40.0),
);
const fn _make_mat2_meters() -> Mat2<Meters, ()> {
Mat2::from_rows(1.0, 3.0, 2.0, 4.0)
}
const fn _make_mat2_pixels() -> Mat2<Pixels, ()> {
Mat2::from_rows(10.0, 30.0, 20.0, 40.0)
}
const _CONST_MAT2_METERS2: Mat2<Meters, ()> = _make_mat2_meters();
const _CONST_MAT2_PIXELS2: Mat2<Pixels, ()> = _make_mat2_pixels();
const _CONST_MAT2_WORLD: Mat2<(), World> = Mat2::new(
Vec2::<(), World>::new(1.0, 2.0),
Vec2::<(), World>::new(3.0, 4.0),
);
const _CONST_MAT2_LOCAL: Mat2<(), Local> = Mat2::new(
Vec2::<(), Local>::new(5.0, 6.0),
Vec2::<(), Local>::new(7.0, 8.0),
);
const _CONST_MAT2_SCREEN: Mat2<(), Screen> = Mat2::new(
Vec2::<(), Screen>::new(9.0, 10.0),
Vec2::<(), Screen>::new(11.0, 12.0),
);
const _: () = {
assert!(_CONST_MAT2_METERS.x_col.x == 1.0 && _CONST_MAT2_METERS.y_col.y == 4.0);
assert!(_CONST_MAT2_PIXELS.x_col.x == 10.0 && _CONST_MAT2_PIXELS.y_col.y == 40.0);
assert!(_CONST_MAT2_METERS2.x_col.x == 1.0 && _CONST_MAT2_METERS2.y_col.y == 4.0);
assert!(_CONST_MAT2_PIXELS2.x_col.x == 10.0 && _CONST_MAT2_PIXELS2.y_col.y == 40.0);
assert!(_CONST_MAT2_WORLD.x_col.x == 1.0 && _CONST_MAT2_WORLD.y_col.y == 4.0);
assert!(_CONST_MAT2_LOCAL.x_col.x == 5.0 && _CONST_MAT2_LOCAL.y_col.y == 8.0);
assert!(_CONST_MAT2_SCREEN.x_col.x == 9.0 && _CONST_MAT2_SCREEN.y_col.y == 12.0);
};