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