1use super::vector::{Vector3, Vector6};
4use serde::{Deserialize, Serialize};
5use std::ops::{Add, AddAssign, Index, IndexMut, Mul, Sub};
6
7#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
13pub struct Matrix3<T> {
14 pub data: [[T; 3]; 3],
16}
17
18impl<T: Default + Copy> Matrix3<T> {
19 #[must_use]
21 pub fn zeros() -> Self {
22 Self {
23 data: [[T::default(); 3]; 3],
24 }
25 }
26}
27
28impl Matrix3<f64> {
29 #[must_use]
31 pub fn identity() -> Self {
32 let mut m = Self::zeros();
33 m.data[0][0] = 1.0;
34 m.data[1][1] = 1.0;
35 m.data[2][2] = 1.0;
36 m
37 }
38
39 #[must_use]
41 pub fn from_columns(c0: &Vector3<f64>, c1: &Vector3<f64>, c2: &Vector3<f64>) -> Self {
42 let mut m = Self::zeros();
43 m.data[0][0] = c0.x;
44 m.data[1][0] = c0.y;
45 m.data[2][0] = c0.z;
46 m.data[0][1] = c1.x;
47 m.data[1][1] = c1.y;
48 m.data[2][1] = c1.z;
49 m.data[0][2] = c2.x;
50 m.data[1][2] = c2.y;
51 m.data[2][2] = c2.z;
52 m
53 }
54
55 #[must_use]
57 pub fn from_iterator<I: IntoIterator<Item = f64>>(iter: I) -> Self {
58 let elems: Vec<f64> = iter.into_iter().collect();
59 let mut m = Self::zeros();
60 for (idx, val) in elems.iter().enumerate() {
62 let col = idx / 3;
63 let row = idx % 3;
64 if row < 3 && col < 3 {
65 m.data[row][col] = *val;
66 }
67 }
68 m
69 }
70
71 #[must_use]
73 pub fn transpose(&self) -> Self {
74 let mut m = Self::zeros();
75 for r in 0..3 {
76 for c in 0..3 {
77 m.data[c][r] = self.data[r][c];
78 }
79 }
80 m
81 }
82
83 #[must_use]
85 pub fn determinant(&self) -> f64 {
86 let d = &self.data;
87 d[0][0] * (d[1][1] * d[2][2] - d[1][2] * d[2][1])
88 - d[0][1] * (d[1][0] * d[2][2] - d[1][2] * d[2][0])
89 + d[0][2] * (d[1][0] * d[2][1] - d[1][1] * d[2][0])
90 }
91
92 #[must_use]
94 pub fn try_inverse(&self) -> Option<Self> {
95 let det = self.determinant();
96 if det.abs() < 1e-15 {
97 return None;
98 }
99 let inv_det = 1.0 / det;
100 let d = &self.data;
101 let mut m = Self::zeros();
102 m.data[0][0] = (d[1][1] * d[2][2] - d[1][2] * d[2][1]) * inv_det;
103 m.data[0][1] = (d[0][2] * d[2][1] - d[0][1] * d[2][2]) * inv_det;
104 m.data[0][2] = (d[0][1] * d[1][2] - d[0][2] * d[1][1]) * inv_det;
105 m.data[1][0] = (d[1][2] * d[2][0] - d[1][0] * d[2][2]) * inv_det;
106 m.data[1][1] = (d[0][0] * d[2][2] - d[0][2] * d[2][0]) * inv_det;
107 m.data[1][2] = (d[0][2] * d[1][0] - d[0][0] * d[1][2]) * inv_det;
108 m.data[2][0] = (d[1][0] * d[2][1] - d[1][1] * d[2][0]) * inv_det;
109 m.data[2][1] = (d[0][1] * d[2][0] - d[0][0] * d[2][1]) * inv_det;
110 m.data[2][2] = (d[0][0] * d[1][1] - d[0][1] * d[1][0]) * inv_det;
111 Some(m)
112 }
113
114 #[must_use]
117 pub fn svd(&self, compute_u: bool, compute_v: bool) -> Svd3 {
118 svd_3x3(self, compute_u, compute_v)
119 }
120
121 #[must_use]
123 pub fn column(&self, c: usize) -> Vector3<f64> {
124 Vector3::new(self.data[0][c], self.data[1][c], self.data[2][c])
125 }
126
127 #[must_use]
129 pub fn mul_vec(&self, v: &Vector3<f64>) -> Vector3<f64> {
130 Vector3::new(
131 self.data[0][0] * v.x + self.data[0][1] * v.y + self.data[0][2] * v.z,
132 self.data[1][0] * v.x + self.data[1][1] * v.y + self.data[1][2] * v.z,
133 self.data[2][0] * v.x + self.data[2][1] * v.y + self.data[2][2] * v.z,
134 )
135 }
136}
137
138impl Index<(usize, usize)> for Matrix3<f64> {
139 type Output = f64;
140 fn index(&self, (r, c): (usize, usize)) -> &f64 {
141 &self.data[r][c]
142 }
143}
144
145impl IndexMut<(usize, usize)> for Matrix3<f64> {
146 fn index_mut(&mut self, (r, c): (usize, usize)) -> &mut f64 {
147 &mut self.data[r][c]
148 }
149}
150
151impl Mul for Matrix3<f64> {
152 type Output = Self;
153 fn mul(self, rhs: Self) -> Self {
154 let mut m = Self::zeros();
155 for r in 0..3 {
156 for c in 0..3 {
157 for k in 0..3 {
158 m.data[r][c] += self.data[r][k] * rhs.data[k][c];
159 }
160 }
161 }
162 m
163 }
164}
165
166impl Mul<f64> for Matrix3<f64> {
167 type Output = Self;
168 fn mul(self, rhs: f64) -> Self {
169 let mut m = self;
170 for r in 0..3 {
171 for c in 0..3 {
172 m.data[r][c] *= rhs;
173 }
174 }
175 m
176 }
177}
178
179impl Mul<Matrix3<f64>> for f64 {
180 type Output = Matrix3<f64>;
181 fn mul(self, rhs: Matrix3<f64>) -> Matrix3<f64> {
182 rhs * self
183 }
184}
185
186impl Add for Matrix3<f64> {
187 type Output = Self;
188 fn add(self, rhs: Self) -> Self {
189 let mut m = self;
190 for r in 0..3 {
191 for c in 0..3 {
192 m.data[r][c] += rhs.data[r][c];
193 }
194 }
195 m
196 }
197}
198
199impl AddAssign for Matrix3<f64> {
200 fn add_assign(&mut self, rhs: Self) {
201 for r in 0..3 {
202 for c in 0..3 {
203 self.data[r][c] += rhs.data[r][c];
204 }
205 }
206 }
207}
208
209impl Mul<Vector3<f64>> for Matrix3<f64> {
211 type Output = Vector3<f64>;
212 fn mul(self, rhs: Vector3<f64>) -> Vector3<f64> {
213 self.mul_vec(&rhs)
214 }
215}
216
217impl Mul<super::vector::Point3<f64>> for Matrix3<f64> {
219 type Output = super::vector::Point3<f64>;
220 fn mul(self, rhs: super::vector::Point3<f64>) -> super::vector::Point3<f64> {
221 let v = self.mul_vec(&rhs.coords());
222 super::vector::Point3::new(v.x, v.y, v.z)
223 }
224}
225
226pub struct Svd3 {
232 pub u: Option<Matrix3<f64>>,
233 pub singular_values: [f64; 3],
234 pub v_t: Option<Matrix3<f64>>,
235}
236
237fn svd_3x3(a: &Matrix3<f64>, compute_u: bool, compute_v: bool) -> Svd3 {
239 let ata = a.transpose() * *a;
241
242 let (eigenvalues, eigenvectors) = jacobi_eigen_3x3(&ata);
244
245 let mut sigma = [0.0f64; 3];
247 for i in 0..3 {
248 sigma[i] = eigenvalues[i].max(0.0).sqrt();
249 }
250
251 let v = eigenvectors;
253 let v_t = v.transpose();
254
255 let u_mat = if compute_u {
257 let mut u = Matrix3::zeros();
258 for col in 0..3 {
259 if sigma[col] > 1e-14 {
260 let v_col = v.column(col);
261 let av = a.mul_vec(&v_col);
262 let inv_s = 1.0 / sigma[col];
263 u.data[0][col] = av.x * inv_s;
264 u.data[1][col] = av.y * inv_s;
265 u.data[2][col] = av.z * inv_s;
266 }
267 }
268 Some(u)
269 } else {
270 None
271 };
272
273 Svd3 {
274 u: u_mat,
275 singular_values: sigma,
276 v_t: if compute_v { Some(v_t) } else { None },
277 }
278}
279
280fn jacobi_eigen_3x3(m: &Matrix3<f64>) -> ([f64; 3], Matrix3<f64>) {
283 let mut a = *m;
284 let mut v = Matrix3::identity();
285
286 for _ in 0..100 {
287 let mut max_val = 0.0f64;
289 let mut p = 0;
290 let mut q = 1;
291 for i in 0..3 {
292 for j in (i + 1)..3 {
293 if a.data[i][j].abs() > max_val {
294 max_val = a.data[i][j].abs();
295 p = i;
296 q = j;
297 }
298 }
299 }
300 if max_val < 1e-14 {
301 break;
302 }
303
304 let app = a.data[p][p];
306 let aqq = a.data[q][q];
307 let apq = a.data[p][q];
308 let theta = if (app - aqq).abs() < 1e-15 {
309 std::f64::consts::FRAC_PI_4
310 } else {
311 0.5 * (2.0 * apq / (app - aqq)).atan()
312 };
313
314 let c = theta.cos();
315 let s = theta.sin();
316
317 let mut new_a = a;
319 for i in 0..3 {
321 if i != p && i != q {
322 new_a.data[i][p] = c * a.data[i][p] + s * a.data[i][q];
323 new_a.data[p][i] = new_a.data[i][p];
324 new_a.data[i][q] = -s * a.data[i][p] + c * a.data[i][q];
325 new_a.data[q][i] = new_a.data[i][q];
326 }
327 }
328 new_a.data[p][p] = c * c * app + 2.0 * c * s * apq + s * s * aqq;
329 new_a.data[q][q] = s * s * app - 2.0 * c * s * apq + c * c * aqq;
330 new_a.data[p][q] = 0.0;
331 new_a.data[q][p] = 0.0;
332 a = new_a;
333
334 let mut new_v = v;
336 for i in 0..3 {
337 new_v.data[i][p] = c * v.data[i][p] + s * v.data[i][q];
338 new_v.data[i][q] = -s * v.data[i][p] + c * v.data[i][q];
339 }
340 v = new_v;
341 }
342
343 let mut eigenvalues = [a.data[0][0], a.data[1][1], a.data[2][2]];
345 let mut indices = [0usize, 1, 2];
346 for i in 0..3 {
348 for j in (i + 1)..3 {
349 if eigenvalues[j] > eigenvalues[i] {
350 eigenvalues.swap(i, j);
351 indices.swap(i, j);
352 }
353 }
354 }
355
356 let mut v_sorted = Matrix3::zeros();
358 for col in 0..3 {
359 let src = indices[col];
360 for row in 0..3 {
361 v_sorted.data[row][col] = v.data[row][src];
362 }
363 }
364
365 (eigenvalues, v_sorted)
366}
367
368#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
374pub struct Matrix4<T> {
375 pub data: [[T; 4]; 4],
376}
377
378impl<T: Default + Copy> Matrix4<T> {
379 #[must_use]
381 pub fn zeros() -> Self {
382 Self {
383 data: [[T::default(); 4]; 4],
384 }
385 }
386}
387
388impl Matrix4<f64> {
389 #[must_use]
391 pub fn identity() -> Self {
392 let mut m = Self::zeros();
393 for i in 0..4 {
394 m.data[i][i] = 1.0;
395 }
396 m
397 }
398
399 #[must_use]
401 pub fn transpose(&self) -> Self {
402 let mut m = Self::zeros();
403 for r in 0..4 {
404 for c in 0..4 {
405 m.data[c][r] = self.data[r][c];
406 }
407 }
408 m
409 }
410
411 #[must_use]
413 pub fn try_inverse(&self) -> Option<Self> {
414 let mut aug = [[0.0f64; 8]; 4];
415 for r in 0..4 {
416 for c in 0..4 {
417 aug[r][c] = self.data[r][c];
418 aug[r][c + 4] = if r == c { 1.0 } else { 0.0 };
419 }
420 }
421 for col in 0..4 {
422 let mut max_row = col;
424 let mut max_val = aug[col][col].abs();
425 for row in (col + 1)..4 {
426 if aug[row][col].abs() > max_val {
427 max_row = row;
428 max_val = aug[row][col].abs();
429 }
430 }
431 if max_val < 1e-15 {
432 return None;
433 }
434 aug.swap(col, max_row);
435 let pivot = aug[col][col];
436 for k in 0..8 {
437 aug[col][k] /= pivot;
438 }
439 for row in 0..4 {
440 if row == col {
441 continue;
442 }
443 let factor = aug[row][col];
444 for k in 0..8 {
445 aug[row][k] -= factor * aug[col][k];
446 }
447 }
448 }
449 let mut m = Self::zeros();
450 for r in 0..4 {
451 for c in 0..4 {
452 m.data[r][c] = aug[r][c + 4];
453 }
454 }
455 Some(m)
456 }
457
458 #[must_use]
460 pub fn fixed_view_3x3(&self, r0: usize, c0: usize) -> Matrix3<f64> {
461 let mut m = Matrix3::zeros();
462 for r in 0..3 {
463 for c in 0..3 {
464 m.data[r][c] = self.data[r0 + r][c0 + c];
465 }
466 }
467 m
468 }
469
470 pub fn set_block_3x3(&mut self, r0: usize, c0: usize, src: &Matrix3<f64>) {
472 for r in 0..3 {
473 for c in 0..3 {
474 self.data[r0 + r][c0 + c] = src.data[r][c];
475 }
476 }
477 }
478
479 pub fn set_block_3x1(&mut self, r0: usize, c0: usize, src: &Vector3<f64>) {
481 self.data[r0][c0] = src.x;
482 self.data[r0 + 1][c0] = src.y;
483 self.data[r0 + 2][c0] = src.z;
484 }
485
486 #[must_use]
488 pub fn get_block_3x1(&self, r0: usize, c0: usize) -> Vector3<f64> {
489 Vector3::new(
490 self.data[r0][c0],
491 self.data[r0 + 1][c0],
492 self.data[r0 + 2][c0],
493 )
494 }
495
496 #[must_use]
498 pub fn mul_homogeneous(&self, v: &[f64; 4]) -> [f64; 4] {
499 let mut out = [0.0f64; 4];
500 for r in 0..4 {
501 for c in 0..4 {
502 out[r] += self.data[r][c] * v[c];
503 }
504 }
505 out
506 }
507}
508
509impl Index<(usize, usize)> for Matrix4<f64> {
510 type Output = f64;
511 fn index(&self, (r, c): (usize, usize)) -> &f64 {
512 &self.data[r][c]
513 }
514}
515
516impl IndexMut<(usize, usize)> for Matrix4<f64> {
517 fn index_mut(&mut self, (r, c): (usize, usize)) -> &mut f64 {
518 &mut self.data[r][c]
519 }
520}
521
522impl Mul for Matrix4<f64> {
523 type Output = Self;
524 fn mul(self, rhs: Self) -> Self {
525 let mut m = Self::zeros();
526 for r in 0..4 {
527 for c in 0..4 {
528 for k in 0..4 {
529 m.data[r][c] += self.data[r][k] * rhs.data[k][c];
530 }
531 }
532 }
533 m
534 }
535}
536
537impl Mul<[f64; 4]> for Matrix4<f64> {
539 type Output = [f64; 4];
540 fn mul(self, rhs: [f64; 4]) -> [f64; 4] {
541 self.mul_homogeneous(&rhs)
542 }
543}
544
545#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
551pub struct Matrix6<T> {
552 pub data: [[T; 6]; 6],
553}
554
555impl<T: Default + Copy> Matrix6<T> {
556 #[must_use]
558 pub fn zeros() -> Self {
559 Self {
560 data: [[T::default(); 6]; 6],
561 }
562 }
563}
564
565impl Matrix6<f64> {
566 #[must_use]
568 pub fn identity() -> Self {
569 let mut m = Self::zeros();
570 for i in 0..6 {
571 m.data[i][i] = 1.0;
572 }
573 m
574 }
575
576 #[must_use]
578 pub fn transpose(&self) -> Self {
579 let mut m = Self::zeros();
580 for r in 0..6 {
581 for c in 0..6 {
582 m.data[c][r] = self.data[r][c];
583 }
584 }
585 m
586 }
587}
588
589impl Index<(usize, usize)> for Matrix6<f64> {
590 type Output = f64;
591 fn index(&self, (r, c): (usize, usize)) -> &f64 {
592 &self.data[r][c]
593 }
594}
595
596impl IndexMut<(usize, usize)> for Matrix6<f64> {
597 fn index_mut(&mut self, (r, c): (usize, usize)) -> &mut f64 {
598 &mut self.data[r][c]
599 }
600}
601
602impl Mul<f64> for Matrix6<f64> {
604 type Output = Self;
605 fn mul(self, rhs: f64) -> Self {
606 let mut m = self;
607 for r in 0..6 {
608 for c in 0..6 {
609 m.data[r][c] *= rhs;
610 }
611 }
612 m
613 }
614}
615
616impl Mul for Matrix6<f64> {
618 type Output = Self;
619 fn mul(self, rhs: Self) -> Self {
620 let mut m = Self::zeros();
621 for r in 0..6 {
622 for c in 0..6 {
623 for k in 0..6 {
624 m.data[r][c] += self.data[r][k] * rhs.data[k][c];
625 }
626 }
627 }
628 m
629 }
630}
631
632impl Mul<Vector6<f64>> for Matrix6<f64> {
634 type Output = Vector6<f64>;
635 fn mul(self, rhs: Vector6<f64>) -> Vector6<f64> {
636 let mut out = Vector6::zeros();
637 for r in 0..6 {
638 for c in 0..6 {
639 out.data[r] += self.data[r][c] * rhs.data[c];
640 }
641 }
642 out
643 }
644}
645
646impl Add for Matrix6<f64> {
647 type Output = Self;
648 fn add(self, rhs: Self) -> Self {
649 let mut m = self;
650 for r in 0..6 {
651 for c in 0..6 {
652 m.data[r][c] += rhs.data[r][c];
653 }
654 }
655 m
656 }
657}
658
659impl Sub for Matrix6<f64> {
660 type Output = Self;
661 fn sub(self, rhs: Self) -> Self {
662 let mut m = self;
663 for r in 0..6 {
664 for c in 0..6 {
665 m.data[r][c] -= rhs.data[r][c];
666 }
667 }
668 m
669 }
670}
671
672#[derive(Debug, Clone, Copy)]
678pub struct Matrix3x6 {
679 pub data: [[f64; 6]; 3],
680}
681
682impl Matrix3x6 {
683 #[must_use]
685 pub fn from_iterator<I: IntoIterator<Item = f64>>(iter: I) -> Self {
686 let elems: Vec<f64> = iter.into_iter().collect();
687 let mut m = Self {
688 data: [[0.0; 6]; 3],
689 };
690 for (idx, val) in elems.iter().enumerate() {
692 let col = idx / 3;
693 let row = idx % 3;
694 if row < 3 && col < 6 {
695 m.data[row][col] = *val;
696 }
697 }
698 m
699 }
700
701 #[must_use]
703 pub fn mul_vec6(&self, v: &Vector6<f64>) -> Vector3<f64> {
704 let mut out = [0.0f64; 3];
705 for r in 0..3 {
706 for c in 0..6 {
707 out[r] += self.data[r][c] * v.data[c];
708 }
709 }
710 Vector3::new(out[0], out[1], out[2])
711 }
712
713 #[must_use]
715 pub fn transpose(&self) -> Matrix6x3 {
716 let mut m = Matrix6x3 {
717 data: [[0.0; 3]; 6],
718 };
719 for r in 0..3 {
720 for c in 0..6 {
721 m.data[c][r] = self.data[r][c];
722 }
723 }
724 m
725 }
726}
727
728impl Mul<Vector6<f64>> for Matrix3x6 {
730 type Output = Vector3<f64>;
731 fn mul(self, rhs: Vector6<f64>) -> Vector3<f64> {
732 self.mul_vec6(&rhs)
733 }
734}
735
736impl Mul<Matrix6<f64>> for Matrix3x6 {
738 type Output = Self;
739 fn mul(self, rhs: Matrix6<f64>) -> Self {
740 let mut m = Self {
741 data: [[0.0; 6]; 3],
742 };
743 for r in 0..3 {
744 for c in 0..6 {
745 for k in 0..6 {
746 m.data[r][c] += self.data[r][k] * rhs.data[k][c];
747 }
748 }
749 }
750 m
751 }
752}
753
754impl Mul<Matrix6x3> for Matrix3x6 {
756 type Output = Matrix3<f64>;
757 fn mul(self, rhs: Matrix6x3) -> Matrix3<f64> {
758 let mut m = Matrix3::zeros();
759 for r in 0..3 {
760 for c in 0..3 {
761 for k in 0..6 {
762 m.data[r][c] += self.data[r][k] * rhs.data[k][c];
763 }
764 }
765 }
766 m
767 }
768}
769
770#[derive(Debug, Clone, Copy)]
776pub struct Matrix6x3 {
777 pub data: [[f64; 3]; 6],
778}
779
780impl Mul<Matrix3<f64>> for Matrix6x3 {
782 type Output = Self;
783 fn mul(self, rhs: Matrix3<f64>) -> Self {
784 let mut m = Self {
785 data: [[0.0; 3]; 6],
786 };
787 for r in 0..6 {
788 for c in 0..3 {
789 for k in 0..3 {
790 m.data[r][c] += self.data[r][k] * rhs.data[k][c];
791 }
792 }
793 }
794 m
795 }
796}
797
798impl Mul<Matrix6x3> for Matrix6<f64> {
800 type Output = Matrix6x3;
801 fn mul(self, rhs: Matrix6x3) -> Matrix6x3 {
802 let mut m = Matrix6x3 {
803 data: [[0.0; 3]; 6],
804 };
805 for r in 0..6 {
806 for c in 0..3 {
807 for k in 0..6 {
808 m.data[r][c] += self.data[r][k] * rhs.data[k][c];
809 }
810 }
811 }
812 m
813 }
814}
815
816impl Matrix6x3 {
822 #[must_use]
824 pub fn mul_vec3(&self, v: &Vector3<f64>) -> Vector6<f64> {
825 let mut out = Vector6::zeros();
826 let arr = [v.x, v.y, v.z];
827 for r in 0..6 {
828 for c in 0..3 {
829 out.data[r] += self.data[r][c] * arr[c];
830 }
831 }
832 out
833 }
834
835 #[must_use]
837 pub fn mul_3x6(&self, rhs: &Matrix3x6) -> Matrix6<f64> {
838 let mut m = Matrix6::zeros();
839 for r in 0..6 {
840 for c in 0..6 {
841 for k in 0..3 {
842 m.data[r][c] += self.data[r][k] * rhs.data[k][c];
843 }
844 }
845 }
846 m
847 }
848}
849
850#[cfg(test)]
855mod tests {
856 use super::*;
857
858 #[test]
859 fn test_matrix3_identity_determinant() {
860 let m = Matrix3::identity();
861 assert!((m.determinant() - 1.0).abs() < 1e-10);
862 }
863
864 #[test]
865 fn test_matrix3_inverse() {
866 let m = Matrix3::identity();
867 let inv = m.try_inverse().expect("should succeed in test");
868 assert!((inv.data[0][0] - 1.0).abs() < 1e-10);
869 }
870
871 #[test]
872 fn test_matrix4_inverse() {
873 let m = Matrix4::identity();
874 let inv = m.try_inverse().expect("should succeed in test");
875 for i in 0..4 {
876 assert!((inv.data[i][i] - 1.0).abs() < 1e-10);
877 }
878 }
879
880 #[test]
881 fn test_matrix6_mul_identity() {
882 let m = Matrix6::identity();
883 let result = m * m;
884 for i in 0..6 {
885 assert!((result.data[i][i] - 1.0).abs() < 1e-10);
886 }
887 }
888
889 #[test]
890 fn test_svd_identity() {
891 let m = Matrix3::identity();
892 let svd = m.svd(true, true);
893 for i in 0..3 {
894 assert!((svd.singular_values[i] - 1.0).abs() < 1e-6);
895 }
896 }
897
898 #[test]
899 fn test_matrix3x6_mul_vec6() {
900 let h = Matrix3x6::from_iterator([
903 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
904 0.0,
905 ]);
906 let v = Vector6 {
907 data: [10.0, 20.0, 30.0, 40.0, 50.0, 60.0],
908 };
909 let result = h * v;
910 assert!((result.x - 10.0).abs() < 1e-10);
911 assert!((result.y - 20.0).abs() < 1e-10);
912 assert!((result.z - 30.0).abs() < 1e-10);
913 }
914}