gemath 0.1.0

Type-safe game math with type-level units/spaces, typed angles, and explicit fallible ops (plus optional geometry/collision).
Documentation
#![cfg(feature = "unit_vec")]

use gemath::*;

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn unitvec2_try_new_normalizes_and_rejects_zero() {
        let u: UnitVec2<(), ()> = UnitVec2::try_new(Vec2::new(3.0, 4.0)).unwrap();
        let v = u.as_vec();
        assert!((v.length() - 1.0).abs() < 1e-6);
        assert!(UnitVec2::<(), ()>::try_new(Vec2::ZERO).is_none());
    }

    #[test]
    fn unitvec3_try_new_normalizes_and_rejects_nonfinite() {
        let u: UnitVec3<(), ()> = UnitVec3::try_new(Vec3::new(0.0, 0.0, 5.0)).unwrap();
        let v = u.as_vec();
        assert!((v.length() - 1.0).abs() < 1e-6);

        assert!(UnitVec3::<(), ()>::try_new(Vec3::new(f32::NAN, 0.0, 0.0)).is_none());
        assert!(UnitVec3::<(), ()>::try_new(Vec3::new(f32::INFINITY, 0.0, 0.0)).is_none());
        assert!(UnitVec3::<(), ()>::try_new(Vec3::ZERO).is_none());
    }

    #[test]
    fn unitvec4_try_new_normalizes() {
        let u: UnitVec4<(), ()> = UnitVec4::try_new(Vec4::new(1.0, 2.0, 3.0, 4.0)).unwrap();
        let v = u.as_vec();
        assert!((v.length() - 1.0).abs() < 1e-6);
    }

    #[test]
    fn axis_angle_apis_accept_unitvec3() {
        let axis: UnitVec3<(), ()> = UnitVec3::Z;
        let angle = Radians(core::f32::consts::FRAC_PI_2);
        let q: Quat<(), ()> = Quat::from_unit_axis_angle_radians(axis, angle);

        // Rotate (1,0,0) around +Z by 90deg => (0,1,0)
        let v = Vec3::new(1.0, 0.0, 0.0);
        let r = q * v;
        assert!((r - Vec3::new(0.0, 1.0, 0.0)).length() < 1e-5);

        let m3: Mat3<(), ()> = Mat3::from_unit_axis_angle_radians(axis, angle);
        let r2 = m3 * v;
        assert!((r2 - Vec3::new(0.0, 1.0, 0.0)).length() < 1e-5);

        let m4: Mat4<(), ()> = Mat4::from_unit_axis_angle_radians(axis, angle);
        let r3 = m4.transform_vector(v);
        assert!((r3 - Vec3::new(0.0, 1.0, 0.0)).length() < 1e-5);
    }
}