use nalgebra::{Const, DimMin, Point, RealField, SMatrix, Scalar};
use num_traits::NumOps;
#[cfg_attr(
feature = "tracing",
tracing::instrument("Calculate Distance Squared", skip_all, level = "trace")
)]
pub(crate) fn distance_squared<T, const N: usize>(point_a: &Point<T, N>, point_b: &Point<T, N>) -> T
where
T: Copy + Default + NumOps + Scalar,
{
point_a
.iter()
.zip(point_b.iter())
.map(|(&x, &y)| {
let diff = x - y;
diff * diff
})
.fold(T::default(), |acc, x| acc + x)
}
#[cfg_attr(
feature = "tracing",
tracing::instrument("Verify Matrix Determinant", skip_all, level = "info")
)]
pub(crate) fn verify_rotation_matrix_determinant<T, const N: usize>(
mut u: SMatrix<T, N, N>,
v_t: SMatrix<T, N, N>,
) -> SMatrix<T, N, N>
where
T: Copy + RealField,
Const<N>: DimMin<Const<N>, Output = Const<N>>,
{
if (u * v_t).determinant() < T::zero() {
u.column_mut(N - 1)
.iter_mut()
.for_each(|element| *element *= T::one().neg()); }
u * v_t
}
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use nalgebra::{Matrix2, Point3};
#[test]
fn test_distance_squared() {
let point_a = Point3::new(1.0, 2.0, 3.0);
let point_b = Point3::new(4.0, 5.0, 6.0);
assert_eq!(distance_squared(&point_a, &point_b), 27.0)
}
#[test]
fn test_verify_rotation_matrix_determinant() {
let mat_a = Matrix2::new(2.0, 3.0, 2.0, 1.0);
let mat_b = Matrix2::new(-1.0, 0.0, 0.0, -1.0);
let regular_dot = mat_a * mat_b;
assert!(regular_dot.determinant() < 0.0);
let func_dot = verify_rotation_matrix_determinant(mat_a, mat_b);
assert!(func_dot.determinant() >= 0.0);
assert_eq!(func_dot.m12, -regular_dot.m12);
assert_eq!(func_dot.m22, -regular_dot.m22);
}
}