1use super::{EPSILON, Float, Vec2, Vec3, approx_eq, lerp};
4use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
5
6#[derive(Debug, Clone, Copy, PartialEq, Default)]
8#[repr(C)]
9pub struct Vec4 {
10 pub x: Float,
12 pub y: Float,
14 pub z: Float,
16 pub w: Float,
18}
19
20impl Vec4 {
21 pub const ZERO: Self = Self {
23 x: 0.0,
24 y: 0.0,
25 z: 0.0,
26 w: 0.0,
27 };
28
29 pub const ONE: Self = Self {
31 x: 1.0,
32 y: 1.0,
33 z: 1.0,
34 w: 1.0,
35 };
36
37 pub const X: Self = Self {
39 x: 1.0,
40 y: 0.0,
41 z: 0.0,
42 w: 0.0,
43 };
44
45 pub const Y: Self = Self {
47 x: 0.0,
48 y: 1.0,
49 z: 0.0,
50 w: 0.0,
51 };
52
53 pub const Z: Self = Self {
55 x: 0.0,
56 y: 0.0,
57 z: 1.0,
58 w: 0.0,
59 };
60
61 pub const W: Self = Self {
63 x: 0.0,
64 y: 0.0,
65 z: 0.0,
66 w: 1.0,
67 };
68
69 #[inline]
71 #[must_use]
72 pub const fn new(x: Float, y: Float, z: Float, w: Float) -> Self {
73 Self { x, y, z, w }
74 }
75
76 #[inline]
78 #[must_use]
79 pub const fn splat(value: Float) -> Self {
80 Self {
81 x: value,
82 y: value,
83 z: value,
84 w: value,
85 }
86 }
87
88 #[inline]
90 #[must_use]
91 pub const fn from_array(arr: [Float; 4]) -> Self {
92 Self {
93 x: arr[0],
94 y: arr[1],
95 z: arr[2],
96 w: arr[3],
97 }
98 }
99
100 #[inline]
102 #[must_use]
103 pub const fn to_array(self) -> [Float; 4] {
104 [self.x, self.y, self.z, self.w]
105 }
106
107 #[inline]
109 #[must_use]
110 pub const fn from_vec3(v: Vec3, w: Float) -> Self {
111 Self {
112 x: v.x,
113 y: v.y,
114 z: v.z,
115 w,
116 }
117 }
118
119 #[inline]
121 #[must_use]
122 pub const fn from_vec2(v: Vec2, z: Float, w: Float) -> Self {
123 Self {
124 x: v.x,
125 y: v.y,
126 z,
127 w,
128 }
129 }
130
131 #[inline]
133 #[must_use]
134 pub const fn xyz(self) -> Vec3 {
135 Vec3 {
136 x: self.x,
137 y: self.y,
138 z: self.z,
139 }
140 }
141
142 #[inline]
144 #[must_use]
145 pub const fn xy(self) -> Vec2 {
146 Vec2 {
147 x: self.x,
148 y: self.y,
149 }
150 }
151
152 #[inline]
154 #[must_use]
155 pub fn dot(self, other: Self) -> Float {
156 self.x * other.x + self.y * other.y + self.z * other.z + self.w * other.w
157 }
158
159 #[inline]
161 #[must_use]
162 pub fn length_squared(self) -> Float {
163 self.dot(self)
164 }
165
166 #[inline]
168 #[must_use]
169 pub fn length(self) -> Float {
170 self.length_squared().sqrt()
171 }
172
173 #[inline]
175 #[must_use]
176 pub fn normalize(self) -> Self {
177 let len = self.length();
178 if len > EPSILON {
179 self / len
180 } else {
181 Self::ZERO
182 }
183 }
184
185 #[inline]
187 #[must_use]
188 pub fn try_normalize(self) -> Option<Self> {
189 let len = self.length();
190 if len > EPSILON {
191 Some(self / len)
192 } else {
193 None
194 }
195 }
196
197 #[inline]
199 #[must_use]
200 pub fn lerp(self, other: Self, t: Float) -> Self {
201 Self {
202 x: lerp(self.x, other.x, t),
203 y: lerp(self.y, other.y, t),
204 z: lerp(self.z, other.z, t),
205 w: lerp(self.w, other.w, t),
206 }
207 }
208
209 #[inline]
211 #[must_use]
212 pub fn min(self, other: Self) -> Self {
213 Self {
214 x: self.x.min(other.x),
215 y: self.y.min(other.y),
216 z: self.z.min(other.z),
217 w: self.w.min(other.w),
218 }
219 }
220
221 #[inline]
223 #[must_use]
224 pub fn max(self, other: Self) -> Self {
225 Self {
226 x: self.x.max(other.x),
227 y: self.y.max(other.y),
228 z: self.z.max(other.z),
229 w: self.w.max(other.w),
230 }
231 }
232
233 #[inline]
235 #[must_use]
236 pub fn abs(self) -> Self {
237 Self {
238 x: self.x.abs(),
239 y: self.y.abs(),
240 z: self.z.abs(),
241 w: self.w.abs(),
242 }
243 }
244
245 #[inline]
247 #[must_use]
248 pub fn approx_eq(self, other: Self) -> bool {
249 approx_eq(self.x, other.x)
250 && approx_eq(self.y, other.y)
251 && approx_eq(self.z, other.z)
252 && approx_eq(self.w, other.w)
253 }
254}
255
256impl Add for Vec4 {
257 type Output = Self;
258
259 #[inline]
260 fn add(self, other: Self) -> Self {
261 Self {
262 x: self.x + other.x,
263 y: self.y + other.y,
264 z: self.z + other.z,
265 w: self.w + other.w,
266 }
267 }
268}
269
270impl AddAssign for Vec4 {
271 #[inline]
272 fn add_assign(&mut self, other: Self) {
273 self.x += other.x;
274 self.y += other.y;
275 self.z += other.z;
276 self.w += other.w;
277 }
278}
279
280impl Sub for Vec4 {
281 type Output = Self;
282
283 #[inline]
284 fn sub(self, other: Self) -> Self {
285 Self {
286 x: self.x - other.x,
287 y: self.y - other.y,
288 z: self.z - other.z,
289 w: self.w - other.w,
290 }
291 }
292}
293
294impl SubAssign for Vec4 {
295 #[inline]
296 fn sub_assign(&mut self, other: Self) {
297 self.x -= other.x;
298 self.y -= other.y;
299 self.z -= other.z;
300 self.w -= other.w;
301 }
302}
303
304impl Mul<Float> for Vec4 {
305 type Output = Self;
306
307 #[inline]
308 fn mul(self, scalar: Float) -> Self {
309 Self {
310 x: self.x * scalar,
311 y: self.y * scalar,
312 z: self.z * scalar,
313 w: self.w * scalar,
314 }
315 }
316}
317
318impl Mul<Vec4> for Float {
319 type Output = Vec4;
320
321 #[inline]
322 fn mul(self, vec: Vec4) -> Vec4 {
323 vec * self
324 }
325}
326
327impl MulAssign<Float> for Vec4 {
328 #[inline]
329 fn mul_assign(&mut self, scalar: Float) {
330 self.x *= scalar;
331 self.y *= scalar;
332 self.z *= scalar;
333 self.w *= scalar;
334 }
335}
336
337impl Mul for Vec4 {
338 type Output = Self;
339
340 #[inline]
341 fn mul(self, other: Self) -> Self {
342 Self {
343 x: self.x * other.x,
344 y: self.y * other.y,
345 z: self.z * other.z,
346 w: self.w * other.w,
347 }
348 }
349}
350
351impl Div<Float> for Vec4 {
352 type Output = Self;
353
354 #[inline]
355 fn div(self, scalar: Float) -> Self {
356 Self {
357 x: self.x / scalar,
358 y: self.y / scalar,
359 z: self.z / scalar,
360 w: self.w / scalar,
361 }
362 }
363}
364
365impl DivAssign<Float> for Vec4 {
366 #[inline]
367 fn div_assign(&mut self, scalar: Float) {
368 self.x /= scalar;
369 self.y /= scalar;
370 self.z /= scalar;
371 self.w /= scalar;
372 }
373}
374
375impl Neg for Vec4 {
376 type Output = Self;
377
378 #[inline]
379 fn neg(self) -> Self {
380 Self {
381 x: -self.x,
382 y: -self.y,
383 z: -self.z,
384 w: -self.w,
385 }
386 }
387}
388
389impl From<[Float; 4]> for Vec4 {
390 #[inline]
391 fn from(arr: [Float; 4]) -> Self {
392 Self::from_array(arr)
393 }
394}
395
396impl From<Vec4> for [Float; 4] {
397 #[inline]
398 fn from(v: Vec4) -> Self {
399 v.to_array()
400 }
401}
402
403impl From<(Float, Float, Float, Float)> for Vec4 {
404 #[inline]
405 fn from((x, y, z, w): (Float, Float, Float, Float)) -> Self {
406 Self { x, y, z, w }
407 }
408}
409
410#[cfg(test)]
411mod tests {
412 use super::*;
413
414 #[test]
415 fn test_new() {
416 let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
417 assert_eq!(v.x, 1.0);
418 assert_eq!(v.y, 2.0);
419 assert_eq!(v.z, 3.0);
420 assert_eq!(v.w, 4.0);
421 }
422
423 #[test]
424 fn test_constants() {
425 assert!(Vec4::ZERO.approx_eq(Vec4::new(0.0, 0.0, 0.0, 0.0)));
426 assert!(Vec4::ONE.approx_eq(Vec4::new(1.0, 1.0, 1.0, 1.0)));
427 assert!(Vec4::X.approx_eq(Vec4::new(1.0, 0.0, 0.0, 0.0)));
428 assert!(Vec4::Y.approx_eq(Vec4::new(0.0, 1.0, 0.0, 0.0)));
429 assert!(Vec4::Z.approx_eq(Vec4::new(0.0, 0.0, 1.0, 0.0)));
430 assert!(Vec4::W.approx_eq(Vec4::new(0.0, 0.0, 0.0, 1.0)));
431 }
432
433 #[test]
434 fn test_splat() {
435 let v = Vec4::splat(5.0);
436 assert!(v.approx_eq(Vec4::new(5.0, 5.0, 5.0, 5.0)));
437 }
438
439 #[test]
440 fn test_from_vec3() {
441 let v3 = Vec3::new(1.0, 2.0, 3.0);
442 let v4 = Vec4::from_vec3(v3, 4.0);
443 assert!(v4.approx_eq(Vec4::new(1.0, 2.0, 3.0, 4.0)));
444 }
445
446 #[test]
447 fn test_from_vec2() {
448 let v2 = Vec2::new(1.0, 2.0);
449 let v4 = Vec4::from_vec2(v2, 3.0, 4.0);
450 assert!(v4.approx_eq(Vec4::new(1.0, 2.0, 3.0, 4.0)));
451 }
452
453 #[test]
454 fn test_truncate() {
455 let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
456 assert!(v.xyz().approx_eq(Vec3::new(1.0, 2.0, 3.0)));
457 assert!(v.xy().approx_eq(Vec2::new(1.0, 2.0)));
458 }
459
460 #[test]
461 fn test_dot() {
462 let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
463 let b = Vec4::new(5.0, 6.0, 7.0, 8.0);
464 assert!(approx_eq(a.dot(b), 70.0)); }
466
467 #[test]
468 fn test_length() {
469 let v = Vec4::new(1.0, 2.0, 2.0, 4.0);
470 assert!(approx_eq(v.length_squared(), 25.0));
471 assert!(approx_eq(v.length(), 5.0));
472 }
473
474 #[test]
475 fn test_normalize() {
476 let v = Vec4::new(1.0, 2.0, 2.0, 4.0);
477 let n = v.normalize();
478 assert!(approx_eq(n.length(), 1.0));
479 }
480
481 #[test]
482 fn test_normalize_zero() {
483 let v = Vec4::ZERO;
484 assert!(v.normalize().approx_eq(Vec4::ZERO));
485 assert!(v.try_normalize().is_none());
486 }
487
488 #[test]
489 fn test_lerp() {
490 let a = Vec4::ZERO;
491 let b = Vec4::new(10.0, 20.0, 30.0, 40.0);
492 assert!(a.lerp(b, 0.0).approx_eq(a));
493 assert!(a.lerp(b, 1.0).approx_eq(b));
494 assert!(a.lerp(b, 0.5).approx_eq(Vec4::new(5.0, 10.0, 15.0, 20.0)));
495 }
496
497 #[test]
498 fn test_min_max() {
499 let a = Vec4::new(1.0, 4.0, 2.0, 5.0);
500 let b = Vec4::new(3.0, 2.0, 5.0, 1.0);
501 assert!(a.min(b).approx_eq(Vec4::new(1.0, 2.0, 2.0, 1.0)));
502 assert!(a.max(b).approx_eq(Vec4::new(3.0, 4.0, 5.0, 5.0)));
503 }
504
505 #[test]
506 fn test_abs() {
507 let v = Vec4::new(-1.0, -2.0, 3.0, -4.0);
508 assert!(v.abs().approx_eq(Vec4::new(1.0, 2.0, 3.0, 4.0)));
509 }
510
511 #[test]
512 fn test_add() {
513 let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
514 let b = Vec4::new(5.0, 6.0, 7.0, 8.0);
515 assert!((a + b).approx_eq(Vec4::new(6.0, 8.0, 10.0, 12.0)));
516 }
517
518 #[test]
519 fn test_sub() {
520 let a = Vec4::new(5.0, 6.0, 7.0, 8.0);
521 let b = Vec4::new(1.0, 2.0, 3.0, 4.0);
522 assert!((a - b).approx_eq(Vec4::new(4.0, 4.0, 4.0, 4.0)));
523 }
524
525 #[test]
526 fn test_mul_scalar() {
527 let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
528 assert!((v * 2.0).approx_eq(Vec4::new(2.0, 4.0, 6.0, 8.0)));
529 assert!((2.0 * v).approx_eq(Vec4::new(2.0, 4.0, 6.0, 8.0)));
530 }
531
532 #[test]
533 fn test_div() {
534 let v = Vec4::new(2.0, 4.0, 6.0, 8.0);
535 assert!((v / 2.0).approx_eq(Vec4::new(1.0, 2.0, 3.0, 4.0)));
536 }
537
538 #[test]
539 fn test_neg() {
540 let v = Vec4::new(1.0, -2.0, 3.0, -4.0);
541 assert!((-v).approx_eq(Vec4::new(-1.0, 2.0, -3.0, 4.0)));
542 }
543
544 #[test]
545 fn test_from_tuple() {
546 let v: Vec4 = (1.0, 2.0, 3.0, 4.0).into();
547 assert!(v.approx_eq(Vec4::new(1.0, 2.0, 3.0, 4.0)));
548 }
549
550 #[test]
551 fn test_default() {
552 let v = Vec4::default();
553 assert!(v.approx_eq(Vec4::ZERO));
554 }
555}