//! Miscellaneous utilities.
use na::{
Matrix1, Matrix2, Matrix3, Point2, Point3, RowVector2, Scalar, SimdRealField, UnitComplex,
UnitQuaternion, Vector1, Vector2, Vector3,
};
use num::Zero;
use simba::simd::SimdValue;
use std::ops::IndexMut;
use parry::utils::SdpMatrix3;
use {
crate::math::{Real, SimdReal},
na::SimdPartialOrd,
num::One,
};
/// The trait for real numbers used by Rapier.
///
/// This includes `f32`, `f64` and their related SIMD types.
pub trait WReal: SimdRealField<Element = Real> + Copy {}
impl WReal for Real {}
impl WReal for SimdReal {}
const INV_EPSILON: Real = 1.0e-20;
pub(crate) fn inv(val: Real) -> Real {
if val >= -INV_EPSILON && val <= INV_EPSILON {
0.0
} else {
1.0 / val
}
}
pub(crate) fn simd_inv<N: WReal>(val: N) -> N {
let eps = N::splat(INV_EPSILON);
N::zero().select(val.simd_gt(-eps) & val.simd_lt(eps), N::one() / val)
}
/// Trait to copy the sign of each component of one scalar/vector/matrix to another.
pub trait WSign<Rhs>: Sized {
// See SIMD implementations of copy_sign there: https://stackoverflow.com/a/57872652
/// Copy the sign of each component of `self` to the corresponding component of `to`.
fn copy_sign_to(self, to: Rhs) -> Rhs;
}
impl WSign<Real> for Real {
fn copy_sign_to(self, to: Self) -> Self {
const MINUS_ZERO: Real = -0.0;
let signbit = MINUS_ZERO.to_bits();
Real::from_bits((signbit & self.to_bits()) | ((!signbit) & to.to_bits()))
}
}
impl<N: Scalar + Copy + WSign<N>> WSign<Vector2<N>> for N {
fn copy_sign_to(self, to: Vector2<N>) -> Vector2<N> {
Vector2::new(self.copy_sign_to(to.x), self.copy_sign_to(to.y))
}
}
impl<N: Scalar + Copy + WSign<N>> WSign<Vector3<N>> for N {
fn copy_sign_to(self, to: Vector3<N>) -> Vector3<N> {
Vector3::new(
self.copy_sign_to(to.x),
self.copy_sign_to(to.y),
self.copy_sign_to(to.z),
)
}
}
impl<N: Scalar + Copy + WSign<N>> WSign<Vector2<N>> for Vector2<N> {
fn copy_sign_to(self, to: Vector2<N>) -> Vector2<N> {
Vector2::new(self.x.copy_sign_to(to.x), self.y.copy_sign_to(to.y))
}
}
impl<N: Scalar + Copy + WSign<N>> WSign<Vector3<N>> for Vector3<N> {
fn copy_sign_to(self, to: Vector3<N>) -> Vector3<N> {
Vector3::new(
self.x.copy_sign_to(to.x),
self.y.copy_sign_to(to.y),
self.z.copy_sign_to(to.z),
)
}
}
impl WSign<SimdReal> for SimdReal {
fn copy_sign_to(self, to: SimdReal) -> SimdReal {
to.simd_copysign(self)
}
}
pub(crate) trait WComponent: Sized {
type Element;
fn min_component(self) -> Self::Element;
fn max_component(self) -> Self::Element;
}
impl WComponent for Real {
type Element = Real;
fn min_component(self) -> Self::Element {
self
}
fn max_component(self) -> Self::Element {
self
}
}
impl WComponent for SimdReal {
type Element = Real;
fn min_component(self) -> Self::Element {
self.simd_horizontal_min()
}
fn max_component(self) -> Self::Element {
self.simd_horizontal_max()
}
}
/// Trait to compute the orthonormal basis of a vector.
pub trait WBasis: Sized {
/// The type of the array of orthonormal vectors.
type Basis;
/// Computes the vectors which, when combined with `self`, form an orthonormal basis.
fn orthonormal_basis(self) -> Self::Basis;
/// Computes a vector orthogonal to `self` with a unit length (if `self` has a unit length).
fn orthonormal_vector(self) -> Self;
}
impl<N: WReal> WBasis for Vector2<N> {
type Basis = [Vector2<N>; 1];
fn orthonormal_basis(self) -> [Vector2<N>; 1] {
[Vector2::new(-self.y, self.x)]
}
fn orthonormal_vector(self) -> Vector2<N> {
Vector2::new(-self.y,