1pub(crate) use {
2 std::{
3 iter::Sum,
4 ops::{Add, AddAssign, BitAnd, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
5 },
6 wide::CmpNe,
7};
8
9pub use ultraviolet::{
10 f32x4, f32x8, f64x2, f64x4, DVec2, DVec2x2, DVec2x4, DVec3, DVec3x2, DVec3x4, DVec4, DVec4x2,
11 DVec4x4, Vec2, Vec2x4, Vec2x8, Vec3, Vec3x4, Vec3x8, Vec4, Vec4x4, Vec4x8,
12};
13
14pub trait Array {
16 type Item;
18}
19impl<I, const D: usize> Array for [I; D] {
20 type Item = I;
21}
22
23pub trait Zero {
25 const ZERO: Self;
27}
28
29pub trait One {
31 const ONE: Self;
33}
34
35pub trait Infinity {
37 fn infinity() -> Self;
39}
40
41pub trait FloatOps:
43 Sized
44 + Neg<Output = Self>
45 + Add<Output = Self>
46 + AddAssign
47 + Sub<Output = Self>
48 + SubAssign
49 + Mul<Output = Self>
50 + MulAssign
51 + Div<Output = Self>
52 + DivAssign
53{
54}
55impl<F> FloatOps for F where
56 F: Sized
57 + Neg<Output = Self>
58 + Add<Output = Self>
59 + AddAssign
60 + Sub<Output = Self>
61 + SubAssign
62 + Mul<Output = Self>
63 + MulAssign
64 + Div<Output = Self>
65 + DivAssign
66{
67}
68
69pub trait Float: One + Zero + Clone + Infinity + FloatOps + PartialEq {
71 #[inline]
73 fn recip(self) -> Self {
74 Self::ONE / self
75 }
76
77 fn sqrt(self) -> Self;
79
80 #[inline]
82 fn rsqrt(self) -> Self {
83 self.recip().sqrt()
84 }
85
86 fn min(self, rhs: Self) -> Self;
88
89 fn max(self, rhs: Self) -> Self;
91
92 #[inline]
94 fn mean(self, rhs: Self) -> Self {
95 (self + rhs) / (Self::ONE + Self::ONE)
96 }
97}
98
99pub trait IntoArray: Into<Self::Array> {
101 type Array: Array;
103}
104
105pub trait FloatVectorOps<F>:
107 Sized
108 + IntoArray
109 + Sum<Self>
110 + Neg<Output = Self>
111 + Add<Output = Self>
112 + AddAssign
113 + Sub<Output = Self>
114 + SubAssign
115 + Mul<F, Output = Self>
116 + MulAssign<F>
117 + Div<F, Output = Self>
118 + DivAssign<F>
119{
120}
121impl<V, F> FloatVectorOps<F> for V where
122 V: Sized
123 + IntoArray
124 + Sum<Self>
125 + Neg<Output = Self>
126 + Add<Output = Self>
127 + AddAssign
128 + Sub<Output = Self>
129 + SubAssign
130 + Mul<F, Output = Self>
131 + MulAssign<F>
132 + Div<F, Output = Self>
133 + DivAssign<F>
134{
135}
136
137pub trait FloatVector: Zero + Clone + FloatVectorOps<Self::Float> {
139 type Float;
141
142 #[doc(alias = "length_squared")]
144 #[doc(alias = "magnitude_squared")]
145 fn norm_squared(self) -> Self::Float;
146}
147
148pub trait SIMD {
150 type Element;
152
153 type Lane;
155
156 fn splat(element: Self::Element) -> Self;
158
159 fn new_lane(lane: Self::Lane) -> Self;
161}
162
163pub trait SIMDElement<const L: usize>: Sized {
165 type SIMD: SIMD<Element = Self, Lane = [Self; L]>;
167}
168
169pub trait Reduce: SIMD {
171 fn reduce_sum(self) -> Self::Element;
173}
174
175pub trait FromPrimitive<U> {
177 fn from(p: U) -> Self;
179}
180
181pub trait AsPrimitive: Sized {
183 #[inline]
185 fn as_<F: FromPrimitive<Self>>(self) -> F {
186 F::from(self)
187 }
188}
189impl<U> AsPrimitive for U {}
190
191macro_rules! impl_zero_value {
192 ($s: ty, $zero: expr) => {
193 impl Zero for $s {
194 const ZERO: Self = $zero;
195 }
196 };
197}
198
199macro_rules! impl_float_values {
200 ($s: ty, $zero: expr, $one: expr, $inf: expr) => {
201 impl_zero_value!($s, $zero);
202
203 impl One for $s {
204 const ONE: Self = $one;
205 }
206
207 impl Infinity for $s {
208 #[inline]
209 fn infinity() -> Self {
210 $inf
211 }
212 }
213 };
214}
215
216impl_float_values!(f32, 0.0, 1.0, Self::INFINITY);
217impl_float_values!(f32x4, Self::ZERO, Self::ONE, Self::splat(f32::INFINITY));
218impl_float_values!(f32x8, Self::ZERO, Self::ONE, Self::splat(f32::INFINITY));
219impl_float_values!(f64, 0.0, 1.0, Self::INFINITY);
220impl_float_values!(f64x2, Self::ZERO, Self::ONE, Self::splat(f64::INFINITY));
221impl_float_values!(f64x4, Self::ZERO, Self::ONE, Self::splat(f64::INFINITY));
222
223impl_zero_value!(Vec2, Self::broadcast(f32::ZERO));
224impl_zero_value!(Vec3, Self::broadcast(f32::ZERO));
225impl_zero_value!(Vec4, Self::broadcast(f32::ZERO));
226impl_zero_value!(DVec2, Self::broadcast(f64::ZERO));
227impl_zero_value!(DVec3, Self::broadcast(f64::ZERO));
228impl_zero_value!(DVec4, Self::broadcast(f64::ZERO));
229impl_zero_value!(Vec2x4, Self::broadcast(f32x4::ZERO));
230impl_zero_value!(Vec2x8, Self::broadcast(f32x8::ZERO));
231impl_zero_value!(Vec3x4, Self::broadcast(f32x4::ZERO));
232impl_zero_value!(Vec3x8, Self::broadcast(f32x8::ZERO));
233impl_zero_value!(Vec4x4, Self::broadcast(f32x4::ZERO));
234impl_zero_value!(Vec4x8, Self::broadcast(f32x8::ZERO));
235impl_zero_value!(DVec2x2, Self::broadcast(f64x2::ZERO));
236impl_zero_value!(DVec2x4, Self::broadcast(f64x4::ZERO));
237impl_zero_value!(DVec3x2, Self::broadcast(f64x2::ZERO));
238impl_zero_value!(DVec3x4, Self::broadcast(f64x4::ZERO));
239impl_zero_value!(DVec4x2, Self::broadcast(f64x2::ZERO));
240impl_zero_value!(DVec4x4, Self::broadcast(f64x4::ZERO));
241
242macro_rules! impl_float {
243 ($s: ty, $recip: expr, $recip_sqrt: expr) => {
244 #[allow(clippy::redundant_closure_call)]
245 impl Float for $s {
246 #[inline]
247 fn recip(self) -> Self {
248 $recip(self)
249 }
250
251 #[inline]
252 fn sqrt(self) -> Self {
253 self.sqrt()
254 }
255
256 #[inline]
257 fn rsqrt(self) -> Self {
258 $recip_sqrt(self)
259 }
260
261 #[inline]
262 fn min(self, rhs: Self) -> Self {
263 self.min(rhs)
264 }
265
266 #[inline]
267 fn max(self, rhs: Self) -> Self {
268 self.max(rhs)
269 }
270 }
271 };
272}
273
274impl_float!(f32, Self::recip, |f| Self::recip(f).sqrt());
275impl_float!(f32x4, Self::recip, Self::recip_sqrt);
276impl_float!(f32x8, Self::recip, Self::recip_sqrt);
277impl_float!(f64, Self::recip, |f| Self::recip(f).sqrt());
278impl_float!(f64x2, |f| 1.0 / f, |f| Self::recip(f).sqrt());
279impl_float!(f64x4, |f| 1.0 / f, |f| Self::recip(f).sqrt());
280
281macro_rules! impl_into_array {
282 ($vector: ty, [$float: ty; $dim: literal]) => {
283 impl IntoArray for $vector {
284 type Array = [$float; $dim];
285 }
286 };
287}
288
289impl_into_array!(Vec2, [f32; 2]);
290impl_into_array!(Vec3, [f32; 3]);
291impl_into_array!(Vec4, [f32; 4]);
292impl_into_array!(DVec2, [f64; 2]);
293impl_into_array!(DVec3, [f64; 3]);
294impl_into_array!(DVec4, [f64; 4]);
295impl_into_array!(Vec2x4, [f32x4; 2]);
296impl_into_array!(Vec2x8, [f32x8; 2]);
297impl_into_array!(Vec3x4, [f32x4; 3]);
298impl_into_array!(Vec3x8, [f32x8; 3]);
299impl_into_array!(Vec4x4, [f32x4; 4]);
300impl_into_array!(Vec4x8, [f32x8; 4]);
301impl_into_array!(DVec2x2, [f64x2; 2]);
302impl_into_array!(DVec2x4, [f64x4; 2]);
303impl_into_array!(DVec3x2, [f64x2; 3]);
304impl_into_array!(DVec3x4, [f64x4; 3]);
305impl_into_array!(DVec4x2, [f64x2; 4]);
306impl_into_array!(DVec4x4, [f64x4; 4]);
307
308macro_rules! impl_float_vector {
309 ($vector: ty, $float: ty) => {
310 impl FloatVector for $vector {
311 type Float = $float;
312
313 #[inline]
314 fn norm_squared(self) -> Self::Float {
315 self.mag_sq()
316 }
317 }
318 };
319}
320
321impl_float_vector!(Vec2, f32);
322impl_float_vector!(Vec3, f32);
323impl_float_vector!(Vec4, f32);
324impl_float_vector!(DVec2, f64);
325impl_float_vector!(DVec3, f64);
326impl_float_vector!(DVec4, f64);
327impl_float_vector!(Vec2x4, f32x4);
328impl_float_vector!(Vec2x8, f32x8);
329impl_float_vector!(Vec3x4, f32x4);
330impl_float_vector!(Vec3x8, f32x8);
331impl_float_vector!(Vec4x4, f32x4);
332impl_float_vector!(Vec4x8, f32x8);
333impl_float_vector!(DVec2x2, f64x2);
334impl_float_vector!(DVec2x4, f64x4);
335impl_float_vector!(DVec3x2, f64x2);
336impl_float_vector!(DVec3x4, f64x4);
337impl_float_vector!(DVec4x2, f64x2);
338impl_float_vector!(DVec4x4, f64x4);
339
340macro_rules! impl_simd {
341 ($simd: ty, $el: ty, $lane: literal, $splat: expr, $new_lane: expr) => {
342 #[allow(clippy::redundant_closure_call)]
343 impl SIMD for $simd {
344 type Element = $el;
345
346 type Lane = [Self::Element; $lane];
347
348 #[inline]
349 fn splat(element: Self::Element) -> Self {
350 $splat(element)
351 }
352
353 #[inline]
354 fn new_lane(lane: Self::Lane) -> Self {
355 $new_lane(lane)
356 }
357 }
358
359 impl SIMDElement<$lane> for $el {
360 type SIMD = $simd;
361 }
362 };
363}
364
365macro_rules! impl_simd_float {
366 ($simd: ty, [$el: ty; $lane: literal]) => {
367 impl_simd!($simd, $el, $lane, Self::splat, Self::from);
368 };
369}
370
371macro_rules! impl_simd_vector {
372 ($simd: ty, [$el: ty; $lane: literal]) => {
373 impl_simd!(
374 $simd,
375 $el,
376 $lane,
377 |e| Self::splat(<$el>::from(e)),
378 |l: Self::Lane| Self::from(l.map(<$el>::from))
379 );
380 };
381}
382
383impl_simd_float!(f32x4, [f32; 4]);
384impl_simd_float!(f32x8, [f32; 8]);
385impl_simd_float!(f64x2, [f64; 2]);
386impl_simd_float!(f64x4, [f64; 4]);
387
388impl_simd_vector!(Vec2x4, [Vec2; 4]);
389impl_simd_vector!(Vec2x8, [Vec2; 8]);
390impl_simd_vector!(Vec3x4, [Vec3; 4]);
391impl_simd_vector!(Vec3x8, [Vec3; 8]);
392impl_simd_vector!(Vec4x4, [Vec4; 4]);
393impl_simd_vector!(Vec4x8, [Vec4; 8]);
394impl_simd_vector!(DVec2x2, [DVec2; 2]);
395impl_simd_vector!(DVec2x4, [DVec2; 4]);
396impl_simd_vector!(DVec3x2, [DVec3; 2]);
397impl_simd_vector!(DVec3x4, [DVec3; 4]);
398impl_simd_vector!(DVec4x2, [DVec4; 2]);
399impl_simd_vector!(DVec4x4, [DVec4; 4]);
400
401macro_rules! impl_reduce {
402 ($vector: ty, [$($f: ident),+]) => {
403 impl Reduce for $vector {
404 #[inline]
405 fn reduce_sum(self) -> Self::Element {
406 Self::Element {
407 $($f: self.$f.reduce_add()),+
408 }
409 }
410 }
411 };
412}
413
414impl_reduce!(Vec2x4, [x, y]);
415impl_reduce!(Vec2x8, [x, y]);
416impl_reduce!(Vec3x4, [x, y, z]);
417impl_reduce!(Vec3x8, [x, y, z]);
418impl_reduce!(Vec4x4, [x, y, z, w]);
419impl_reduce!(Vec4x8, [x, y, z, w]);
420impl_reduce!(DVec2x2, [x, y]);
421impl_reduce!(DVec2x4, [x, y]);
422impl_reduce!(DVec3x2, [x, y, z]);
423impl_reduce!(DVec3x4, [x, y, z]);
424impl_reduce!(DVec4x2, [x, y, z, w]);
425impl_reduce!(DVec4x4, [x, y, z, w]);
426
427macro_rules! impl_from_primitive {
428 ($p1: ty => ($($pn: ty),*)) => {$(
429 impl FromPrimitive<$pn> for $p1 {
430 #[inline]
431 fn from(p: $pn) -> Self {
432 p as Self
433 }
434 }
435 )*};
436}
437
438impl_from_primitive!(f32 => (usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f64));
439impl_from_primitive!(f64 => (usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32));