1#![cfg(feature = "ultraviolet")]
2
3use decorum::R64;
4use typenum::consts::{U2, U3, U4};
5use ultraviolet::interp::Lerp;
6use ultraviolet::vec::{Vec2, Vec3, Vec4};
7
8use crate::adjunct::{Adjunct, Converged, Extend, Fold, Map, Truncate, ZipMap};
9use crate::ops::{Cross, Dot, Interpolate};
10use crate::space::{
11 AffineSpace, Basis, DualSpace, EuclideanSpace, FiniteDimensional, Homogeneous, InnerSpace,
12 VectorSpace,
13};
14use crate::{AsPosition, AsPositionMut};
15
16impl Adjunct for Vec2 {
17 type Item = f32;
18}
19
20impl Adjunct for Vec3 {
21 type Item = f32;
22}
23
24impl Adjunct for Vec4 {
25 type Item = f32;
26}
27
28impl AffineSpace for Vec2 {
29 type Translation = Self;
30}
31
32impl AffineSpace for Vec3 {
33 type Translation = Self;
34}
35
36impl AsPosition for Vec2 {
37 type Position = Self;
38
39 fn as_position(&self) -> &Self::Position {
40 self
41 }
42}
43
44impl AsPosition for Vec3 {
45 type Position = Self;
46
47 fn as_position(&self) -> &Self::Position {
48 self
49 }
50}
51
52impl AsPositionMut for Vec2 {
53 fn as_position_mut(&mut self) -> &mut Self::Position {
54 self
55 }
56}
57
58impl AsPositionMut for Vec3 {
59 fn as_position_mut(&mut self) -> &mut Self::Position {
60 self
61 }
62}
63
64impl Basis for Vec2 {
65 type Bases = [Self; 2];
66
67 fn canonical_basis() -> Self::Bases {
68 [
69 Self::canonical_basis_component(0).unwrap(),
70 Self::canonical_basis_component(1).unwrap(),
71 ]
72 }
73
74 fn canonical_basis_component(index: usize) -> Option<Self> {
75 match index {
76 0 => Some(Self::unit_x()),
77 1 => Some(Self::unit_y()),
78 _ => None,
79 }
80 }
81}
82
83impl Basis for Vec3 {
84 type Bases = [Self; 3];
85
86 fn canonical_basis() -> Self::Bases {
87 [
88 Self::canonical_basis_component(0).unwrap(),
89 Self::canonical_basis_component(1).unwrap(),
90 Self::canonical_basis_component(2).unwrap(),
91 ]
92 }
93
94 fn canonical_basis_component(index: usize) -> Option<Self> {
95 match index {
96 0 => Some(Self::unit_x()),
97 1 => Some(Self::unit_y()),
98 2 => Some(Self::unit_z()),
99 _ => None,
100 }
101 }
102}
103
104impl Basis for Vec4 {
105 type Bases = [Self; 4];
106
107 fn canonical_basis() -> Self::Bases {
108 [
109 Self::canonical_basis_component(0).unwrap(),
110 Self::canonical_basis_component(1).unwrap(),
111 Self::canonical_basis_component(2).unwrap(),
112 Self::canonical_basis_component(3).unwrap(),
113 ]
114 }
115
116 fn canonical_basis_component(index: usize) -> Option<Self> {
117 match index {
118 0 => Some(Self::unit_x()),
119 1 => Some(Self::unit_y()),
120 2 => Some(Self::unit_z()),
121 3 => Some(Self::unit_w()),
122 _ => None,
123 }
124 }
125}
126
127impl Converged for Vec2 {
128 fn converged(value: Self::Item) -> Self {
129 Self::broadcast(value)
130 }
131}
132
133impl Converged for Vec3 {
134 fn converged(value: Self::Item) -> Self {
135 Self::broadcast(value)
136 }
137}
138
139impl Converged for Vec4 {
140 fn converged(value: Self::Item) -> Self {
141 Self::broadcast(value)
142 }
143}
144
145impl Cross for Vec3 {
146 type Output = Self;
147
148 fn cross(self, other: Self) -> Self::Output {
149 Self::cross(&self, other)
150 }
151}
152
153impl Dot for Vec2 {
154 type Output = f32;
155
156 fn dot(self, other: Self) -> Self::Output {
157 Self::dot(&self, other)
158 }
159}
160
161impl Dot for Vec3 {
162 type Output = f32;
163
164 fn dot(self, other: Self) -> Self::Output {
165 Self::dot(&self, other)
166 }
167}
168
169impl Dot for Vec4 {
170 type Output = f32;
171
172 fn dot(self, other: Self) -> Self::Output {
173 Self::dot(&self, other)
174 }
175}
176
177impl DualSpace for Vec2 {
178 type Dual = Self;
179
180 fn transpose(self) -> Self::Dual {
181 self
182 }
183}
184
185impl DualSpace for Vec3 {
186 type Dual = Self;
187
188 fn transpose(self) -> Self::Dual {
189 self
190 }
191}
192
193impl DualSpace for Vec4 {
194 type Dual = Self;
195
196 fn transpose(self) -> Self::Dual {
197 self
198 }
199}
200
201impl Extend<Vec3> for Vec2 {
202 fn extend(self, z: Self::Item) -> Vec3 {
203 let (x, y) = self.into();
204 [x, y, z].into()
205 }
206}
207
208impl Extend<Vec4> for Vec3 {
209 fn extend(self, w: Self::Item) -> Vec4 {
210 let (x, y, z) = self.into();
211 [x, y, z, w].into()
212 }
213}
214
215impl EuclideanSpace for Vec2 {
216 type CoordinateSpace = Self;
217
218 fn origin() -> Self {
219 Self::zero()
220 }
221}
222
223impl EuclideanSpace for Vec3 {
224 type CoordinateSpace = Self;
225
226 fn origin() -> Self {
227 Self::zero()
228 }
229}
230
231impl FiniteDimensional for Vec2 {
232 type N = U2;
233}
234
235impl FiniteDimensional for Vec3 {
236 type N = U3;
237}
238
239impl FiniteDimensional for Vec4 {
240 type N = U4;
241}
242
243impl Fold for Vec2 {
244 fn fold<T, F>(self, seed: T, f: F) -> T
245 where
246 F: FnMut(T, Self::Item) -> T,
247 {
248 self.as_slice().iter().cloned().fold(seed, f)
249 }
250}
251
252impl Fold for Vec3 {
253 fn fold<T, F>(self, seed: T, f: F) -> T
254 where
255 F: FnMut(T, Self::Item) -> T,
256 {
257 self.as_slice().iter().cloned().fold(seed, f)
258 }
259}
260
261impl Fold for Vec4 {
262 fn fold<T, F>(self, seed: T, f: F) -> T
263 where
264 F: FnMut(T, Self::Item) -> T,
265 {
266 self.as_slice().iter().cloned().fold(seed, f)
267 }
268}
269
270impl Homogeneous for Vec2 {
271 type ProjectiveSpace = Vec3;
272}
273
274impl Homogeneous for Vec3 {
275 type ProjectiveSpace = Vec4;
276}
277
278impl InnerSpace for Vec2 {}
279
280impl InnerSpace for Vec3 {}
281
282impl InnerSpace for Vec4 {}
283
284impl Interpolate for Vec2 {
285 type Output = Self;
286
287 fn lerp(self, other: Self, f: R64) -> Self::Output {
288 <Self as Lerp<f32>>::lerp(&self, other, f64::from(f) as f32)
289 }
290}
291
292impl Interpolate for Vec3 {
293 type Output = Self;
294
295 fn lerp(self, other: Self, f: R64) -> Self::Output {
296 <Self as Lerp<f32>>::lerp(&self, other, f64::from(f) as f32)
297 }
298}
299
300impl Interpolate for Vec4 {
301 type Output = Self;
302
303 fn lerp(self, other: Self, f: R64) -> Self::Output {
304 <Self as Lerp<f32>>::lerp(&self, other, f64::from(f) as f32)
305 }
306}
307
308impl Map<f32> for Vec2 {
309 type Output = Self;
310
311 fn map<F>(self, mut f: F) -> Self::Output
312 where
313 F: FnMut(Self::Item) -> f32,
314 {
315 let (x, y) = self.into();
316 [f(x), f(y)].into()
317 }
318}
319
320impl Map<f32> for Vec3 {
321 type Output = Self;
322
323 fn map<F>(self, mut f: F) -> Self::Output
324 where
325 F: FnMut(Self::Item) -> f32,
326 {
327 let (x, y, z) = self.into();
328 [f(x), f(y), f(z)].into()
329 }
330}
331
332impl Map<f32> for Vec4 {
333 type Output = Self;
334
335 #[allow(clippy::many_single_char_names)]
336 fn map<F>(self, mut f: F) -> Self::Output
337 where
338 F: FnMut(Self::Item) -> f32,
339 {
340 let (x, y, z, w) = self.into();
341 [f(x), f(y), f(z), f(w)].into()
342 }
343}
344
345impl Truncate<Vec2> for Vec3 {
346 fn truncate(self) -> (Vec2, Self::Item) {
347 let z = self.z;
348 (self.into(), z)
349 }
350}
351
352impl Truncate<Vec3> for Vec4 {
353 fn truncate(self) -> (Vec3, Self::Item) {
354 let w = self.w;
355 (self.into(), w)
356 }
357}
358
359impl VectorSpace for Vec2 {
360 type Scalar = f32;
361
362 fn scalar_component(&self, index: usize) -> Option<Self::Scalar> {
363 match index {
364 0 => Some(self.x),
365 1 => Some(self.y),
366 _ => None,
367 }
368 }
369
370 fn into_xy(self) -> (Self::Scalar, Self::Scalar) {
371 self.into()
372 }
373
374 fn zero() -> Self {
375 Self::zero()
376 }
377}
378
379impl VectorSpace for Vec3 {
380 type Scalar = f32;
381
382 fn scalar_component(&self, index: usize) -> Option<Self::Scalar> {
383 match index {
384 0 => Some(self.x),
385 1 => Some(self.y),
386 2 => Some(self.z),
387 _ => None,
388 }
389 }
390
391 fn into_xyz(self) -> (Self::Scalar, Self::Scalar, Self::Scalar) {
392 self.into()
393 }
394
395 fn zero() -> Self {
396 Self::zero()
397 }
398}
399
400impl VectorSpace for Vec4 {
401 type Scalar = f32;
402
403 fn scalar_component(&self, index: usize) -> Option<Self::Scalar> {
404 match index {
405 0 => Some(self.x),
406 1 => Some(self.y),
407 2 => Some(self.z),
408 3 => Some(self.w),
409 _ => None,
410 }
411 }
412
413 fn zero() -> Self {
414 Self::zero()
415 }
416}
417
418impl ZipMap<f32> for Vec2 {
419 type Output = Self;
420
421 fn zip_map<F>(self, other: Self, mut f: F) -> Self::Output
422 where
423 F: FnMut(Self::Item, Self::Item) -> f32,
424 {
425 let (x1, y1) = self.into();
426 let (x2, y2) = other.into();
427 [f(x1, x2), f(y1, y2)].into()
428 }
429}
430
431impl ZipMap<f32> for Vec3 {
432 type Output = Self;
433
434 fn zip_map<F>(self, other: Self, mut f: F) -> Self::Output
435 where
436 F: FnMut(Self::Item, Self::Item) -> f32,
437 {
438 let (x1, y1, z1) = self.into();
439 let (x2, y2, z2) = other.into();
440 [f(x1, x2), f(y1, y2), f(z1, z2)].into()
441 }
442}
443
444impl ZipMap<f32> for Vec4 {
445 type Output = Self;
446
447 fn zip_map<F>(self, other: Self, mut f: F) -> Self::Output
448 where
449 F: FnMut(Self::Item, Self::Item) -> f32,
450 {
451 let (x1, y1, z1, w1) = self.into();
452 let (x2, y2, z2, w2) = other.into();
453 [f(x1, x2), f(y1, y2), f(z1, z2), f(w1, w2)].into()
454 }
455}