1use crate::math::{Real, Vector2, Vector3};
4
5#[cfg(feature = "simd-is-enabled")]
6use {
7 crate::math::{SimdBool, SimdReal},
8 simba::simd::SimdValue,
9};
10
11#[cfg(feature = "simd-is-enabled")]
12#[allow(dead_code)]
13pub fn simd_swap(do_swap: SimdBool, a: &mut SimdReal, b: &mut SimdReal) {
18 let _a = *a;
19 *a = b.select(do_swap, *a);
20 *b = _a.select(do_swap, *b);
21}
22
23pub trait WSign<Rhs>: Sized {
25 fn copy_sign_to(self, to: Rhs) -> Rhs;
28}
29
30impl WSign<Real> for Real {
31 fn copy_sign_to(self, to: Self) -> Self {
32 let minus_zero: Real = -0.0;
33 let signbit = minus_zero.to_bits();
34 Real::from_bits((signbit & self.to_bits()) | ((!signbit) & to.to_bits()))
35 }
36}
37
38impl WSign<Vector2> for Real {
39 fn copy_sign_to(self, to: Vector2) -> Vector2 {
40 Vector2::new(self.copy_sign_to(to.x), self.copy_sign_to(to.y))
41 }
42}
43
44impl WSign<Vector3> for Real {
45 fn copy_sign_to(self, to: Vector3) -> Vector3 {
46 Vector3::new(
47 self.copy_sign_to(to.x),
48 self.copy_sign_to(to.y),
49 self.copy_sign_to(to.z),
50 )
51 }
52}
53
54impl WSign<Vector2> for Vector2 {
55 fn copy_sign_to(self, to: Vector2) -> Vector2 {
56 Vector2::new(self.x.copy_sign_to(to.x), self.y.copy_sign_to(to.y))
57 }
58}
59
60impl WSign<Vector3> for Vector3 {
61 fn copy_sign_to(self, to: Vector3) -> Vector3 {
62 Vector3::new(
63 self.x.copy_sign_to(to.x),
64 self.y.copy_sign_to(to.y),
65 self.z.copy_sign_to(to.z),
66 )
67 }
68}
69
70#[cfg(feature = "simd-is-enabled")]
71impl WSign<SimdReal> for SimdReal {
72 fn copy_sign_to(self, to: SimdReal) -> SimdReal {
73 use simba::simd::SimdRealField;
74 to.simd_copysign(self)
75 }
76}
77
78pub trait WBasis: Sized {
80 type Basis;
82 fn orthonormal_basis(self) -> Self::Basis;
84}
85
86impl WBasis for Vector2 {
87 type Basis = [Vector2; 1];
88 fn orthonormal_basis(self) -> [Vector2; 1] {
89 [Vector2::new(-self.y, self.x)]
90 }
91}
92
93impl WBasis for Vector3 {
94 type Basis = [Vector3; 2];
95 fn orthonormal_basis(self) -> [Vector3; 2] {
98 let sign = self.z.copy_sign_to(1.0);
99 let a = -1.0 / (sign + self.z);
100 let b = self.x * self.y * a;
101
102 [
103 Vector3::new(1.0 + sign * self.x * self.x * a, sign * b, -sign * self.x),
104 Vector3::new(b, sign + self.y * self.y * a, -self.y),
105 ]
106 }
107}
108
109pub(crate) trait WCross<Rhs>: Sized {
110 type Result;
111 fn gcross(&self, rhs: Rhs) -> Self::Result;
112}
113
114impl WCross<Vector3> for Vector3 {
115 type Result = Self;
116
117 fn gcross(&self, rhs: Vector3) -> Self::Result {
118 self.cross(rhs)
119 }
120}
121
122impl WCross<Vector2> for Vector2 {
123 type Result = Real;
124
125 fn gcross(&self, rhs: Vector2) -> Self::Result {
126 self.x * rhs.y - self.y * rhs.x
127 }
128}
129
130impl WCross<Vector2> for Real {
131 type Result = Vector2;
132
133 fn gcross(&self, rhs: Vector2) -> Self::Result {
134 Vector2::new(-rhs.y * *self, rhs.x * *self)
135 }
136}