Coverage Report

Created: 2025-10-10 07:21

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