1use crate::math::{FusedMultiplyAdd, FusedMultiplyNegAdd};
30use crate::mlaf::{mlaf, neg_mlaf};
31use crate::reader::s15_fixed16_number_to_double;
32use num_traits::{AsPrimitive, MulAdd};
33use std::ops::{Add, Div, Mul, Neg, Shr, Sub};
34
35#[repr(transparent)]
37#[derive(Copy, Clone, Debug, Default)]
38pub struct Vector3<T> {
39 pub v: [T; 3],
40}
41
42#[repr(transparent)]
44#[derive(Copy, Clone, Debug, Default)]
45pub struct Vector4<T> {
46 pub v: [T; 4],
47}
48
49pub type Vector4f = Vector4<f32>;
50pub type Vector4d = Vector4<f64>;
51pub type Vector4i = Vector4<i32>;
52
53pub type Vector3f = Vector3<f32>;
54pub type Vector3d = Vector3<f64>;
55pub type Vector3i = Vector3<i32>;
56pub type Vector3u = Vector3<u32>;
57
58impl<T> PartialEq<Self> for Vector3<T>
59where
60 T: AsPrimitive<f32>,
61{
62 #[inline(always)]
63 fn eq(&self, other: &Self) -> bool {
64 const TOLERANCE: f32 = 0.0001f32;
65 let dx = (self.v[0].as_() - other.v[0].as_()).abs();
66 let dy = (self.v[1].as_() - other.v[1].as_()).abs();
67 let dz = (self.v[2].as_() - other.v[2].as_()).abs();
68 dx < TOLERANCE && dy < TOLERANCE && dz < TOLERANCE
69 }
70}
71
72impl<T> Vector3<T> {
73 #[inline(always)]
74 pub fn to_<Z: Copy + 'static>(self) -> Vector3<Z>
75 where
76 T: AsPrimitive<Z>,
77 {
78 Vector3 {
79 v: [self.v[0].as_(), self.v[1].as_(), self.v[2].as_()],
80 }
81 }
82}
83
84impl<T> Mul<Vector3<T>> for Vector3<T>
85where
86 T: Mul<Output = T> + Copy,
87{
88 type Output = Vector3<T>;
89
90 #[inline(always)]
91 fn mul(self, rhs: Vector3<T>) -> Self::Output {
92 Self {
93 v: [
94 self.v[0] * rhs.v[0],
95 self.v[1] * rhs.v[1],
96 self.v[2] * rhs.v[2],
97 ],
98 }
99 }
100}
101
102impl<T: Copy> Shr<i32> for Vector3<T>
103where
104 T: Shr<i32, Output = T>,
105{
106 type Output = Vector3<T>;
107 fn shr(self, rhs: i32) -> Self::Output {
108 Self {
109 v: [self.v[0] >> rhs, self.v[1] >> rhs, self.v[2] >> rhs],
110 }
111 }
112}
113
114impl<T: Copy> Shr<i32> for Vector4<T>
115where
116 T: Shr<i32, Output = T>,
117{
118 type Output = Vector4<T>;
119 fn shr(self, rhs: i32) -> Self::Output {
120 Self {
121 v: [
122 self.v[0] >> rhs,
123 self.v[1] >> rhs,
124 self.v[2] >> rhs,
125 self.v[3] >> rhs,
126 ],
127 }
128 }
129}
130
131impl<T> Mul<Vector4<T>> for Vector4<T>
132where
133 T: Mul<Output = T> + Copy,
134{
135 type Output = Vector4<T>;
136
137 #[inline(always)]
138 fn mul(self, rhs: Vector4<T>) -> Self::Output {
139 Self {
140 v: [
141 self.v[0] * rhs.v[0],
142 self.v[1] * rhs.v[1],
143 self.v[2] * rhs.v[2],
144 self.v[3] * rhs.v[3],
145 ],
146 }
147 }
148}
149
150impl<T> Mul<T> for Vector3<T>
151where
152 T: Mul<Output = T> + Copy,
153{
154 type Output = Vector3<T>;
155
156 #[inline(always)]
157 fn mul(self, rhs: T) -> Self::Output {
158 Self {
159 v: [self.v[0] * rhs, self.v[1] * rhs, self.v[2] * rhs],
160 }
161 }
162}
163
164impl Vector3<f32> {
165 #[inline(always)]
166 const fn const_mul_vector(self, v: Vector3f) -> Vector3f {
167 Vector3f {
168 v: [self.v[0] * v.v[0], self.v[1] * v.v[1], self.v[2] * v.v[2]],
169 }
170 }
171}
172
173impl Vector3d {
174 #[inline(always)]
175 const fn const_mul_vector(self, v: Vector3d) -> Vector3d {
176 Vector3d {
177 v: [self.v[0] * v.v[0], self.v[1] * v.v[1], self.v[2] * v.v[2]],
178 }
179 }
180}
181
182impl<T: 'static> Vector3<T> {
183 pub fn cast<V: Copy + 'static>(&self) -> Vector3<V>
184 where
185 T: AsPrimitive<V>,
186 {
187 Vector3::<V> {
188 v: [self.v[0].as_(), self.v[1].as_(), self.v[2].as_()],
189 }
190 }
191}
192
193impl<T> Mul<T> for Vector4<T>
194where
195 T: Mul<Output = T> + Copy,
196{
197 type Output = Vector4<T>;
198
199 #[inline(always)]
200 fn mul(self, rhs: T) -> Self::Output {
201 Self {
202 v: [
203 self.v[0] * rhs,
204 self.v[1] * rhs,
205 self.v[2] * rhs,
206 self.v[3] * rhs,
207 ],
208 }
209 }
210}
211
212impl<T: Copy + Mul<T, Output = T> + Add<T, Output = T> + MulAdd<T, Output = T>>
213 FusedMultiplyAdd<Vector3<T>> for Vector3<T>
214{
215 #[inline(always)]
216 fn mla(&self, b: Vector3<T>, c: Vector3<T>) -> Vector3<T> {
217 let x0 = mlaf(self.v[0], b.v[0], c.v[0]);
218 let x1 = mlaf(self.v[1], b.v[1], c.v[1]);
219 let x2 = mlaf(self.v[2], b.v[2], c.v[2]);
220 Vector3 { v: [x0, x1, x2] }
221 }
222}
223
224impl<T: Copy + Mul<T, Output = T> + Add<T, Output = T> + MulAdd<T, Output = T> + Neg<Output = T>>
225 FusedMultiplyNegAdd<Vector3<T>> for Vector3<T>
226{
227 #[inline(always)]
228 fn neg_mla(&self, b: Vector3<T>, c: Vector3<T>) -> Vector3<T> {
229 let x0 = neg_mlaf(self.v[0], b.v[0], c.v[0]);
230 let x1 = neg_mlaf(self.v[1], b.v[1], c.v[1]);
231 let x2 = neg_mlaf(self.v[2], b.v[2], c.v[2]);
232 Vector3 { v: [x0, x1, x2] }
233 }
234}
235
236impl<T: Copy + Mul<T, Output = T> + Add<T, Output = T> + MulAdd<T, Output = T>>
237 FusedMultiplyAdd<Vector4<T>> for Vector4<T>
238{
239 #[inline(always)]
240 fn mla(&self, b: Vector4<T>, c: Vector4<T>) -> Vector4<T> {
241 let x0 = mlaf(self.v[0], b.v[0], c.v[0]);
242 let x1 = mlaf(self.v[1], b.v[1], c.v[1]);
243 let x2 = mlaf(self.v[2], b.v[2], c.v[2]);
244 let x3 = mlaf(self.v[3], b.v[3], c.v[3]);
245 Vector4 {
246 v: [x0, x1, x2, x3],
247 }
248 }
249}
250
251impl<T: Copy + Mul<T, Output = T> + Add<T, Output = T> + MulAdd<T, Output = T> + Neg<Output = T>>
252 FusedMultiplyNegAdd<Vector4<T>> for Vector4<T>
253{
254 #[inline(always)]
255 fn neg_mla(&self, b: Vector4<T>, c: Vector4<T>) -> Vector4<T> {
256 let x0 = neg_mlaf(self.v[0], b.v[0], c.v[0]);
257 let x1 = neg_mlaf(self.v[1], b.v[1], c.v[1]);
258 let x2 = neg_mlaf(self.v[2], b.v[2], c.v[2]);
259 let x3 = neg_mlaf(self.v[3], b.v[3], c.v[3]);
260 Vector4 {
261 v: [x0, x1, x2, x3],
262 }
263 }
264}
265
266impl<T> From<T> for Vector3<T>
267where
268 T: Copy,
269{
270 fn from(value: T) -> Self {
271 Self {
272 v: [value, value, value],
273 }
274 }
275}
276
277impl<T> From<T> for Vector4<T>
278where
279 T: Copy,
280{
281 fn from(value: T) -> Self {
282 Self {
283 v: [value, value, value, value],
284 }
285 }
286}
287
288impl<T> Add<Vector3<T>> for Vector3<T>
289where
290 T: Add<Output = T> + Copy,
291{
292 type Output = Vector3<T>;
293
294 #[inline(always)]
295 fn add(self, rhs: Vector3<T>) -> Self::Output {
296 Self {
297 v: [
298 self.v[0] + rhs.v[0],
299 self.v[1] + rhs.v[1],
300 self.v[2] + rhs.v[2],
301 ],
302 }
303 }
304}
305
306impl<T> Add<Vector4<T>> for Vector4<T>
307where
308 T: Add<Output = T> + Copy,
309{
310 type Output = Vector4<T>;
311
312 #[inline(always)]
313 fn add(self, rhs: Vector4<T>) -> Self::Output {
314 Self {
315 v: [
316 self.v[0] + rhs.v[0],
317 self.v[1] + rhs.v[1],
318 self.v[2] + rhs.v[2],
319 self.v[3] + rhs.v[3],
320 ],
321 }
322 }
323}
324
325impl<T> Add<T> for Vector3<T>
326where
327 T: Add<Output = T> + Copy,
328{
329 type Output = Vector3<T>;
330
331 #[inline(always)]
332 fn add(self, rhs: T) -> Self::Output {
333 Self {
334 v: [self.v[0] + rhs, self.v[1] + rhs, self.v[2] + rhs],
335 }
336 }
337}
338
339impl<T> Add<T> for Vector4<T>
340where
341 T: Add<Output = T> + Copy,
342{
343 type Output = Vector4<T>;
344
345 #[inline(always)]
346 fn add(self, rhs: T) -> Self::Output {
347 Self {
348 v: [
349 self.v[0] + rhs,
350 self.v[1] + rhs,
351 self.v[2] + rhs,
352 self.v[3] + rhs,
353 ],
354 }
355 }
356}
357
358impl<T> Sub<Vector3<T>> for Vector3<T>
359where
360 T: Sub<Output = T> + Copy,
361{
362 type Output = Vector3<T>;
363
364 #[inline(always)]
365 fn sub(self, rhs: Vector3<T>) -> Self::Output {
366 Self {
367 v: [
368 self.v[0] - rhs.v[0],
369 self.v[1] - rhs.v[1],
370 self.v[2] - rhs.v[2],
371 ],
372 }
373 }
374}
375
376impl<T> Sub<Vector4<T>> for Vector4<T>
377where
378 T: Sub<Output = T> + Copy,
379{
380 type Output = Vector4<T>;
381
382 #[inline(always)]
383 fn sub(self, rhs: Vector4<T>) -> Self::Output {
384 Self {
385 v: [
386 self.v[0] - rhs.v[0],
387 self.v[1] - rhs.v[1],
388 self.v[2] - rhs.v[2],
389 self.v[3] - rhs.v[3],
390 ],
391 }
392 }
393}
394
395#[repr(C)]
397#[derive(Copy, Clone, Debug, Default)]
398pub struct Matrix3f {
399 pub v: [[f32; 3]; 3],
400}
401
402#[repr(C)]
404#[derive(Copy, Clone, Debug, Default)]
405pub struct Matrix3d {
406 pub v: [[f64; 3]; 3],
407}
408
409#[repr(C)]
410#[derive(Copy, Clone, Debug, Default)]
411pub struct Matrix3<T> {
412 pub v: [[T; 3]; 3],
413}
414
415impl<T: Copy> Matrix3<T> {
416 #[inline]
417 #[allow(dead_code)]
418 pub(crate) fn transpose(&self) -> Matrix3<T> {
419 Matrix3 {
420 v: [
421 [self.v[0][0], self.v[1][0], self.v[2][0]],
422 [self.v[0][1], self.v[1][1], self.v[2][1]],
423 [self.v[0][2], self.v[1][2], self.v[2][2]],
424 ],
425 }
426 }
427}
428
429#[repr(C)]
430#[derive(Copy, Clone, Debug, Default)]
431pub struct Matrix4f {
432 pub v: [[f32; 4]; 4],
433}
434
435pub const SRGB_MATRIX: Matrix3d = Matrix3d {
436 v: [
437 [
438 s15_fixed16_number_to_double(0x6FA2),
439 s15_fixed16_number_to_double(0x6299),
440 s15_fixed16_number_to_double(0x24A0),
441 ],
442 [
443 s15_fixed16_number_to_double(0x38F5),
444 s15_fixed16_number_to_double(0xB785),
445 s15_fixed16_number_to_double(0x0F84),
446 ],
447 [
448 s15_fixed16_number_to_double(0x0390),
449 s15_fixed16_number_to_double(0x18DA),
450 s15_fixed16_number_to_double(0xB6CF),
451 ],
452 ],
453};
454
455pub const DISPLAY_P3_MATRIX: Matrix3d = Matrix3d {
456 v: [
457 [0.515102, 0.291965, 0.157153],
458 [0.241182, 0.692236, 0.0665819],
459 [-0.00104941, 0.0418818, 0.784378],
460 ],
461};
462
463pub const BT2020_MATRIX: Matrix3d = Matrix3d {
464 v: [
465 [0.673459, 0.165661, 0.125100],
466 [0.279033, 0.675338, 0.0456288],
467 [-0.00193139, 0.0299794, 0.797162],
468 ],
469};
470
471impl Matrix4f {
472 #[inline]
473 pub fn determinant(&self) -> Option<f32> {
474 let a = self.v[0][0];
475 let b = self.v[0][1];
476 let c = self.v[0][2];
477 let d = self.v[0][3];
478
479 let m11 = Matrix3f {
482 v: [
483 [self.v[1][1], self.v[1][2], self.v[1][3]],
484 [self.v[2][1], self.v[2][2], self.v[2][3]],
485 [self.v[3][1], self.v[3][2], self.v[3][3]],
486 ],
487 };
488
489 let m12 = Matrix3f {
490 v: [
491 [self.v[1][0], self.v[1][2], self.v[1][3]],
492 [self.v[2][0], self.v[2][2], self.v[2][3]],
493 [self.v[3][0], self.v[3][2], self.v[3][3]],
494 ],
495 };
496
497 let m13 = Matrix3f {
498 v: [
499 [self.v[1][0], self.v[1][1], self.v[1][3]],
500 [self.v[2][0], self.v[2][1], self.v[2][3]],
501 [self.v[3][0], self.v[3][1], self.v[3][3]],
502 ],
503 };
504
505 let m14 = Matrix3f {
506 v: [
507 [self.v[1][0], self.v[1][1], self.v[1][2]],
508 [self.v[2][0], self.v[2][1], self.v[2][2]],
509 [self.v[3][0], self.v[3][1], self.v[3][2]],
510 ],
511 };
512
513 let m1_det = m11.determinant()?;
514 let m2_det = m12.determinant()?;
515 let m3_det = m13.determinant()?;
516 let m4_det = m14.determinant()?;
517
518 Some(a * m1_det - b * m2_det + c * m3_det - d * m4_det)
520 }
521}
522
523impl Matrix3f {
524 #[inline]
525 pub fn transpose(&self) -> Matrix3f {
526 Matrix3f {
527 v: [
528 [self.v[0][0], self.v[1][0], self.v[2][0]],
529 [self.v[0][1], self.v[1][1], self.v[2][1]],
530 [self.v[0][2], self.v[1][2], self.v[2][2]],
531 ],
532 }
533 }
534
535 pub const IDENTITY: Matrix3f = Matrix3f {
536 v: [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
537 };
538
539 #[inline]
540 pub const fn test_equality(&self, other: Matrix3f) -> bool {
541 const TOLERANCE: f32 = 0.001f32;
542 let diff_r_x = (self.v[0][0] - other.v[0][0]).abs();
543 let diff_r_y = (self.v[0][1] - other.v[0][1]).abs();
544 let diff_r_z = (self.v[0][2] - other.v[0][2]).abs();
545
546 if diff_r_x > TOLERANCE || diff_r_y > TOLERANCE || diff_r_z > TOLERANCE {
547 return false;
548 }
549
550 let diff_g_x = (self.v[1][0] - other.v[1][0]).abs();
551 let diff_g_y = (self.v[1][1] - other.v[1][1]).abs();
552 let diff_g_z = (self.v[1][2] - other.v[1][2]).abs();
553
554 if diff_g_x > TOLERANCE || diff_g_y > TOLERANCE || diff_g_z > TOLERANCE {
555 return false;
556 }
557
558 let diff_b_x = (self.v[2][0] - other.v[2][0]).abs();
559 let diff_b_y = (self.v[2][1] - other.v[2][1]).abs();
560 let diff_b_z = (self.v[2][2] - other.v[2][2]).abs();
561
562 if diff_b_x > TOLERANCE || diff_b_y > TOLERANCE || diff_b_z > TOLERANCE {
563 return false;
564 }
565
566 true
567 }
568
569 #[inline]
570 pub const fn determinant(&self) -> Option<f32> {
571 let v = self.v;
572 let a0 = v[0][0] * v[1][1] * v[2][2];
573 let a1 = v[0][1] * v[1][2] * v[2][0];
574 let a2 = v[0][2] * v[1][0] * v[2][1];
575
576 let s0 = v[0][2] * v[1][1] * v[2][0];
577 let s1 = v[0][1] * v[1][0] * v[2][2];
578 let s2 = v[0][0] * v[1][2] * v[2][1];
579
580 let j = a0 + a1 + a2 - s0 - s1 - s2;
581 if j == 0. {
582 return None;
583 }
584 Some(j)
585 }
586
587 #[inline]
588 pub const fn inverse(&self) -> Self {
589 let v = self.v;
590 let det = self.determinant();
591 match det {
592 None => Matrix3f::IDENTITY,
593 Some(determinant) => {
594 let det = 1. / determinant;
595 let a = v[0][0];
596 let b = v[0][1];
597 let c = v[0][2];
598 let d = v[1][0];
599 let e = v[1][1];
600 let f = v[1][2];
601 let g = v[2][0];
602 let h = v[2][1];
603 let i = v[2][2];
604
605 Matrix3f {
606 v: [
607 [
608 (e * i - f * h) * det,
609 (c * h - b * i) * det,
610 (b * f - c * e) * det,
611 ],
612 [
613 (f * g - d * i) * det,
614 (a * i - c * g) * det,
615 (c * d - a * f) * det,
616 ],
617 [
618 (d * h - e * g) * det,
619 (b * g - a * h) * det,
620 (a * e - b * d) * det,
621 ],
622 ],
623 }
624 }
625 }
626 }
627
628 #[inline]
629 pub fn mul_row<const R: usize>(&self, rhs: f32) -> Self {
630 if R == 0 {
631 Self {
632 v: [(Vector3f { v: self.v[0] } * rhs).v, self.v[1], self.v[2]],
633 }
634 } else if R == 1 {
635 Self {
636 v: [self.v[0], (Vector3f { v: self.v[1] } * rhs).v, self.v[2]],
637 }
638 } else if R == 2 {
639 Self {
640 v: [self.v[0], self.v[1], (Vector3f { v: self.v[2] } * rhs).v],
641 }
642 } else {
643 unimplemented!()
644 }
645 }
646
647 #[inline]
648 pub const fn mul_row_vector<const R: usize>(&self, rhs: Vector3f) -> Self {
649 if R == 0 {
650 Self {
651 v: [
652 (Vector3f { v: self.v[0] }.const_mul_vector(rhs)).v,
653 self.v[1],
654 self.v[2],
655 ],
656 }
657 } else if R == 1 {
658 Self {
659 v: [
660 self.v[0],
661 (Vector3f { v: self.v[1] }.const_mul_vector(rhs)).v,
662 self.v[2],
663 ],
664 }
665 } else if R == 2 {
666 Self {
667 v: [
668 self.v[0],
669 self.v[1],
670 (Vector3f { v: self.v[2] }.const_mul_vector(rhs)).v,
671 ],
672 }
673 } else {
674 unimplemented!()
675 }
676 }
677
678 #[inline]
679 pub const fn mul_vector(&self, other: Vector3f) -> Vector3f {
680 let x = self.v[0][1] * other.v[1] + self.v[0][2] * other.v[2] + self.v[0][0] * other.v[0];
681 let y = self.v[1][0] * other.v[0] + self.v[1][1] * other.v[1] + self.v[1][2] * other.v[2];
682 let z = self.v[2][0] * other.v[0] + self.v[2][1] * other.v[1] + self.v[2][2] * other.v[2];
683 Vector3f { v: [x, y, z] }
684 }
685
686 #[inline]
688 pub fn f_mul_vector(&self, other: Vector3f) -> Vector3f {
689 let x = mlaf(
690 mlaf(self.v[0][1] * other.v[1], self.v[0][2], other.v[2]),
691 self.v[0][0],
692 other.v[0],
693 );
694 let y = mlaf(
695 mlaf(self.v[1][0] * other.v[0], self.v[1][1], other.v[1]),
696 self.v[1][2],
697 other.v[2],
698 );
699 let z = mlaf(
700 mlaf(self.v[2][0] * other.v[0], self.v[2][1], other.v[1]),
701 self.v[2][2],
702 other.v[2],
703 );
704 Vector3f { v: [x, y, z] }
705 }
706
707 #[inline]
708 pub fn mat_mul(&self, other: Matrix3f) -> Self {
709 let mut result = Matrix3f::default();
710
711 for i in 0..3 {
712 for j in 0..3 {
713 result.v[i][j] = mlaf(
714 mlaf(self.v[i][0] * other.v[0][j], self.v[i][1], other.v[1][j]),
715 self.v[i][2],
716 other.v[2][j],
717 );
718 }
719 }
720
721 result
722 }
723
724 #[inline]
725 pub const fn mat_mul_const(&self, other: Matrix3f) -> Self {
726 let mut result = Matrix3f { v: [[0f32; 3]; 3] };
727 let mut i = 0usize;
728 while i < 3 {
729 let mut j = 0usize;
730 while j < 3 {
731 result.v[i][j] = self.v[i][0] * other.v[0][j]
732 + self.v[i][1] * other.v[1][j]
733 + self.v[i][2] * other.v[2][j];
734 j += 1;
735 }
736 i += 1;
737 }
738
739 result
740 }
741
742 #[inline]
743 pub const fn to_f64(&self) -> Matrix3d {
744 Matrix3d {
745 v: [
746 [
747 self.v[0][0] as f64,
748 self.v[0][1] as f64,
749 self.v[0][2] as f64,
750 ],
751 [
752 self.v[1][0] as f64,
753 self.v[1][1] as f64,
754 self.v[1][2] as f64,
755 ],
756 [
757 self.v[2][0] as f64,
758 self.v[2][1] as f64,
759 self.v[2][2] as f64,
760 ],
761 ],
762 }
763 }
764}
765
766impl Matrix3d {
767 #[inline]
768 pub fn transpose(&self) -> Matrix3d {
769 Matrix3d {
770 v: [
771 [self.v[0][0], self.v[1][0], self.v[2][0]],
772 [self.v[0][1], self.v[1][1], self.v[2][1]],
773 [self.v[0][2], self.v[1][2], self.v[2][2]],
774 ],
775 }
776 }
777
778 pub const IDENTITY: Matrix3d = Matrix3d {
779 v: [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
780 };
781
782 #[inline]
783 pub const fn test_equality(&self, other: Matrix3d) -> bool {
784 const TOLERANCE: f64 = 0.001f64;
785 let diff_r_x = (self.v[0][0] - other.v[0][0]).abs();
786 let diff_r_y = (self.v[0][1] - other.v[0][1]).abs();
787 let diff_r_z = (self.v[0][2] - other.v[0][2]).abs();
788
789 if diff_r_x > TOLERANCE || diff_r_y > TOLERANCE || diff_r_z > TOLERANCE {
790 return false;
791 }
792
793 let diff_g_x = (self.v[1][0] - other.v[1][0]).abs();
794 let diff_g_y = (self.v[1][1] - other.v[1][1]).abs();
795 let diff_g_z = (self.v[1][2] - other.v[1][2]).abs();
796
797 if diff_g_x > TOLERANCE || diff_g_y > TOLERANCE || diff_g_z > TOLERANCE {
798 return false;
799 }
800
801 let diff_b_x = (self.v[2][0] - other.v[2][0]).abs();
802 let diff_b_y = (self.v[2][1] - other.v[2][1]).abs();
803 let diff_b_z = (self.v[2][2] - other.v[2][2]).abs();
804
805 if diff_b_x > TOLERANCE || diff_b_y > TOLERANCE || diff_b_z > TOLERANCE {
806 return false;
807 }
808
809 true
810 }
811
812 #[inline]
813 pub const fn determinant(&self) -> Option<f64> {
814 let v = self.v;
815 let a0 = v[0][0] * v[1][1] * v[2][2];
816 let a1 = v[0][1] * v[1][2] * v[2][0];
817 let a2 = v[0][2] * v[1][0] * v[2][1];
818
819 let s0 = v[0][2] * v[1][1] * v[2][0];
820 let s1 = v[0][1] * v[1][0] * v[2][2];
821 let s2 = v[0][0] * v[1][2] * v[2][1];
822
823 let j = a0 + a1 + a2 - s0 - s1 - s2;
824 if j == 0. {
825 return None;
826 }
827 Some(j)
828 }
829
830 #[inline]
831 pub const fn inverse(&self) -> Self {
832 let v = self.v;
833 let det = self.determinant();
834 match det {
835 None => Matrix3d::IDENTITY,
836 Some(determinant) => {
837 let det = 1. / determinant;
838 let a = v[0][0];
839 let b = v[0][1];
840 let c = v[0][2];
841 let d = v[1][0];
842 let e = v[1][1];
843 let f = v[1][2];
844 let g = v[2][0];
845 let h = v[2][1];
846 let i = v[2][2];
847
848 Matrix3d {
849 v: [
850 [
851 (e * i - f * h) * det,
852 (c * h - b * i) * det,
853 (b * f - c * e) * det,
854 ],
855 [
856 (f * g - d * i) * det,
857 (a * i - c * g) * det,
858 (c * d - a * f) * det,
859 ],
860 [
861 (d * h - e * g) * det,
862 (b * g - a * h) * det,
863 (a * e - b * d) * det,
864 ],
865 ],
866 }
867 }
868 }
869 }
870
871 #[inline]
872 pub fn mul_row<const R: usize>(&self, rhs: f64) -> Self {
873 if R == 0 {
874 Self {
875 v: [(Vector3d { v: self.v[0] } * rhs).v, self.v[1], self.v[2]],
876 }
877 } else if R == 1 {
878 Self {
879 v: [self.v[0], (Vector3d { v: self.v[1] } * rhs).v, self.v[2]],
880 }
881 } else if R == 2 {
882 Self {
883 v: [self.v[0], self.v[1], (Vector3d { v: self.v[2] } * rhs).v],
884 }
885 } else {
886 unimplemented!()
887 }
888 }
889
890 #[inline]
891 pub const fn mul_row_vector<const R: usize>(&self, rhs: Vector3d) -> Self {
892 if R == 0 {
893 Self {
894 v: [
895 (Vector3d { v: self.v[0] }.const_mul_vector(rhs)).v,
896 self.v[1],
897 self.v[2],
898 ],
899 }
900 } else if R == 1 {
901 Self {
902 v: [
903 self.v[0],
904 (Vector3d { v: self.v[1] }.const_mul_vector(rhs)).v,
905 self.v[2],
906 ],
907 }
908 } else if R == 2 {
909 Self {
910 v: [
911 self.v[0],
912 self.v[1],
913 (Vector3d { v: self.v[2] }.const_mul_vector(rhs)).v,
914 ],
915 }
916 } else {
917 unimplemented!()
918 }
919 }
920
921 #[inline]
922 pub const fn mul_vector(&self, other: Vector3d) -> Vector3d {
923 let x = self.v[0][1] * other.v[1] + self.v[0][2] * other.v[2] + self.v[0][0] * other.v[0];
924 let y = self.v[1][0] * other.v[0] + self.v[1][1] * other.v[1] + self.v[1][2] * other.v[2];
925 let z = self.v[2][0] * other.v[0] + self.v[2][1] * other.v[1] + self.v[2][2] * other.v[2];
926 Vector3::<f64> { v: [x, y, z] }
927 }
928
929 #[inline]
930 pub fn mat_mul(&self, other: Matrix3d) -> Self {
931 let mut result = Matrix3d::default();
932
933 for i in 0..3 {
934 for j in 0..3 {
935 result.v[i][j] = mlaf(
936 mlaf(self.v[i][0] * other.v[0][j], self.v[i][1], other.v[1][j]),
937 self.v[i][2],
938 other.v[2][j],
939 );
940 }
941 }
942
943 result
944 }
945
946 #[inline]
947 pub const fn mat_mul_const(&self, other: Matrix3d) -> Self {
948 let mut result = Matrix3d { v: [[0.; 3]; 3] };
949 let mut i = 0usize;
950 while i < 3 {
951 let mut j = 0usize;
952 while j < 3 {
953 result.v[i][j] = self.v[i][0] * other.v[0][j]
954 + self.v[i][1] * other.v[1][j]
955 + self.v[i][2] * other.v[2][j];
956 j += 1;
957 }
958 i += 1;
959 }
960
961 result
962 }
963
964 #[inline]
965 pub const fn to_f32(&self) -> Matrix3f {
966 Matrix3f {
967 v: [
968 [
969 self.v[0][0] as f32,
970 self.v[0][1] as f32,
971 self.v[0][2] as f32,
972 ],
973 [
974 self.v[1][0] as f32,
975 self.v[1][1] as f32,
976 self.v[1][2] as f32,
977 ],
978 [
979 self.v[2][0] as f32,
980 self.v[2][1] as f32,
981 self.v[2][2] as f32,
982 ],
983 ],
984 }
985 }
986}
987
988impl Mul<Matrix3f> for Matrix3f {
989 type Output = Matrix3f;
990
991 #[inline]
992 fn mul(self, rhs: Matrix3f) -> Self::Output {
993 self.mat_mul(rhs)
994 }
995}
996
997impl Mul<Matrix3d> for Matrix3d {
998 type Output = Matrix3d;
999
1000 #[inline]
1001 fn mul(self, rhs: Matrix3d) -> Self::Output {
1002 self.mat_mul(rhs)
1003 }
1004}
1005
1006#[repr(C)]
1008#[derive(Clone, Debug, Copy, Default)]
1009pub struct Xyz {
1010 pub x: f32,
1011 pub y: f32,
1012 pub z: f32,
1013}
1014
1015impl Xyz {
1016 #[inline]
1017 pub fn to_xyy(&self) -> [f32; 3] {
1018 let sums = self.x + self.y + self.z;
1019 if sums == 0. {
1020 return [0., 0., self.y];
1021 }
1022 let x = self.x / sums;
1023 let y = self.y / sums;
1024 let yb = self.y;
1025 [x, y, yb]
1026 }
1027
1028 #[inline]
1029 pub fn from_xyy(xyy: [f32; 3]) -> Xyz {
1030 let reciprocal = if xyy[1] != 0. {
1031 1. / xyy[1] * xyy[2]
1032 } else {
1033 0.
1034 };
1035 let x = xyy[0] * reciprocal;
1036 let y = xyy[2];
1037 let z = (1. - xyy[0] - xyy[1]) * reciprocal;
1038 Xyz { x, y, z }
1039 }
1040}
1041
1042#[repr(C)]
1044#[derive(Clone, Debug, Copy, Default)]
1045pub struct Xyzd {
1046 pub x: f64,
1047 pub y: f64,
1048 pub z: f64,
1049}
1050
1051macro_rules! define_xyz {
1052 ($xyz_name:ident, $im_type: ident, $matrix: ident) => {
1053 impl PartialEq<Self> for $xyz_name {
1054 #[inline]
1055 fn eq(&self, other: &Self) -> bool {
1056 const TOLERANCE: $im_type = 0.0001;
1057 let dx = (self.x - other.x).abs();
1058 let dy = (self.y - other.y).abs();
1059 let dz = (self.z - other.z).abs();
1060 dx < TOLERANCE && dy < TOLERANCE && dz < TOLERANCE
1061 }
1062 }
1063
1064 impl $xyz_name {
1065 #[inline]
1066 pub const fn new(x: $im_type, y: $im_type, z: $im_type) -> Self {
1067 Self { x, y, z }
1068 }
1069
1070 #[inline]
1071 pub const fn to_vector(self) -> Vector3f {
1072 Vector3f {
1073 v: [self.x as f32, self.y as f32, self.z as f32],
1074 }
1075 }
1076
1077 #[inline]
1078 pub const fn to_vector_d(self) -> Vector3d {
1079 Vector3d {
1080 v: [self.x as f64, self.y as f64, self.z as f64],
1081 }
1082 }
1083
1084 #[inline]
1085 pub fn matrix_mul(&self, matrix: $matrix) -> Self {
1086 let x = mlaf(
1087 mlaf(self.x * matrix.v[0][0], self.y, matrix.v[0][1]),
1088 self.z,
1089 matrix.v[0][2],
1090 );
1091 let y = mlaf(
1092 mlaf(self.x * matrix.v[1][0], self.y, matrix.v[1][1]),
1093 self.z,
1094 matrix.v[1][2],
1095 );
1096 let z = mlaf(
1097 mlaf(self.x * matrix.v[2][0], self.y, matrix.v[2][1]),
1098 self.z,
1099 matrix.v[2][2],
1100 );
1101 Self::new(x, y, z)
1102 }
1103
1104 #[inline]
1105 pub fn from_linear_rgb(rgb: crate::Rgb<$im_type>, rgb_to_xyz: $matrix) -> Self {
1106 let r = rgb.r;
1107 let g = rgb.g;
1108 let b = rgb.b;
1109
1110 let transform = rgb_to_xyz;
1111
1112 let new_r = mlaf(
1113 mlaf(r * transform.v[0][0], g, transform.v[0][1]),
1114 b,
1115 transform.v[0][2],
1116 );
1117
1118 let new_g = mlaf(
1119 mlaf(r * transform.v[1][0], g, transform.v[1][1]),
1120 b,
1121 transform.v[1][2],
1122 );
1123
1124 let new_b = mlaf(
1125 mlaf(r * transform.v[2][0], g, transform.v[2][1]),
1126 b,
1127 transform.v[2][2],
1128 );
1129
1130 $xyz_name::new(new_r, new_g, new_b)
1131 }
1132
1133 #[inline]
1134 pub fn normalize(self) -> Self {
1135 if self.y == 0. {
1136 return Self {
1137 x: 0.,
1138 y: 1.0,
1139 z: 0.0,
1140 };
1141 }
1142 let reciprocal = 1. / self.y;
1143 Self {
1144 x: self.x * reciprocal,
1145 y: 1.0,
1146 z: self.z * reciprocal,
1147 }
1148 }
1149
1150 #[inline]
1151 pub fn to_linear_rgb(self, rgb_to_xyz: $matrix) -> crate::Rgb<$im_type> {
1152 let x = self.x;
1153 let y = self.y;
1154 let z = self.z;
1155
1156 let transform = rgb_to_xyz;
1157
1158 let new_r = mlaf(
1159 mlaf(x * transform.v[0][0], y, transform.v[0][1]),
1160 z,
1161 transform.v[0][2],
1162 );
1163
1164 let new_g = mlaf(
1165 mlaf(x * transform.v[1][0], y, transform.v[1][1]),
1166 z,
1167 transform.v[1][2],
1168 );
1169
1170 let new_b = mlaf(
1171 mlaf(x * transform.v[2][0], y, transform.v[2][1]),
1172 z,
1173 transform.v[2][2],
1174 );
1175
1176 crate::Rgb::<$im_type>::new(new_r, new_g, new_b)
1177 }
1178 }
1179
1180 impl Mul<$im_type> for $xyz_name {
1181 type Output = $xyz_name;
1182
1183 #[inline]
1184 fn mul(self, rhs: $im_type) -> Self::Output {
1185 Self {
1186 x: self.x * rhs,
1187 y: self.y * rhs,
1188 z: self.z * rhs,
1189 }
1190 }
1191 }
1192
1193 impl Mul<$matrix> for $xyz_name {
1194 type Output = $xyz_name;
1195
1196 #[inline]
1197 fn mul(self, rhs: $matrix) -> Self::Output {
1198 self.matrix_mul(rhs)
1199 }
1200 }
1201
1202 impl Mul<$xyz_name> for $xyz_name {
1203 type Output = $xyz_name;
1204
1205 #[inline]
1206 fn mul(self, rhs: $xyz_name) -> Self::Output {
1207 Self {
1208 x: self.x * rhs.x,
1209 y: self.y * rhs.y,
1210 z: self.z * rhs.z,
1211 }
1212 }
1213 }
1214
1215 impl Div<$xyz_name> for $xyz_name {
1216 type Output = $xyz_name;
1217
1218 #[inline]
1219 fn div(self, rhs: $xyz_name) -> Self::Output {
1220 Self {
1221 x: self.x / rhs.x,
1222 y: self.y / rhs.y,
1223 z: self.z / rhs.z,
1224 }
1225 }
1226 }
1227
1228 impl Div<$im_type> for $xyz_name {
1229 type Output = $xyz_name;
1230
1231 #[inline]
1232 fn div(self, rhs: $im_type) -> Self::Output {
1233 Self {
1234 x: self.x / rhs,
1235 y: self.y / rhs,
1236 z: self.z / rhs,
1237 }
1238 }
1239 }
1240 };
1241}
1242
1243impl Xyz {
1244 pub fn to_xyzd(self) -> Xyzd {
1245 Xyzd {
1246 x: self.x as f64,
1247 y: self.y as f64,
1248 z: self.z as f64,
1249 }
1250 }
1251}
1252
1253impl Xyzd {
1254 pub fn to_xyz(self) -> Xyz {
1255 Xyz {
1256 x: self.x as f32,
1257 y: self.y as f32,
1258 z: self.z as f32,
1259 }
1260 }
1261
1262 pub fn to_xyzd(self) -> Xyzd {
1263 Xyzd {
1264 x: self.x,
1265 y: self.y,
1266 z: self.z,
1267 }
1268 }
1269}
1270
1271define_xyz!(Xyz, f32, Matrix3f);
1272define_xyz!(Xyzd, f64, Matrix3d);