#![cfg(feature = "proptest-support")] #![allow(non_snake_case)] use na::{Unit, UnitComplex}; use crate::proptest::*; use proptest::{prop_assert, proptest}; proptest!( /* * * From/to rotation matrix. * */ #[test] fn unit_complex_rotation_conversion(c in unit_complex()) { let r = c.to_rotation_matrix(); let cc = UnitComplex::from_rotation_matrix(&r); let rr = cc.to_rotation_matrix(); prop_assert!(relative_eq!(c, cc, epsilon = 1.0e-7)); prop_assert!(relative_eq!(r, rr, epsilon = 1.0e-7)); } /* * * Point/Vector transformation. * */ #[test] fn unit_complex_transformation(c in unit_complex(), v in vector2(), p in point2()) { let r = c.to_rotation_matrix(); let rv = r * v; let rp = r * p; prop_assert!(relative_eq!(c * v, rv, epsilon = 1.0e-7) && relative_eq!(c * &v, rv, epsilon = 1.0e-7) && relative_eq!(&c * v, rv, epsilon = 1.0e-7) && relative_eq!(&c * &v, rv, epsilon = 1.0e-7) && relative_eq!(c * p, rp, epsilon = 1.0e-7) && relative_eq!(c * &p, rp, epsilon = 1.0e-7) && relative_eq!(&c * p, rp, epsilon = 1.0e-7) && relative_eq!(&c * &p, rp, epsilon = 1.0e-7)) } /* * * Inversion. * */ #[test] fn unit_complex_inv(c in unit_complex()) { let iq = c.inverse(); prop_assert!(relative_eq!(&iq * &c, UnitComplex::identity(), epsilon = 1.0e-7) && relative_eq!(iq * &c, UnitComplex::identity(), epsilon = 1.0e-7) && relative_eq!(&iq * c, UnitComplex::identity(), epsilon = 1.0e-7) && relative_eq!(iq * c, UnitComplex::identity(), epsilon = 1.0e-7) && relative_eq!(&c * &iq, UnitComplex::identity(), epsilon = 1.0e-7) && relative_eq!(c * &iq, UnitComplex::identity(), epsilon = 1.0e-7) && relative_eq!(&c * iq, UnitComplex::identity(), epsilon = 1.0e-7) && relative_eq!(c * iq, UnitComplex::identity(), epsilon = 1.0e-7)) } /* * * Quaternion * Vector == Rotation * Vector * */ #[test] fn unit_complex_mul_vector(c in unit_complex(), v in vector2(), p in point2()) { let r = c.to_rotation_matrix(); prop_assert!(relative_eq!(c * v, r * v, epsilon = 1.0e-7)); prop_assert!(relative_eq!(c * p, r * p, epsilon = 1.0e-7)); } // Test that all operators (incl. all combinations of references) work. // See the top comment on `geometry/quaternion_ops.rs` for details on which operations are // supported. #[test] #[cfg_attr(rustfmt, rustfmt_skip)] fn all_op_exist( uc in unit_complex(), v in vector2(), p in point2(), r in rotation2() ) { let uv = Unit::new_normalize(v); let ucMuc = uc * uc; let ucMr = uc * r; let rMuc = r * uc; let ucDuc = uc / uc; let ucDr = uc / r; let rDuc = r / uc; let ucMp = uc * p; let ucMv = uc * v; let ucMuv = uc * uv; let mut ucMuc1 = uc; let mut ucMuc2 = uc; let mut ucMr1 = uc; let mut ucMr2 = uc; let mut ucDuc1 = uc; let mut ucDuc2 = uc; let mut ucDr1 = uc; let mut ucDr2 = uc; ucMuc1 *= uc; ucMuc2 *= &uc; ucMr1 *= r; ucMr2 *= &r; ucDuc1 /= uc; ucDuc2 /= &uc; ucDr1 /= r; ucDr2 /= &r; prop_assert!(ucMuc1 == ucMuc && ucMuc1 == ucMuc2 && ucMr1 == ucMr && ucMr1 == ucMr2 && ucDuc1 == ucDuc && ucDuc1 == ucDuc2 && ucDr1 == ucDr && ucDr1 == ucDr2 && ucMuc == &uc * &uc && ucMuc == uc * &uc && ucMuc == &uc * uc && ucMr == &uc * &r && ucMr == uc * &r && ucMr == &uc * r && rMuc == &r * &uc && rMuc == r * &uc && rMuc == &r * uc && ucDuc == &uc / &uc && ucDuc == uc / &uc && ucDuc == &uc / uc && ucDr == &uc / &r && ucDr == uc / &r && ucDr == &uc / r && rDuc == &r / &uc && rDuc == r / &uc && rDuc == &r / uc && ucMp == &uc * &p && ucMp == uc * &p && ucMp == &uc * p && ucMv == &uc * &v && ucMv == uc * &v && ucMv == &uc * v && ucMuv == &uc * &uv && ucMuv == uc * &uv && ucMuv == &uc * uv) } );