use crate::math::{Real, Vector2, Vector3};
#[cfg(feature = "simd-is-enabled")]
use {
crate::math::{SimdBool, SimdReal},
simba::simd::SimdValue,
};
#[cfg(feature = "simd-is-enabled")]
#[allow(dead_code)]
pub fn simd_swap(do_swap: SimdBool, a: &mut SimdReal, b: &mut SimdReal) {
let _a = *a;
*a = b.select(do_swap, *a);
*b = _a.select(do_swap, *b);
}
pub trait WSign<Rhs>: Sized {
fn copy_sign_to(self, to: Rhs) -> Rhs;
}
impl WSign<Real> for Real {
fn copy_sign_to(self, to: Self) -> Self {
let minus_zero: Real = -0.0;
let signbit = minus_zero.to_bits();
Real::from_bits((signbit & self.to_bits()) | ((!signbit) & to.to_bits()))
}
}
impl WSign<Vector2> for Real {
fn copy_sign_to(self, to: Vector2) -> Vector2 {
Vector2::new(self.copy_sign_to(to.x), self.copy_sign_to(to.y))
}
}
impl WSign<Vector3> for Real {
fn copy_sign_to(self, to: Vector3) -> Vector3 {
Vector3::new(
self.copy_sign_to(to.x),
self.copy_sign_to(to.y),
self.copy_sign_to(to.z),
)
}
}
impl WSign<Vector2> for Vector2 {
fn copy_sign_to(self, to: Vector2) -> Vector2 {
Vector2::new(self.x.copy_sign_to(to.x), self.y.copy_sign_to(to.y))
}
}
impl WSign<Vector3> for Vector3 {
fn copy_sign_to(self, to: Vector3) -> Vector3 {
Vector3::new(
self.x.copy_sign_to(to.x),
self.y.copy_sign_to(to.y),
self.z.copy_sign_to(to.z),
)
}
}
#[cfg(feature = "simd-is-enabled")]
impl WSign<SimdReal> for SimdReal {
fn copy_sign_to(self, to: SimdReal) -> SimdReal {
use simba::simd::SimdRealField;
to.simd_copysign(self)
}
}
pub trait WBasis: Sized {
type Basis;
fn orthonormal_basis(self) -> Self::Basis;
}
impl WBasis for Vector2 {
type Basis = [Vector2; 1];
fn orthonormal_basis(self) -> [Vector2; 1] {
[Vector2::new(-self.y, self.x)]
}
}
impl WBasis for Vector3 {
type Basis = [Vector3; 2];
fn orthonormal_basis(self) -> [Vector3; 2] {
let sign = self.z.copy_sign_to(1.0);
let a = -1.0 / (sign + self.z);
let b = self.x * self.y * a;
[
Vector3::new(1.0 + sign * self.x * self.x * a, sign * b, -sign * self.x),
Vector3::new(b, sign + self.y * self.y * a, -self.y),
]
}
}
pub(crate) trait WCross<Rhs>: Sized {
type Result;
fn gcross(&self, rhs: Rhs) -> Self::Result;
}
impl WCross<Vector3> for Vector3 {
type Result = Self;
fn gcross(&self, rhs: Vector3) -> Self::Result {
self.cross(rhs)
}
}
impl WCross<Vector2> for Vector2 {
type Result = Real;
fn gcross(&self, rhs: Vector2) -> Self::Result {
self.x * rhs.y - self.y * rhs.x
}
}
impl WCross<Vector2> for Real {
type Result = Vector2;
fn gcross(&self, rhs: Vector2) -> Self::Result {
Vector2::new(-rhs.y * *self, rhs.x * *self)
}
}