use crate::{
nums::num_traits::*, Affine2, Affine2x4, Affine3A, Affine3x4, DAffine2, DAffine3, DIsometry3,
DMat2, DMat3, DMat4, DPoint2, DPoint3, DPoint4, DQuat, DVec2, DVec3, DVec4, Isometry3,
Isometry3x4, Mat2, Mat2x4, Mat3, Mat3A, Mat3x4, Mat4, Mat4x4, Point2, Point2x4, Point3,
Point3A, Point3x4, Point4, Point4x4, Quat, Quatx4, UnitDQuat, UnitDVec2, UnitDVec3, UnitDVec4,
UnitQuat, UnitQuatx4, UnitVec2, UnitVec2x4, UnitVec3, UnitVec3A, UnitVec3x4, UnitVec4,
UnitVec4x4, Vec2, Vec2x4, Vec3, Vec3A, Vec3x4, Vec4, Vec4x4,
};
use approx_det::{AbsDiffEq, RelativeEq, UlpsEq};
macro_rules! impl_approx_as_ref {
($prim:ident, $type:ty) => {
impl AbsDiffEq for $type {
type Epsilon = <$prim as AbsDiffEq>::Epsilon;
fn default_epsilon() -> Self::Epsilon {
$prim::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
self.as_ref().abs_diff_eq(other.as_ref(), epsilon)
}
}
impl RelativeEq for $type {
fn default_max_relative() -> Self::Epsilon {
$prim::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
self.as_ref()
.relative_eq(other.as_ref(), epsilon, max_relative)
}
}
impl UlpsEq for $type {
fn default_max_ulps() -> u32 {
$prim::default_max_ulps()
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
self.as_ref().ulps_eq(other.as_ref(), epsilon, max_ulps)
}
}
};
}
macro_rules! impl_approx_soa_as_ref {
($prim:ident, $type:ty) => {
impl AbsDiffEq for $type {
type Epsilon = <$prim as AbsDiffEq>::Epsilon;
fn default_epsilon() -> Self::Epsilon {
$prim::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
self.as_ref().abs_diff_eq(other.as_ref(), epsilon).all()
}
}
impl RelativeEq for $type {
fn default_max_relative() -> Self::Epsilon {
$prim::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
self.as_ref()
.relative_eq(other.as_ref(), epsilon, max_relative)
.all()
}
}
impl UlpsEq for $type {
fn default_max_ulps() -> u32 {
$prim::default_max_ulps()
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
self.as_ref()
.ulps_eq(other.as_ref(), epsilon, max_ulps)
.all()
}
}
};
}
macro_rules! impl_approx_xzy_axes {
($prim:ident, $type:ty) => {
impl AbsDiffEq for $type {
type Epsilon = <$prim as AbsDiffEq>::Epsilon;
fn default_epsilon() -> Self::Epsilon {
$prim::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
AbsDiffEq::abs_diff_eq(&self.x_axis, &other.x_axis, epsilon)
&& AbsDiffEq::abs_diff_eq(&self.y_axis, &other.y_axis, epsilon)
&& AbsDiffEq::abs_diff_eq(&self.z_axis, &other.z_axis, epsilon)
}
}
impl RelativeEq for $type {
fn default_max_relative() -> Self::Epsilon {
$prim::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
RelativeEq::relative_eq(&self.x_axis, &other.x_axis, epsilon, max_relative)
&& RelativeEq::relative_eq(&self.y_axis, &other.y_axis, epsilon, max_relative)
&& RelativeEq::relative_eq(&self.z_axis, &other.z_axis, epsilon, max_relative)
}
}
impl UlpsEq for $type {
fn default_max_ulps() -> u32 {
$prim::default_max_ulps()
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
UlpsEq::ulps_eq(&self.x_axis, &other.x_axis, epsilon, max_ulps)
&& UlpsEq::ulps_eq(&self.y_axis, &other.y_axis, epsilon, max_ulps)
&& UlpsEq::ulps_eq(&self.z_axis, &other.z_axis, epsilon, max_ulps)
}
}
};
}
macro_rules! impl_approx_soa_xzy_axes {
($prim:ident, $type:ty) => {
impl AbsDiffEq for $type {
type Epsilon = <$prim as AbsDiffEq>::Epsilon;
fn default_epsilon() -> Self::Epsilon {
$prim::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
AbsDiffEq::abs_diff_eq(&self.x_axis, &other.x_axis, epsilon).all()
&& AbsDiffEq::abs_diff_eq(&self.y_axis, &other.y_axis, epsilon).all()
&& AbsDiffEq::abs_diff_eq(&self.z_axis, &other.z_axis, epsilon).all()
}
}
impl RelativeEq for $type {
fn default_max_relative() -> Self::Epsilon {
$prim::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
RelativeEq::relative_eq(&self.x_axis, &other.x_axis, epsilon, max_relative).all()
&& RelativeEq::relative_eq(&self.y_axis, &other.y_axis, epsilon, max_relative)
.all()
&& RelativeEq::relative_eq(&self.z_axis, &other.z_axis, epsilon, max_relative)
.all()
}
}
impl UlpsEq for $type {
fn default_max_ulps() -> u32 {
$prim::default_max_ulps()
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
UlpsEq::ulps_eq(&self.x_axis, &other.x_axis, epsilon, max_ulps).all()
&& UlpsEq::ulps_eq(&self.y_axis, &other.y_axis, epsilon, max_ulps).all()
&& UlpsEq::ulps_eq(&self.z_axis, &other.z_axis, epsilon, max_ulps).all()
}
}
};
}
macro_rules! impl_approx_xzyw_axes {
($prim:ident, $type:ty) => {
impl AbsDiffEq for $type {
type Epsilon = <$prim as AbsDiffEq>::Epsilon;
fn default_epsilon() -> Self::Epsilon {
$prim::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
AbsDiffEq::abs_diff_eq(&self.x_axis, &other.x_axis, epsilon)
&& AbsDiffEq::abs_diff_eq(&self.y_axis, &other.y_axis, epsilon)
&& AbsDiffEq::abs_diff_eq(&self.z_axis, &other.z_axis, epsilon)
&& AbsDiffEq::abs_diff_eq(&self.w_axis, &other.w_axis, epsilon)
}
}
impl RelativeEq for $type {
fn default_max_relative() -> Self::Epsilon {
$prim::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
RelativeEq::relative_eq(&self.x_axis, &other.x_axis, epsilon, max_relative)
&& RelativeEq::relative_eq(&self.y_axis, &other.y_axis, epsilon, max_relative)
&& RelativeEq::relative_eq(&self.z_axis, &other.z_axis, epsilon, max_relative)
&& RelativeEq::relative_eq(&self.w_axis, &other.w_axis, epsilon, max_relative)
}
}
impl UlpsEq for $type {
fn default_max_ulps() -> u32 {
$prim::default_max_ulps()
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
UlpsEq::ulps_eq(&self.x_axis, &other.x_axis, epsilon, max_ulps)
&& UlpsEq::ulps_eq(&self.y_axis, &other.y_axis, epsilon, max_ulps)
&& UlpsEq::ulps_eq(&self.z_axis, &other.z_axis, epsilon, max_ulps)
&& UlpsEq::ulps_eq(&self.w_axis, &other.w_axis, epsilon, max_ulps)
}
}
};
}
macro_rules! impl_approx_soa_xzyw_axes {
($prim:ident, $type:ty) => {
impl AbsDiffEq for $type {
type Epsilon = <$prim as AbsDiffEq>::Epsilon;
fn default_epsilon() -> Self::Epsilon {
$prim::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
AbsDiffEq::abs_diff_eq(&self.x_axis, &other.x_axis, epsilon).all()
&& AbsDiffEq::abs_diff_eq(&self.y_axis, &other.y_axis, epsilon).all()
&& AbsDiffEq::abs_diff_eq(&self.z_axis, &other.z_axis, epsilon).all()
&& AbsDiffEq::abs_diff_eq(&self.w_axis, &other.w_axis, epsilon).all()
}
}
impl RelativeEq for $type {
fn default_max_relative() -> Self::Epsilon {
$prim::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
RelativeEq::relative_eq(&self.x_axis, &other.x_axis, epsilon, max_relative).all()
&& RelativeEq::relative_eq(&self.y_axis, &other.y_axis, epsilon, max_relative)
.all()
&& RelativeEq::relative_eq(&self.z_axis, &other.z_axis, epsilon, max_relative)
.all()
&& RelativeEq::relative_eq(&self.w_axis, &other.w_axis, epsilon, max_relative)
.all()
}
}
impl UlpsEq for $type {
fn default_max_ulps() -> u32 {
$prim::default_max_ulps()
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
UlpsEq::ulps_eq(&self.x_axis, &other.x_axis, epsilon, max_ulps).all()
&& UlpsEq::ulps_eq(&self.y_axis, &other.y_axis, epsilon, max_ulps).all()
&& UlpsEq::ulps_eq(&self.z_axis, &other.z_axis, epsilon, max_ulps).all()
&& UlpsEq::ulps_eq(&self.w_axis, &other.w_axis, epsilon, max_ulps).all()
}
}
};
}
macro_rules! impl_approx_for_unit {
($unit_type:ty, $general_type:ty, $cast_fn:ident) => {
impl AbsDiffEq for $unit_type {
type Epsilon = <$general_type as AbsDiffEq>::Epsilon;
fn default_epsilon() -> Self::Epsilon {
<$general_type>::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
<$general_type as AbsDiffEq>::abs_diff_eq(
&self.$cast_fn(),
&other.$cast_fn(),
epsilon,
)
}
}
impl RelativeEq for $unit_type {
fn default_max_relative() -> Self::Epsilon {
<$general_type>::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
<$general_type as RelativeEq>::relative_eq(
&self.$cast_fn(),
&other.$cast_fn(),
epsilon,
max_relative,
)
}
}
impl UlpsEq for $unit_type {
fn default_max_ulps() -> u32 {
<$general_type>::default_max_ulps()
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
<$general_type as UlpsEq>::ulps_eq(
&self.$cast_fn(),
&other.$cast_fn(),
epsilon,
max_ulps,
)
}
}
};
}
macro_rules! impl_approx_isometry {
($prim:ident, $type:ty) => {
impl AbsDiffEq for $type {
type Epsilon = <$prim as AbsDiffEq>::Epsilon;
fn default_epsilon() -> Self::Epsilon {
$prim::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
AbsDiffEq::abs_diff_eq(&self.rotation, &other.rotation, epsilon)
&& AbsDiffEq::abs_diff_eq(&self.translation, &other.translation, epsilon)
}
}
impl RelativeEq for $type {
fn default_max_relative() -> Self::Epsilon {
$prim::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
RelativeEq::relative_eq(&self.rotation, &other.rotation, epsilon, max_relative)
&& RelativeEq::relative_eq(
&self.translation,
&other.translation,
epsilon,
max_relative,
)
}
}
impl UlpsEq for $type {
fn default_max_ulps() -> u32 {
$prim::default_max_ulps()
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
UlpsEq::ulps_eq(&self.rotation, &other.rotation, epsilon, max_ulps)
&& UlpsEq::ulps_eq(&self.translation, &other.translation, epsilon, max_ulps)
}
}
};
}
macro_rules! impl_approx_soa_isometry {
($prim:ident, $type:ty) => {
impl AbsDiffEq for $type {
type Epsilon = <$prim as AbsDiffEq>::Epsilon;
fn default_epsilon() -> Self::Epsilon {
$prim::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
AbsDiffEq::abs_diff_eq(&self.rotation, &other.rotation, epsilon).all()
&& AbsDiffEq::abs_diff_eq(&self.translation, &other.translation, epsilon).all()
}
}
impl RelativeEq for $type {
fn default_max_relative() -> Self::Epsilon {
$prim::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
RelativeEq::relative_eq(&self.rotation, &other.rotation, epsilon, max_relative)
.all()
&& RelativeEq::relative_eq(
&self.translation,
&other.translation,
epsilon,
max_relative,
)
.all()
}
}
impl UlpsEq for $type {
fn default_max_ulps() -> u32 {
$prim::default_max_ulps()
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
UlpsEq::ulps_eq(&self.rotation, &other.rotation, epsilon, max_ulps).all()
&& UlpsEq::ulps_eq(&self.translation, &other.translation, epsilon, max_ulps)
.all()
}
}
};
}
impl_approx_as_ref!(f32, crate::nums::f32x4);
impl_approx_as_ref!(f32, Mat2);
impl_approx_as_ref!(f32, Mat3);
impl_approx_as_ref!(f32, Mat4);
impl_approx_as_ref!(f32, Quat);
impl_approx_as_ref!(f32, Vec2);
impl_approx_as_ref!(f32, Vec3);
impl_approx_as_ref!(f32, Vec4);
impl_approx_as_ref!(f32, Vec3A);
impl_approx_xzy_axes!(f32, Affine2);
impl_approx_xzyw_axes!(f32, Affine3A);
impl_approx_xzy_axes!(f32, Mat3A);
impl_approx_xzy_axes!(f64, DAffine2);
impl_approx_xzyw_axes!(f64, DAffine3);
impl_approx_as_ref!(f64, DMat2);
impl_approx_as_ref!(f64, DMat3);
impl_approx_as_ref!(f64, DMat4);
impl_approx_as_ref!(f64, DQuat);
impl_approx_as_ref!(f64, DVec2);
impl_approx_as_ref!(f64, DVec3);
impl_approx_as_ref!(f64, DVec4);
impl_approx_as_ref!(f32, Point2);
impl_approx_as_ref!(f32, Point3);
impl_approx_as_ref!(f32, Point4);
impl_approx_as_ref!(f32, Point3A);
impl_approx_as_ref!(f64, DPoint2);
impl_approx_as_ref!(f64, DPoint3);
impl_approx_as_ref!(f64, DPoint4);
impl_approx_for_unit!(UnitQuat, Quat, as_quat);
impl_approx_for_unit!(UnitVec2, Vec2, as_vec2);
impl_approx_for_unit!(UnitVec3, Vec3, as_vec3);
impl_approx_for_unit!(UnitVec3A, Vec3A, as_vec3a);
impl_approx_for_unit!(UnitVec4, Vec4, as_vec4);
impl_approx_for_unit!(UnitDQuat, DQuat, as_dquat);
impl_approx_for_unit!(UnitDVec2, DVec2, as_dvec2);
impl_approx_for_unit!(UnitDVec3, DVec3, as_dvec3);
impl_approx_for_unit!(UnitDVec4, DVec4, as_dvec4);
impl_approx_soa_as_ref!(Mat2, Mat2x4);
impl_approx_soa_as_ref!(Mat3, Mat3x4);
impl_approx_soa_as_ref!(Mat4, Mat4x4);
impl_approx_soa_as_ref!(Quat, Quatx4);
impl_approx_soa_as_ref!(Vec2, Vec2x4);
impl_approx_soa_as_ref!(Vec3, Vec3x4);
impl_approx_soa_as_ref!(Vec4, Vec4x4);
impl_approx_soa_xzy_axes!(Affine2, Affine2x4);
impl_approx_soa_xzyw_axes!(Affine3A, Affine3x4);
impl_approx_soa_as_ref!(Point2, Point2x4);
impl_approx_soa_as_ref!(Point3, Point3x4);
impl_approx_soa_as_ref!(Point4, Point4x4);
impl_approx_for_unit!(UnitQuatx4, Quatx4, as_quatx4);
impl_approx_for_unit!(UnitVec2x4, Vec2x4, as_vec2x4);
impl_approx_for_unit!(UnitVec3x4, Vec3x4, as_vec3x4);
impl_approx_for_unit!(UnitVec4x4, Vec4x4, as_vec4x4);
impl_approx_isometry!(f32, Isometry3);
impl_approx_isometry!(f64, DIsometry3);
impl_approx_soa_isometry!(Isometry3, Isometry3x4);
#[cfg(test)]
mod test {
use crate::nums::num_traits::*;
use crate::*;
use approx_det::*;
macro_rules! impl_approx_test {
($prim:ident, $type:ident, $ones:expr) => {
let one_eps = $ones * $type::default_epsilon();
let two_eps = one_eps + one_eps;
let one_ulp = $ones * $prim::from_bits($prim::to_bits(1.0) + 1);
let four_ulp = $ones * $prim::from_bits($prim::to_bits(1.0) + 16);
approx_det::assert_abs_diff_eq!($ones, $ones);
approx_det::assert_abs_diff_eq!($ones, $ones + one_eps);
approx_det::assert_abs_diff_eq!($ones, $ones - one_eps);
approx_det::assert_abs_diff_ne!($ones, $ones + two_eps);
approx_det::assert_abs_diff_ne!($ones, $ones - two_eps);
approx_det::assert_relative_eq!($ones, $ones);
approx_det::assert_relative_ne!($ones, $ones - $ones);
approx_det::assert_ulps_eq!($ones, one_ulp);
approx_det::assert_ulps_ne!($ones, four_ulp);
};
($prim:ident, $type:ident) => {
impl_approx_test!($prim, $type, $type::ONE)
};
}
macro_rules! impl_approx_soa_test {
($prim:ident, $soa_prim:ident, $type:ident, $ones:expr) => {
let one_eps = $ones * nums::$soa_prim::const_splat($type::default_epsilon());
let two_eps = one_eps + one_eps;
let one_ulp =
$ones * nums::$soa_prim::const_splat($prim::from_bits($prim::to_bits(1.0) + 1));
let four_ulp =
$ones * nums::$soa_prim::const_splat($prim::from_bits($prim::to_bits(1.0) + 16));
approx_det::assert_abs_diff_eq!($ones, $ones);
approx_det::assert_abs_diff_eq!($ones, $ones + one_eps);
approx_det::assert_abs_diff_eq!($ones, $ones - one_eps);
approx_det::assert_abs_diff_ne!($ones, $ones + two_eps);
approx_det::assert_abs_diff_ne!($ones, $ones - two_eps);
approx_det::assert_relative_eq!($ones, $ones);
approx_det::assert_relative_ne!($ones, $ones - $ones);
approx_det::assert_ulps_eq!($ones, one_ulp);
approx_det::assert_ulps_ne!($ones, four_ulp);
};
($prim:ident, $soa_prim:ident, $type:ident) => {
impl_approx_soa_test!($prim, $soa_prim, $type, $type::ONE)
};
}
macro_rules! impl_approx_point_test {
($prim:ident, $type:ident, $ones:expr) => {
let one_eps = $ones.0 * $type::default_epsilon();
let two_eps = one_eps + one_eps;
let one_ulp = $ones.0 * $prim::from_bits($prim::to_bits(1.0) + 1);
let four_ulp = $ones.0 * $prim::from_bits($prim::to_bits(1.0) + 16);
approx_det::assert_abs_diff_eq!($ones, $ones);
approx_det::assert_abs_diff_eq!($ones, $ones + one_eps);
approx_det::assert_abs_diff_eq!($ones, $ones - one_eps);
approx_det::assert_abs_diff_ne!($ones, $ones + two_eps);
approx_det::assert_abs_diff_ne!($ones, $ones - two_eps);
approx_det::assert_relative_eq!($ones, $ones);
approx_det::assert_relative_ne!($ones.0, $ones - $ones);
approx_det::assert_ulps_eq!($ones.0, one_ulp);
approx_det::assert_ulps_ne!($ones.0, four_ulp);
};
($prim:ident, $type:ident) => {
impl_approx_point_test!($prim, $type, $type::ONE)
};
}
macro_rules! impl_approx_unit_test {
($prim:ident, $type:ident, $ones:expr) => {
let one_eps = $ones * $type::default_epsilon();
let two_eps = one_eps + one_eps;
let zero = one_eps - one_eps;
let one_ulp = $ones * $prim::from_bits($prim::to_bits(1.0) + 1);
let four_ulp = $ones * $prim::from_bits($prim::to_bits(1.0) + 16);
approx_det::assert_abs_diff_eq!($ones, $ones);
approx_det::assert_abs_diff_eq!($ones + zero, $ones + one_eps);
approx_det::assert_abs_diff_eq!($ones + zero, $ones - one_eps);
approx_det::assert_abs_diff_ne!($ones + zero, $ones + two_eps);
approx_det::assert_abs_diff_ne!($ones + zero, $ones - two_eps);
approx_det::assert_relative_eq!($ones, $ones);
approx_det::assert_relative_ne!($ones + zero, $ones - $ones);
approx_det::assert_ulps_eq!($ones + zero, one_ulp);
approx_det::assert_ulps_ne!($ones + zero, four_ulp);
};
}
macro_rules! impl_approx_unit_quat_test {
($prim:ident, $type:ident, $ones:expr, $cast_fn:ident) => {
let one_eps = $ones.$cast_fn() * $type::default_epsilon();
let two_eps = one_eps + one_eps;
let one_ulp = $ones.$cast_fn() * $prim::from_bits($prim::to_bits(1.0) + 1);
let four_ulp = $ones.$cast_fn() * $prim::from_bits($prim::to_bits(1.0) + 16);
approx_det::assert_abs_diff_eq!($ones, $ones);
approx_det::assert_abs_diff_eq!($ones.$cast_fn(), $ones.$cast_fn() + one_eps);
approx_det::assert_abs_diff_eq!($ones.$cast_fn(), $ones.$cast_fn() - one_eps);
approx_det::assert_abs_diff_ne!($ones.$cast_fn(), $ones.$cast_fn() + two_eps);
approx_det::assert_abs_diff_ne!($ones.$cast_fn(), $ones.$cast_fn() - two_eps);
approx_det::assert_relative_eq!($ones, $ones);
approx_det::assert_relative_ne!($ones.$cast_fn(), $ones.$cast_fn() - $ones.$cast_fn());
approx_det::assert_ulps_eq!($ones.$cast_fn(), one_ulp);
approx_det::assert_ulps_ne!($ones.$cast_fn(), four_ulp);
};
}
#[test]
fn test_approx_1() {
const ONESF32: [f32; 16] = [1.0; 16];
impl_approx_test!(f32, Vec2);
impl_approx_test!(f32, Vec3);
impl_approx_test!(f32, Vec3A);
impl_approx_test!(f32, Vec4);
impl_approx_test!(f32, Quat, Quat::from_slice(&ONESF32));
impl_approx_test!(f32, Mat2, Mat2::from_cols_slice(&ONESF32));
impl_approx_test!(f32, Mat3, Mat3::from_cols_slice(&ONESF32));
impl_approx_test!(f32, Mat3A, Mat3A::from_cols_slice(&ONESF32));
impl_approx_test!(f32, Mat4, Mat4::from_cols_slice(&ONESF32));
const ONESF64: [f64; 16] = [1.0; 16];
impl_approx_test!(f64, DVec2);
impl_approx_test!(f64, DVec3);
impl_approx_test!(f64, DVec4);
impl_approx_test!(f64, DQuat, DQuat::from_slice(&ONESF64));
impl_approx_test!(f64, DMat2, DMat2::from_cols_slice(&ONESF64));
impl_approx_test!(f64, DMat3, DMat3::from_cols_slice(&ONESF64));
impl_approx_test!(f64, DMat4, DMat4::from_cols_slice(&ONESF64));
}
#[test]
fn test_approx_2() {
impl_approx_point_test!(f32, Point2);
impl_approx_point_test!(f32, Point3);
impl_approx_point_test!(f32, Point3A);
impl_approx_point_test!(f32, Point4);
impl_approx_point_test!(f64, DPoint2);
impl_approx_point_test!(f64, DPoint3);
impl_approx_point_test!(f64, DPoint4);
impl_approx_unit_test!(f32, UnitVec2, UnitVec2::X);
impl_approx_unit_test!(f32, UnitVec3, UnitVec3::X);
impl_approx_unit_test!(f32, UnitVec4, UnitVec4::X);
impl_approx_unit_test!(f32, UnitVec3A, UnitVec3A::X);
impl_approx_unit_test!(f64, UnitDVec2, UnitDVec2::X);
impl_approx_unit_test!(f64, UnitDVec3, UnitDVec3::X);
impl_approx_unit_test!(f64, UnitDVec4, UnitDVec4::X);
impl_approx_unit_quat_test!(f32, UnitQuat, UnitQuat::IDENTITY, as_quat);
impl_approx_unit_quat_test!(f64, UnitDQuat, UnitDQuat::IDENTITY, as_dquat);
}
#[test]
fn test_approx_3() {
const ONESF32X4: [nums::f32x4; 16] = [nums::f32x4::ONE; 16];
impl_approx_soa_test!(f32, f32x4, Vec2x4);
impl_approx_soa_test!(f32, f32x4, Vec3x4);
impl_approx_soa_test!(f32, f32x4, Vec4x4);
impl_approx_soa_test!(f32, f32x4, Quatx4, Quatx4::from_slice(&ONESF32X4));
impl_approx_soa_test!(f32, f32x4, Mat2x4, Mat2x4::from_cols_slice(&ONESF32X4));
impl_approx_soa_test!(f32, f32x4, Mat3x4, Mat3x4::from_cols_slice(&ONESF32X4));
impl_approx_soa_test!(f32, f32x4, Mat4x4, Mat4x4::from_cols_slice(&ONESF32X4));
}
}