1#![no_std]
39#![forbid(unsafe_code)]
40#![warn(missing_docs)]
41
42use embedded_f32_sqrt::sqrt;
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum VecError {
51 ZeroNorm,
53 NonFiniteValue,
55}
56
57#[derive(Debug, Clone, Copy, PartialEq)]
63pub struct Vec2 {
64 pub x: f32,
66 pub y: f32,
68}
69
70impl Vec2 {
71 #[inline]
73 pub const fn new(x: f32, y: f32) -> Self {
74 Self { x, y }
75 }
76
77 pub const ZERO: Self = Self::new(0.0, 0.0);
79
80 pub const X: Self = Self::new(1.0, 0.0);
82
83 pub const Y: Self = Self::new(0.0, 1.0);
85
86 #[inline]
88 pub fn as_array(&self) -> [f32; 2] {
89 [self.x, self.y]
90 }
91
92 #[inline]
94 pub const fn from_array(v: [f32; 2]) -> Self {
95 Self::new(v[0], v[1])
96 }
97
98 #[inline]
100 pub fn dot(&self, rhs: &Self) -> f32 {
101 self.x * rhs.x + self.y * rhs.y
102 }
103
104 #[inline]
106 pub fn norm_sq(&self) -> f32 {
107 self.dot(self)
108 }
109
110 pub fn norm(&self) -> Result<f32, VecError> {
114 let sq = self.norm_sq();
115 if !sq.is_finite() {
116 return Err(VecError::NonFiniteValue);
117 }
118 sqrt(sq).map_err(|_| VecError::ZeroNorm)
119 }
120
121 pub fn normalize(&self) -> Result<Self, VecError> {
126 let n = self.norm()?;
127 if n < 1e-10 {
128 return Err(VecError::ZeroNorm);
129 }
130 Ok(Self::new(self.x / n, self.y / n))
131 }
132
133 pub fn distance(&self, rhs: &Self) -> Result<f32, VecError> {
135 (*self - *rhs).norm()
136 }
137
138 #[inline]
140 pub fn lerp(&self, rhs: &Self, t: f32) -> Self {
141 Self::new(
142 self.x + t * (rhs.x - self.x),
143 self.y + t * (rhs.y - self.y),
144 )
145 }
146
147 #[inline]
149 pub fn hadamard(&self, rhs: &Self) -> Self {
150 Self::new(self.x * rhs.x, self.y * rhs.y)
151 }
152
153 #[inline]
155 pub fn is_finite(&self) -> bool {
156 self.x.is_finite() && self.y.is_finite()
157 }
158}
159
160impl core::ops::Add for Vec2 {
161 type Output = Self;
162 #[inline]
163 fn add(self, rhs: Self) -> Self { Self::new(self.x + rhs.x, self.y + rhs.y) }
164}
165impl core::ops::Sub for Vec2 {
166 type Output = Self;
167 #[inline]
168 fn sub(self, rhs: Self) -> Self { Self::new(self.x - rhs.x, self.y - rhs.y) }
169}
170impl core::ops::Mul<f32> for Vec2 {
171 type Output = Self;
172 #[inline]
173 fn mul(self, s: f32) -> Self { Self::new(self.x * s, self.y * s) }
174}
175impl core::ops::Div<f32> for Vec2 {
176 type Output = Self;
177 #[inline]
178 fn div(self, s: f32) -> Self { Self::new(self.x / s, self.y / s) }
179}
180impl core::ops::Neg for Vec2 {
181 type Output = Self;
182 #[inline]
183 fn neg(self) -> Self { Self::new(-self.x, -self.y) }
184}
185impl core::ops::AddAssign for Vec2 {
186 #[inline]
187 fn add_assign(&mut self, rhs: Self) { self.x += rhs.x; self.y += rhs.y; }
188}
189impl core::ops::SubAssign for Vec2 {
190 #[inline]
191 fn sub_assign(&mut self, rhs: Self) { self.x -= rhs.x; self.y -= rhs.y; }
192}
193impl core::ops::MulAssign<f32> for Vec2 {
194 #[inline]
195 fn mul_assign(&mut self, s: f32) { self.x *= s; self.y *= s; }
196}
197
198#[derive(Debug, Clone, Copy, PartialEq)]
204pub struct Vec3 {
205 pub x: f32,
207 pub y: f32,
209 pub z: f32,
211}
212
213impl Vec3 {
214 #[inline]
216 pub const fn new(x: f32, y: f32, z: f32) -> Self {
217 Self { x, y, z }
218 }
219
220 pub const ZERO: Self = Self::new(0.0, 0.0, 0.0);
222
223 pub const X: Self = Self::new(1.0, 0.0, 0.0);
225
226 pub const Y: Self = Self::new(0.0, 1.0, 0.0);
228
229 pub const Z: Self = Self::new(0.0, 0.0, 1.0);
231
232 #[inline]
234 pub fn as_array(&self) -> [f32; 3] {
235 [self.x, self.y, self.z]
236 }
237
238 #[inline]
240 pub const fn from_array(v: [f32; 3]) -> Self {
241 Self::new(v[0], v[1], v[2])
242 }
243
244 #[inline]
246 pub fn dot(&self, rhs: &Self) -> f32 {
247 self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
248 }
249
250 #[inline]
255 pub fn cross(&self, rhs: &Self) -> Self {
256 Self::new(
257 self.y * rhs.z - self.z * rhs.y,
258 self.z * rhs.x - self.x * rhs.z,
259 self.x * rhs.y - self.y * rhs.x,
260 )
261 }
262
263 #[inline]
265 pub fn norm_sq(&self) -> f32 {
266 self.dot(self)
267 }
268
269 pub fn norm(&self) -> Result<f32, VecError> {
273 let sq = self.norm_sq();
274 if !sq.is_finite() {
275 return Err(VecError::NonFiniteValue);
276 }
277 sqrt(sq).map_err(|_| VecError::ZeroNorm)
278 }
279
280 pub fn normalize(&self) -> Result<Self, VecError> {
285 let n = self.norm()?;
286 if n < 1e-10 {
287 return Err(VecError::ZeroNorm);
288 }
289 Ok(Self::new(self.x / n, self.y / n, self.z / n))
290 }
291
292 pub fn distance(&self, rhs: &Self) -> Result<f32, VecError> {
294 (*self - *rhs).norm()
295 }
296
297 #[inline]
299 pub fn lerp(&self, rhs: &Self, t: f32) -> Self {
300 Self::new(
301 self.x + t * (rhs.x - self.x),
302 self.y + t * (rhs.y - self.y),
303 self.z + t * (rhs.z - self.z),
304 )
305 }
306
307 #[inline]
309 pub fn hadamard(&self, rhs: &Self) -> Self {
310 Self::new(self.x * rhs.x, self.y * rhs.y, self.z * rhs.z)
311 }
312
313 pub fn project_onto(&self, rhs: &Self) -> Result<Self, VecError> {
317 let denom = rhs.norm_sq();
318 if denom < 1e-20 {
319 return Err(VecError::ZeroNorm);
320 }
321 Ok(*rhs * (self.dot(rhs) / denom))
322 }
323
324 pub fn reject_from(&self, rhs: &Self) -> Result<Self, VecError> {
326 Ok(*self - self.project_onto(rhs)?)
327 }
328
329 #[inline]
331 pub fn is_finite(&self) -> bool {
332 self.x.is_finite() && self.y.is_finite() && self.z.is_finite()
333 }
334}
335
336impl core::ops::Add for Vec3 {
337 type Output = Self;
338 #[inline]
339 fn add(self, rhs: Self) -> Self { Self::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z) }
340}
341impl core::ops::Sub for Vec3 {
342 type Output = Self;
343 #[inline]
344 fn sub(self, rhs: Self) -> Self { Self::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z) }
345}
346impl core::ops::Mul<f32> for Vec3 {
347 type Output = Self;
348 #[inline]
349 fn mul(self, s: f32) -> Self { Self::new(self.x * s, self.y * s, self.z * s) }
350}
351impl core::ops::Div<f32> for Vec3 {
352 type Output = Self;
353 #[inline]
354 fn div(self, s: f32) -> Self { Self::new(self.x / s, self.y / s, self.z / s) }
355}
356impl core::ops::Neg for Vec3 {
357 type Output = Self;
358 #[inline]
359 fn neg(self) -> Self { Self::new(-self.x, -self.y, -self.z) }
360}
361impl core::ops::AddAssign for Vec3 {
362 #[inline]
363 fn add_assign(&mut self, rhs: Self) { self.x += rhs.x; self.y += rhs.y; self.z += rhs.z; }
364}
365impl core::ops::SubAssign for Vec3 {
366 #[inline]
367 fn sub_assign(&mut self, rhs: Self) { self.x -= rhs.x; self.y -= rhs.y; self.z -= rhs.z; }
368}
369impl core::ops::MulAssign<f32> for Vec3 {
370 #[inline]
371 fn mul_assign(&mut self, s: f32) { self.x *= s; self.y *= s; self.z *= s; }
372}
373
374#[derive(Debug, Clone, Copy, PartialEq)]
383pub struct Vec4 {
384 pub x: f32,
386 pub y: f32,
388 pub z: f32,
390 pub w: f32,
392}
393
394impl Vec4 {
395 #[inline]
397 pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
398 Self { x, y, z, w }
399 }
400
401 pub const ZERO: Self = Self::new(0.0, 0.0, 0.0, 0.0);
403
404 #[inline]
406 pub fn as_array(&self) -> [f32; 4] {
407 [self.x, self.y, self.z, self.w]
408 }
409
410 #[inline]
412 pub const fn from_array(v: [f32; 4]) -> Self {
413 Self::new(v[0], v[1], v[2], v[3])
414 }
415
416 #[inline]
420 pub const fn from_vec3(v: Vec3, w: f32) -> Self {
421 Self::new(v.x, v.y, v.z, w)
422 }
423
424 #[inline]
426 pub const fn xyz(&self) -> Vec3 {
427 Vec3::new(self.x, self.y, self.z)
428 }
429
430 #[inline]
432 pub fn dot(&self, rhs: &Self) -> f32 {
433 self.x * rhs.x + self.y * rhs.y + self.z * rhs.z + self.w * rhs.w
434 }
435
436 #[inline]
438 pub fn norm_sq(&self) -> f32 {
439 self.dot(self)
440 }
441
442 pub fn norm(&self) -> Result<f32, VecError> {
444 let sq = self.norm_sq();
445 if !sq.is_finite() {
446 return Err(VecError::NonFiniteValue);
447 }
448 sqrt(sq).map_err(|_| VecError::ZeroNorm)
449 }
450
451 pub fn normalize(&self) -> Result<Self, VecError> {
453 let n = self.norm()?;
454 if n < 1e-10 {
455 return Err(VecError::ZeroNorm);
456 }
457 Ok(Self::new(self.x / n, self.y / n, self.z / n, self.w / n))
458 }
459
460 #[inline]
462 pub fn lerp(&self, rhs: &Self, t: f32) -> Self {
463 Self::new(
464 self.x + t * (rhs.x - self.x),
465 self.y + t * (rhs.y - self.y),
466 self.z + t * (rhs.z - self.z),
467 self.w + t * (rhs.w - self.w),
468 )
469 }
470
471 #[inline]
473 pub fn hadamard(&self, rhs: &Self) -> Self {
474 Self::new(self.x * rhs.x, self.y * rhs.y, self.z * rhs.z, self.w * rhs.w)
475 }
476
477 #[inline]
479 pub fn is_finite(&self) -> bool {
480 self.x.is_finite() && self.y.is_finite()
481 && self.z.is_finite() && self.w.is_finite()
482 }
483}
484
485impl core::ops::Add for Vec4 {
486 type Output = Self;
487 #[inline]
488 fn add(self, rhs: Self) -> Self {
489 Self::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z, self.w + rhs.w)
490 }
491}
492impl core::ops::Sub for Vec4 {
493 type Output = Self;
494 #[inline]
495 fn sub(self, rhs: Self) -> Self {
496 Self::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z, self.w - rhs.w)
497 }
498}
499impl core::ops::Mul<f32> for Vec4 {
500 type Output = Self;
501 #[inline]
502 fn mul(self, s: f32) -> Self {
503 Self::new(self.x * s, self.y * s, self.z * s, self.w * s)
504 }
505}
506impl core::ops::Div<f32> for Vec4 {
507 type Output = Self;
508 #[inline]
509 fn div(self, s: f32) -> Self {
510 Self::new(self.x / s, self.y / s, self.z / s, self.w / s)
511 }
512}
513impl core::ops::Neg for Vec4 {
514 type Output = Self;
515 #[inline]
516 fn neg(self) -> Self { Self::new(-self.x, -self.y, -self.z, -self.w) }
517}
518impl core::ops::AddAssign for Vec4 {
519 #[inline]
520 fn add_assign(&mut self, rhs: Self) {
521 self.x += rhs.x; self.y += rhs.y; self.z += rhs.z; self.w += rhs.w;
522 }
523}
524impl core::ops::SubAssign for Vec4 {
525 #[inline]
526 fn sub_assign(&mut self, rhs: Self) {
527 self.x -= rhs.x; self.y -= rhs.y; self.z -= rhs.z; self.w -= rhs.w;
528 }
529}
530impl core::ops::MulAssign<f32> for Vec4 {
531 #[inline]
532 fn mul_assign(&mut self, s: f32) {
533 self.x *= s; self.y *= s; self.z *= s; self.w *= s;
534 }
535}
536
537#[cfg(test)]
542mod tests {
543 use super::*;
544
545 #[test]
548 fn v2_constants() {
549 assert_eq!(Vec2::ZERO.as_array(), [0.0, 0.0]);
550 assert_eq!(Vec2::X.as_array(), [1.0, 0.0]);
551 assert_eq!(Vec2::Y.as_array(), [0.0, 1.0]);
552 }
553
554 #[test]
555 fn v2_dot() {
556 let a = Vec2::new(1.0, 2.0);
557 let b = Vec2::new(3.0, 4.0);
558 assert!((a.dot(&b) - 11.0).abs() < 1e-6);
559 }
560
561 #[test]
562 fn v2_norm() {
563 assert!((Vec2::new(3.0, 4.0).norm().unwrap() - 5.0).abs() < 1e-5);
565 }
566
567 #[test]
568 fn v2_normalize() {
569 let u = Vec2::new(3.0, 0.0).normalize().unwrap();
570 assert!((u.x - 1.0).abs() < 1e-6);
571 assert!(u.y.abs() < 1e-6);
572 assert!((u.norm().unwrap() - 1.0).abs() < 1e-5);
573 }
574
575 #[test]
576 fn v2_normalize_zero() {
577 assert_eq!(Vec2::ZERO.normalize(), Err(VecError::ZeroNorm));
578 }
579
580 #[test]
581 fn v2_distance() {
582 assert!((Vec2::ZERO.distance(&Vec2::new(3.0, 4.0)).unwrap() - 5.0).abs() < 1e-5);
583 }
584
585 #[test]
586 fn v2_lerp() {
587 let m = Vec2::ZERO.lerp(&Vec2::new(2.0, 4.0), 0.5);
588 assert!((m.x - 1.0).abs() < 1e-6);
589 assert!((m.y - 2.0).abs() < 1e-6);
590 }
591
592 #[test]
593 fn v2_hadamard() {
594 let h = Vec2::new(2.0, 3.0).hadamard(&Vec2::new(4.0, 5.0));
595 assert!((h.x - 8.0).abs() < 1e-6);
596 assert!((h.y - 15.0).abs() < 1e-6);
597 }
598
599 #[test]
600 fn v2_ops() {
601 let a = Vec2::new(1.0, 2.0);
602 let b = Vec2::new(3.0, 4.0);
603 assert!((( a + b).x - 4.0).abs() < 1e-6);
604 assert!(((b - a).x - 2.0).abs() < 1e-6);
605 assert!((( a * 3.0).y - 6.0).abs() < 1e-6);
606 assert!((( b / 2.0).x - 1.5).abs() < 1e-6);
607 assert!(((-a).x + 1.0).abs() < 1e-6);
608 }
609
610 #[test]
611 fn v2_assign_ops() {
612 let mut v = Vec2::new(1.0, 1.0);
613 v += Vec2::new(2.0, 3.0);
614 assert!((v.x - 3.0).abs() < 1e-6);
615 v -= Vec2::new(1.0, 0.0);
616 assert!((v.x - 2.0).abs() < 1e-6);
617 v *= 2.0;
618 assert!((v.x - 4.0).abs() < 1e-6);
619 }
620
621 #[test]
622 fn v2_non_finite() {
623 let v = Vec2::new(f32::NAN, 0.0);
624 assert_eq!(v.norm(), Err(VecError::NonFiniteValue));
625 assert!(!v.is_finite());
626 }
627
628 #[test]
631 fn v3_constants() {
632 assert_eq!(Vec3::ZERO.as_array(), [0.0, 0.0, 0.0]);
633 assert_eq!(Vec3::X.as_array(), [1.0, 0.0, 0.0]);
634 assert_eq!(Vec3::Y.as_array(), [0.0, 1.0, 0.0]);
635 assert_eq!(Vec3::Z.as_array(), [0.0, 0.0, 1.0]);
636 }
637
638 #[test]
639 fn v3_dot() {
640 let a = Vec3::new(1.0, 2.0, 3.0);
641 let b = Vec3::new(4.0, 5.0, 6.0);
642 assert!((a.dot(&b) - 32.0).abs() < 1e-6);
643 }
644
645 #[test]
646 fn v3_cross_basis() {
647 let z = Vec3::X.cross(&Vec3::Y);
649 assert!(z.x.abs() < 1e-6);
650 assert!(z.y.abs() < 1e-6);
651 assert!((z.z - 1.0).abs() < 1e-6);
652
653 let x = Vec3::Y.cross(&Vec3::Z);
654 assert!((x.x - 1.0).abs() < 1e-6);
655
656 let y = Vec3::Z.cross(&Vec3::X);
657 assert!((y.y - 1.0).abs() < 1e-6);
658 }
659
660 #[test]
661 fn v3_cross_anticommutative() {
662 let a = Vec3::new(1.0, 2.0, 3.0);
663 let b = Vec3::new(4.0, 5.0, 6.0);
664 let axb = a.cross(&b);
665 let bxa = b.cross(&a);
666 assert!((axb.x + bxa.x).abs() < 1e-6);
668 assert!((axb.y + bxa.y).abs() < 1e-6);
669 assert!((axb.z + bxa.z).abs() < 1e-6);
670 }
671
672 #[test]
673 fn v3_cross_perpendicular() {
674 let a = Vec3::new(1.0, 2.0, 3.0);
675 let b = Vec3::new(4.0, 5.0, 6.0);
676 let c = a.cross(&b);
677 assert!(a.dot(&c).abs() < 1e-5);
678 assert!(b.dot(&c).abs() < 1e-5);
679 }
680
681 #[test]
682 fn v3_norm() {
683 assert!((Vec3::new(1.0, 2.0, 2.0).norm().unwrap() - 3.0).abs() < 1e-5);
685 }
686
687 #[test]
688 fn v3_normalize() {
689 let u = Vec3::new(0.0, 0.0, 5.0).normalize().unwrap();
690 assert!(u.x.abs() < 1e-6);
691 assert!(u.y.abs() < 1e-6);
692 assert!((u.z - 1.0).abs() < 1e-6);
693 assert!((u.norm().unwrap() - 1.0).abs() < 1e-5);
694 }
695
696 #[test]
697 fn v3_normalize_zero() {
698 assert_eq!(Vec3::ZERO.normalize(), Err(VecError::ZeroNorm));
699 }
700
701 #[test]
702 fn v3_distance() {
703 let a = Vec3::new(1.0, 0.0, 0.0);
704 let b = Vec3::new(4.0, 0.0, 0.0);
705 assert!((a.distance(&b).unwrap() - 3.0).abs() < 1e-5);
706 }
707
708 #[test]
709 fn v3_lerp() {
710 let m = Vec3::ZERO.lerp(&Vec3::new(2.0, 4.0, 6.0), 0.5);
711 assert!((m.x - 1.0).abs() < 1e-6);
712 assert!((m.y - 2.0).abs() < 1e-6);
713 assert!((m.z - 3.0).abs() < 1e-6);
714 }
715
716 #[test]
717 fn v3_project_onto() {
718 let p = Vec3::new(3.0, 4.0, 0.0).project_onto(&Vec3::X).unwrap();
719 assert!((p.x - 3.0).abs() < 1e-6);
720 assert!(p.y.abs() < 1e-6);
721 }
722
723 #[test]
724 fn v3_project_onto_zero() {
725 assert_eq!(Vec3::X.project_onto(&Vec3::ZERO), Err(VecError::ZeroNorm));
726 }
727
728 #[test]
729 fn v3_reject_from() {
730 let r = Vec3::new(3.0, 4.0, 0.0).reject_from(&Vec3::X).unwrap();
732 assert!(r.x.abs() < 1e-6);
733 assert!((r.y - 4.0).abs() < 1e-6);
734 assert!(r.z.abs() < 1e-6);
735 }
736
737 #[test]
738 fn v3_hadamard() {
739 let h = Vec3::new(1.0, 2.0, 3.0).hadamard(&Vec3::new(4.0, 5.0, 6.0));
740 assert!((h.x - 4.0).abs() < 1e-6);
741 assert!((h.y - 10.0).abs() < 1e-6);
742 assert!((h.z - 18.0).abs() < 1e-6);
743 }
744
745 #[test]
746 fn v3_ops() {
747 let a = Vec3::new(1.0, 2.0, 3.0);
748 let b = Vec3::new(4.0, 5.0, 6.0);
749 assert!(((a + b).x - 5.0).abs() < 1e-6);
750 assert!(((b - a).x - 3.0).abs() < 1e-6);
751 assert!(((a * 2.0).z - 6.0).abs() < 1e-6);
752 assert!(((b / 2.0).x - 2.0).abs() < 1e-6);
753 assert!(((-a).x + 1.0).abs() < 1e-6);
754 }
755
756 #[test]
757 fn v3_assign_ops() {
758 let mut v = Vec3::new(1.0, 1.0, 1.0);
759 v += Vec3::new(1.0, 2.0, 3.0);
760 assert!((v.z - 4.0).abs() < 1e-6);
761 v -= Vec3::new(0.0, 0.0, 1.0);
762 assert!((v.z - 3.0).abs() < 1e-6);
763 v *= 2.0;
764 assert!((v.z - 6.0).abs() < 1e-6);
765 }
766
767 #[test]
768 fn v3_non_finite() {
769 let v = Vec3::new(0.0, f32::INFINITY, 0.0);
770 assert_eq!(v.norm(), Err(VecError::NonFiniteValue));
771 assert!(!v.is_finite());
772 }
773
774 #[test]
775 fn v3_from_array_roundtrip() {
776 let arr = [1.0_f32, 2.0, 3.0];
777 assert_eq!(Vec3::from_array(arr).as_array(), arr);
778 }
779
780 #[test]
783 fn v4_from_vec3() {
784 let v4 = Vec4::from_vec3(Vec3::new(1.0, 2.0, 3.0), 1.0);
785 assert!((v4.w - 1.0).abs() < 1e-6);
786 let back = v4.xyz();
787 assert!((back.x - 1.0).abs() < 1e-6);
788 assert!((back.z - 3.0).abs() < 1e-6);
789 }
790
791 #[test]
792 fn v4_dot() {
793 let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
794 assert!((a.dot(&Vec4::new(1.0, 0.0, 0.0, 0.0)) - 1.0).abs() < 1e-6);
795 }
796
797 #[test]
798 fn v4_norm() {
799 assert!((Vec4::new(1.0, 0.0, 0.0, 0.0).norm().unwrap() - 1.0).abs() < 1e-5);
800 }
801
802 #[test]
803 fn v4_normalize() {
804 let u = Vec4::new(2.0, 0.0, 0.0, 0.0).normalize().unwrap();
805 assert!((u.x - 1.0).abs() < 1e-6);
806 assert!((u.norm().unwrap() - 1.0).abs() < 1e-5);
807 }
808
809 #[test]
810 fn v4_lerp() {
811 let m = Vec4::ZERO.lerp(&Vec4::new(2.0, 4.0, 6.0, 8.0), 0.5);
812 assert!((m.w - 4.0).abs() < 1e-6);
813 }
814
815 #[test]
816 fn v4_ops() {
817 let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
818 let b = Vec4::new(1.0, 1.0, 1.0, 1.0);
819 assert!(((a + b).w - 5.0).abs() < 1e-6);
820 assert!(((a * 2.0).w - 8.0).abs() < 1e-6);
821 assert!(((-a).x + 1.0).abs() < 1e-6);
822 }
823
824 #[test]
825 fn v4_non_finite() {
826 assert!(!Vec4::new(0.0, 0.0, 0.0, f32::NAN).is_finite());
827 }
828
829 #[test]
830 fn v4_hadamard() {
831 let h = Vec4::new(1.0, 2.0, 3.0, 4.0).hadamard(&Vec4::new(2.0, 2.0, 2.0, 2.0));
832 assert!((h.w - 8.0).abs() < 1e-6);
833 }
834}