Coverage Report

Created: 2026-05-16 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/moxcms-0.8.1/src/rgb.rs
Line
Count
Source
1
/*
2
 * // Copyright 2024 (c) the Radzivon Bartoshyk. All rights reserved.
3
 * //
4
 * // Use of this source code is governed by a BSD-style
5
 * // license that can be found in the LICENSE file.
6
 */
7
use crate::math::{FusedMultiplyAdd, m_clamp, m_max, m_min};
8
use crate::mlaf::mlaf;
9
use crate::{Matrix3f, Vector3, Xyz};
10
use num_traits::{AsPrimitive, Bounded, Float, Num, Pow, Signed};
11
use pxfm::{
12
    f_exp, f_exp2, f_exp2f, f_exp10, f_exp10f, f_expf, f_log, f_log2, f_log2f, f_log10, f_log10f,
13
    f_logf, f_pow, f_powf,
14
};
15
use std::cmp::Ordering;
16
use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub};
17
18
#[repr(C)]
19
#[derive(Debug, PartialOrd, PartialEq, Clone, Copy, Default)]
20
/// Represents any RGB values
21
pub struct Rgb<T> {
22
    /// Red component
23
    pub r: T,
24
    /// Green component
25
    pub g: T,
26
    /// Blue component
27
    pub b: T,
28
}
29
30
impl<T> Rgb<T> {
31
0
    pub fn new(r: T, g: T, b: T) -> Rgb<T> {
32
0
        Rgb { r, g, b }
33
0
    }
Unexecuted instantiation: <moxcms::rgb::Rgb<f64>>::new
Unexecuted instantiation: <moxcms::rgb::Rgb<f32>>::new
34
}
35
36
impl<T> Rgb<T>
37
where
38
    T: Copy,
39
{
40
0
    pub fn dup(v: T) -> Rgb<T> {
41
0
        Rgb { r: v, g: v, b: v }
42
0
    }
43
44
    #[inline]
45
0
    pub const fn to_vector(self) -> Vector3<T> {
46
0
        Vector3 {
47
0
            v: [self.r, self.g, self.b],
48
0
        }
49
0
    }
50
}
51
52
impl Rgb<f32> {
53
    #[inline(always)]
54
0
    pub fn apply(&self, matrix: Matrix3f) -> Rgb<f32> {
55
0
        let new_r = mlaf(
56
0
            mlaf(self.r * matrix.v[0][0], self.g, matrix.v[0][1]),
57
0
            self.b,
58
0
            matrix.v[0][2],
59
        );
60
61
0
        let new_g = mlaf(
62
0
            mlaf(self.r * matrix.v[1][0], self.g, matrix.v[1][1]),
63
0
            self.b,
64
0
            matrix.v[1][2],
65
        );
66
67
0
        let new_b = mlaf(
68
0
            mlaf(self.r * matrix.v[2][0], self.g, matrix.v[2][1]),
69
0
            self.b,
70
0
            matrix.v[2][2],
71
        );
72
73
0
        Rgb {
74
0
            r: new_r,
75
0
            g: new_g,
76
0
            b: new_b,
77
0
        }
78
0
    }
79
80
    #[inline(always)]
81
0
    pub fn to_xyz(&self, matrix: Matrix3f) -> Xyz {
82
0
        let new_self = self.apply(matrix);
83
0
        Xyz {
84
0
            x: new_self.r,
85
0
            y: new_self.g,
86
0
            z: new_self.b,
87
0
        }
88
0
    }
89
90
    #[inline(always)]
91
0
    pub fn is_out_of_gamut(&self) -> bool {
92
0
        !(0.0..=1.0).contains(&self.r)
93
0
            || !(0.0..=1.0).contains(&self.g)
94
0
            || !(0.0..=1.0).contains(&self.b)
95
0
    }
96
}
97
98
impl<T> Index<usize> for Rgb<T> {
99
    type Output = T;
100
101
0
    fn index(&self, index: usize) -> &T {
102
0
        match index {
103
0
            0 => &self.r,
104
0
            1 => &self.g,
105
0
            2 => &self.b,
106
0
            _ => panic!("Index out of bounds for Rgb"),
107
        }
108
0
    }
109
}
110
111
impl<T> IndexMut<usize> for Rgb<T> {
112
0
    fn index_mut(&mut self, index: usize) -> &mut T {
113
0
        match index {
114
0
            0 => &mut self.r,
115
0
            1 => &mut self.g,
116
0
            2 => &mut self.b,
117
0
            _ => panic!("Index out of bounds for RGB"),
118
        }
119
0
    }
120
}
121
122
macro_rules! generated_float_definition_rgb {
123
    ($T: ty) => {
124
        impl Rgb<$T> {
125
            #[inline]
126
0
            pub fn zeroed() -> Rgb<$T> {
127
0
                Rgb::<$T>::new(0., 0., 0.)
128
0
            }
Unexecuted instantiation: <moxcms::rgb::Rgb<f32>>::zeroed
Unexecuted instantiation: <moxcms::rgb::Rgb<f64>>::zeroed
129
130
            #[inline]
131
0
            pub fn ones() -> Rgb<$T> {
132
0
                Rgb::<$T>::new(1., 1., 1.)
133
0
            }
Unexecuted instantiation: <moxcms::rgb::Rgb<f32>>::ones
Unexecuted instantiation: <moxcms::rgb::Rgb<f64>>::ones
134
135
            #[inline]
136
0
            pub fn white() -> Rgb<$T> {
137
0
                Rgb::<$T>::ones()
138
0
            }
Unexecuted instantiation: <moxcms::rgb::Rgb<f32>>::white
Unexecuted instantiation: <moxcms::rgb::Rgb<f64>>::white
139
140
            #[inline]
141
0
            pub fn black() -> Rgb<$T> {
142
0
                Rgb::<$T>::zeroed()
143
0
            }
Unexecuted instantiation: <moxcms::rgb::Rgb<f32>>::black
Unexecuted instantiation: <moxcms::rgb::Rgb<f64>>::black
144
        }
145
    };
146
}
147
148
generated_float_definition_rgb!(f32);
149
generated_float_definition_rgb!(f64);
150
151
macro_rules! generated_integral_definition_rgb {
152
    ($T: ty) => {
153
        impl Rgb<$T> {
154
            #[inline]
155
0
            pub fn zeroed() -> Rgb<$T> {
156
0
                Rgb::<$T>::new(0, 0, 0)
157
0
            }
Unexecuted instantiation: <moxcms::rgb::Rgb<u8>>::zeroed
Unexecuted instantiation: <moxcms::rgb::Rgb<u16>>::zeroed
Unexecuted instantiation: <moxcms::rgb::Rgb<i8>>::zeroed
Unexecuted instantiation: <moxcms::rgb::Rgb<i16>>::zeroed
Unexecuted instantiation: <moxcms::rgb::Rgb<i32>>::zeroed
Unexecuted instantiation: <moxcms::rgb::Rgb<u32>>::zeroed
158
159
            #[inline]
160
0
            pub fn capped() -> Rgb<$T> {
161
0
                Rgb::<$T>::new(<$T>::MAX, <$T>::MAX, <$T>::MAX)
162
0
            }
Unexecuted instantiation: <moxcms::rgb::Rgb<u8>>::capped
Unexecuted instantiation: <moxcms::rgb::Rgb<u16>>::capped
Unexecuted instantiation: <moxcms::rgb::Rgb<i8>>::capped
Unexecuted instantiation: <moxcms::rgb::Rgb<i16>>::capped
Unexecuted instantiation: <moxcms::rgb::Rgb<i32>>::capped
Unexecuted instantiation: <moxcms::rgb::Rgb<u32>>::capped
163
164
            #[inline]
165
0
            pub fn white() -> Rgb<$T> {
166
0
                Rgb::<$T>::capped()
167
0
            }
Unexecuted instantiation: <moxcms::rgb::Rgb<u8>>::white
Unexecuted instantiation: <moxcms::rgb::Rgb<u16>>::white
Unexecuted instantiation: <moxcms::rgb::Rgb<i8>>::white
Unexecuted instantiation: <moxcms::rgb::Rgb<i16>>::white
Unexecuted instantiation: <moxcms::rgb::Rgb<i32>>::white
Unexecuted instantiation: <moxcms::rgb::Rgb<u32>>::white
168
169
            #[inline]
170
0
            pub fn black() -> Rgb<$T> {
171
0
                Rgb::<$T>::new(0, 0, 0)
172
0
            }
Unexecuted instantiation: <moxcms::rgb::Rgb<u8>>::black
Unexecuted instantiation: <moxcms::rgb::Rgb<u16>>::black
Unexecuted instantiation: <moxcms::rgb::Rgb<i8>>::black
Unexecuted instantiation: <moxcms::rgb::Rgb<i16>>::black
Unexecuted instantiation: <moxcms::rgb::Rgb<i32>>::black
Unexecuted instantiation: <moxcms::rgb::Rgb<u32>>::black
173
        }
174
    };
175
}
176
177
generated_integral_definition_rgb!(u8);
178
generated_integral_definition_rgb!(u16);
179
generated_integral_definition_rgb!(i8);
180
generated_integral_definition_rgb!(i16);
181
generated_integral_definition_rgb!(i32);
182
generated_integral_definition_rgb!(u32);
183
184
pub trait FusedPow<T> {
185
    fn f_pow(&self, power: T) -> Self;
186
}
187
188
pub trait FusedLog2<T> {
189
    fn f_log2(&self) -> Self;
190
}
191
192
pub trait FusedLog10<T> {
193
    fn f_log10(&self) -> Self;
194
}
195
196
pub trait FusedLog<T> {
197
    fn f_log(&self) -> Self;
198
}
199
200
pub trait FusedExp<T> {
201
    fn f_exp(&self) -> Self;
202
}
203
204
pub trait FusedExp2<T> {
205
    fn f_exp2(&self) -> Self;
206
}
207
208
pub trait FusedExp10<T> {
209
    fn f_exp10(&self) -> Self;
210
}
211
212
impl FusedPow<Rgb<f32>> for Rgb<f32> {
213
0
    fn f_pow(&self, power: Rgb<f32>) -> Rgb<f32> {
214
0
        Rgb::new(
215
0
            f_powf(self.r, power.r),
216
0
            f_powf(self.g, power.g),
217
0
            f_powf(self.b, power.b),
218
        )
219
0
    }
220
}
221
222
impl FusedPow<Rgb<f64>> for Rgb<f64> {
223
0
    fn f_pow(&self, power: Rgb<f64>) -> Rgb<f64> {
224
0
        Rgb::new(
225
0
            f_pow(self.r, power.r),
226
0
            f_pow(self.g, power.g),
227
0
            f_pow(self.b, power.b),
228
        )
229
0
    }
230
}
231
232
impl FusedLog2<Rgb<f32>> for Rgb<f32> {
233
    #[inline]
234
0
    fn f_log2(&self) -> Rgb<f32> {
235
0
        Rgb::new(f_log2f(self.r), f_log2f(self.g), f_log2f(self.b))
236
0
    }
237
}
238
239
impl FusedLog2<Rgb<f64>> for Rgb<f64> {
240
    #[inline]
241
0
    fn f_log2(&self) -> Rgb<f64> {
242
0
        Rgb::new(f_log2(self.r), f_log2(self.g), f_log2(self.b))
243
0
    }
244
}
245
246
impl FusedLog<Rgb<f32>> for Rgb<f32> {
247
    #[inline]
248
0
    fn f_log(&self) -> Rgb<f32> {
249
0
        Rgb::new(f_logf(self.r), f_logf(self.g), f_logf(self.b))
250
0
    }
251
}
252
253
impl FusedLog<Rgb<f64>> for Rgb<f64> {
254
    #[inline]
255
0
    fn f_log(&self) -> Rgb<f64> {
256
0
        Rgb::new(f_log(self.r), f_log(self.g), f_log(self.b))
257
0
    }
258
}
259
260
impl FusedLog10<Rgb<f32>> for Rgb<f32> {
261
    #[inline]
262
0
    fn f_log10(&self) -> Rgb<f32> {
263
0
        Rgb::new(f_log10f(self.r), f_log10f(self.g), f_log10f(self.b))
264
0
    }
265
}
266
267
impl FusedLog10<Rgb<f64>> for Rgb<f64> {
268
    #[inline]
269
0
    fn f_log10(&self) -> Rgb<f64> {
270
0
        Rgb::new(f_log10(self.r), f_log10(self.g), f_log10(self.b))
271
0
    }
272
}
273
274
impl FusedExp<Rgb<f32>> for Rgb<f32> {
275
    #[inline]
276
0
    fn f_exp(&self) -> Rgb<f32> {
277
0
        Rgb::new(f_expf(self.r), f_expf(self.g), f_expf(self.b))
278
0
    }
279
}
280
281
impl FusedExp<Rgb<f64>> for Rgb<f64> {
282
    #[inline]
283
0
    fn f_exp(&self) -> Rgb<f64> {
284
0
        Rgb::new(f_exp(self.r), f_exp(self.g), f_exp(self.b))
285
0
    }
286
}
287
288
impl FusedExp2<Rgb<f32>> for Rgb<f32> {
289
    #[inline]
290
0
    fn f_exp2(&self) -> Rgb<f32> {
291
0
        Rgb::new(f_exp2f(self.r), f_exp2f(self.g), f_exp2f(self.b))
292
0
    }
293
}
294
295
impl FusedExp2<Rgb<f64>> for Rgb<f64> {
296
    #[inline]
297
0
    fn f_exp2(&self) -> Rgb<f64> {
298
0
        Rgb::new(f_exp2(self.r), f_exp2(self.g), f_exp2(self.b))
299
0
    }
300
}
301
302
impl FusedExp10<Rgb<f32>> for Rgb<f32> {
303
    #[inline]
304
0
    fn f_exp10(&self) -> Rgb<f32> {
305
0
        Rgb::new(f_exp10f(self.r), f_exp10f(self.g), f_exp10f(self.b))
306
0
    }
307
}
308
309
impl FusedExp10<Rgb<f64>> for Rgb<f64> {
310
    #[inline]
311
0
    fn f_exp10(&self) -> Rgb<f64> {
312
0
        Rgb::new(f_exp10(self.r), f_exp10(self.g), f_exp10(self.b))
313
0
    }
314
}
315
316
impl<T> Rgb<T>
317
where
318
    T: Copy + AsPrimitive<f32>,
319
{
320
0
    pub fn euclidean_distance(&self, other: Rgb<T>) -> f32 {
321
0
        let dr = self.r.as_() - other.r.as_();
322
0
        let dg = self.g.as_() - other.g.as_();
323
0
        let db = self.b.as_() - other.b.as_();
324
0
        (dr * dr + dg * dg + db * db).sqrt()
325
0
    }
326
}
327
328
impl<T> Rgb<T>
329
where
330
    T: Copy + AsPrimitive<f32>,
331
{
332
0
    pub fn taxicab_distance(&self, other: Self) -> f32 {
333
0
        let dr = self.r.as_() - other.r.as_();
334
0
        let dg = self.g.as_() - other.g.as_();
335
0
        let db = self.b.as_() - other.b.as_();
336
0
        dr.abs() + dg.abs() + db.abs()
337
0
    }
338
}
339
340
impl<T> Add for Rgb<T>
341
where
342
    T: Add<Output = T>,
343
{
344
    type Output = Rgb<T>;
345
346
    #[inline]
347
0
    fn add(self, rhs: Self) -> Self::Output {
348
0
        Rgb::new(self.r + rhs.r, self.g + rhs.g, self.b + rhs.b)
349
0
    }
350
}
351
352
impl<T> Sub for Rgb<T>
353
where
354
    T: Sub<Output = T>,
355
{
356
    type Output = Rgb<T>;
357
358
    #[inline]
359
0
    fn sub(self, rhs: Self) -> Self::Output {
360
0
        Rgb::new(self.r - rhs.r, self.g - rhs.g, self.b - rhs.b)
361
0
    }
362
}
363
364
impl<T: Copy + Clone> Sub<T> for Rgb<T>
365
where
366
    T: Sub<Output = T>,
367
{
368
    type Output = Rgb<T>;
369
370
    #[inline]
371
0
    fn sub(self, rhs: T) -> Self::Output {
372
0
        Rgb::new(self.r - rhs, self.g - rhs, self.b - rhs)
373
0
    }
374
}
375
376
impl<T: Copy + Clone> Add<T> for Rgb<T>
377
where
378
    T: Add<Output = T>,
379
{
380
    type Output = Rgb<T>;
381
382
    #[inline]
383
0
    fn add(self, rhs: T) -> Self::Output {
384
0
        Rgb::new(self.r + rhs, self.g + rhs, self.b + rhs)
385
0
    }
386
}
387
388
impl<T: Copy + Clone> Rgb<T>
389
where
390
    T: Signed,
391
{
392
    #[inline]
393
0
    pub fn abs(self) -> Self {
394
0
        Rgb::new(self.r.abs(), self.g.abs(), self.b.abs())
395
0
    }
396
}
397
398
impl<T> Div for Rgb<T>
399
where
400
    T: Div<Output = T>,
401
{
402
    type Output = Rgb<T>;
403
404
    #[inline]
405
0
    fn div(self, rhs: Self) -> Self::Output {
406
0
        Rgb::new(self.r / rhs.r, self.g / rhs.g, self.b / rhs.b)
407
0
    }
408
}
409
410
impl<T: Clone + Copy> Div<T> for Rgb<T>
411
where
412
    T: Div<Output = T>,
413
{
414
    type Output = Rgb<T>;
415
416
    #[inline]
417
0
    fn div(self, rhs: T) -> Self::Output {
418
0
        Rgb::new(self.r / rhs, self.g / rhs, self.b / rhs)
419
0
    }
420
}
421
422
impl<T> Mul for Rgb<T>
423
where
424
    T: Mul<Output = T>,
425
{
426
    type Output = Rgb<T>;
427
428
    #[inline]
429
0
    fn mul(self, rhs: Self) -> Self::Output {
430
0
        Rgb::new(self.r * rhs.r, self.g * rhs.g, self.b * rhs.b)
431
0
    }
432
}
433
434
impl<T: Clone + Copy> Mul<T> for Rgb<T>
435
where
436
    T: Mul<Output = T>,
437
{
438
    type Output = Rgb<T>;
439
440
    #[inline]
441
0
    fn mul(self, rhs: T) -> Self::Output {
442
0
        Rgb::new(self.r * rhs, self.g * rhs, self.b * rhs)
443
0
    }
444
}
445
446
impl<T> MulAssign for Rgb<T>
447
where
448
    T: MulAssign<T>,
449
{
450
    #[inline]
451
0
    fn mul_assign(&mut self, rhs: Self) {
452
0
        self.r *= rhs.r;
453
0
        self.g *= rhs.g;
454
0
        self.b *= rhs.b;
455
0
    }
456
}
457
458
macro_rules! generated_mul_assign_definition_rgb {
459
    ($T: ty) => {
460
        impl<T> MulAssign<$T> for Rgb<T>
461
        where
462
            T: MulAssign<$T>,
463
        {
464
            #[inline]
465
0
            fn mul_assign(&mut self, rhs: $T) {
466
0
                self.r *= rhs;
467
0
                self.g *= rhs;
468
0
                self.b *= rhs;
469
0
            }
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<i8>>::mul_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<u8>>::mul_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<u16>>::mul_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<i16>>::mul_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<u32>>::mul_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<i32>>::mul_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<f32>>::mul_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<f64>>::mul_assign
470
        }
471
    };
472
}
473
474
generated_mul_assign_definition_rgb!(i8);
475
generated_mul_assign_definition_rgb!(u8);
476
generated_mul_assign_definition_rgb!(u16);
477
generated_mul_assign_definition_rgb!(i16);
478
generated_mul_assign_definition_rgb!(u32);
479
generated_mul_assign_definition_rgb!(i32);
480
generated_mul_assign_definition_rgb!(f32);
481
generated_mul_assign_definition_rgb!(f64);
482
483
impl<T> AddAssign for Rgb<T>
484
where
485
    T: AddAssign<T>,
486
{
487
    #[inline]
488
0
    fn add_assign(&mut self, rhs: Self) {
489
0
        self.r += rhs.r;
490
0
        self.g += rhs.g;
491
0
        self.b += rhs.b;
492
0
    }
493
}
494
495
macro_rules! generated_add_assign_definition_rgb {
496
    ($T: ty) => {
497
        impl<T: Copy> AddAssign<$T> for Rgb<T>
498
        where
499
            T: AddAssign<$T>,
500
        {
501
            #[inline]
502
0
            fn add_assign(&mut self, rhs: $T) {
503
0
                self.r += rhs;
504
0
                self.g += rhs;
505
0
                self.b += rhs;
506
0
            }
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<i8>>::add_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<u8>>::add_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<u16>>::add_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<i16>>::add_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<u32>>::add_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<i32>>::add_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<f32>>::add_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<f64>>::add_assign
507
        }
508
    };
509
}
510
511
generated_add_assign_definition_rgb!(i8);
512
generated_add_assign_definition_rgb!(u8);
513
generated_add_assign_definition_rgb!(u16);
514
generated_add_assign_definition_rgb!(i16);
515
generated_add_assign_definition_rgb!(u32);
516
generated_add_assign_definition_rgb!(i32);
517
generated_add_assign_definition_rgb!(f32);
518
generated_add_assign_definition_rgb!(f64);
519
520
impl<T> DivAssign for Rgb<T>
521
where
522
    T: DivAssign<T>,
523
{
524
    #[inline]
525
0
    fn div_assign(&mut self, rhs: Self) {
526
0
        self.r /= rhs.r;
527
0
        self.g /= rhs.g;
528
0
        self.b /= rhs.b;
529
0
    }
530
}
531
532
macro_rules! generated_div_assign_definition_rgb {
533
    ($T: ty) => {
534
        impl<T: Copy> DivAssign<$T> for Rgb<T>
535
        where
536
            T: DivAssign<$T>,
537
        {
538
            #[inline]
539
0
            fn div_assign(&mut self, rhs: $T) {
540
0
                self.r /= rhs;
541
0
                self.g /= rhs;
542
0
                self.b /= rhs;
543
0
            }
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<u8>>::div_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<i8>>::div_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<u16>>::div_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<i16>>::div_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<u32>>::div_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<i32>>::div_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<f32>>::div_assign
Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<f64>>::div_assign
544
        }
545
    };
546
}
547
548
generated_div_assign_definition_rgb!(u8);
549
generated_div_assign_definition_rgb!(i8);
550
generated_div_assign_definition_rgb!(u16);
551
generated_div_assign_definition_rgb!(i16);
552
generated_div_assign_definition_rgb!(u32);
553
generated_div_assign_definition_rgb!(i32);
554
generated_div_assign_definition_rgb!(f32);
555
generated_div_assign_definition_rgb!(f64);
556
557
impl<T> Neg for Rgb<T>
558
where
559
    T: Neg<Output = T>,
560
{
561
    type Output = Rgb<T>;
562
563
    #[inline]
564
0
    fn neg(self) -> Self::Output {
565
0
        Rgb::new(-self.r, -self.g, -self.b)
566
0
    }
567
}
568
569
impl<T> Rgb<T>
570
where
571
    T: FusedMultiplyAdd<T>,
572
{
573
0
    pub fn mla(&self, b: Rgb<T>, c: Rgb<T>) -> Rgb<T> {
574
0
        Rgb::new(
575
0
            self.r.mla(b.r, c.r),
576
0
            self.g.mla(b.g, c.g),
577
0
            self.b.mla(b.b, c.b),
578
        )
579
0
    }
580
}
581
582
impl<T> Rgb<T>
583
where
584
    T: Num + PartialOrd + Copy + Bounded,
585
{
586
    /// Clamp function to clamp each channel within a given range
587
    #[inline]
588
    #[allow(clippy::manual_clamp)]
589
0
    pub fn clamp(&self, min_value: T, max_value: T) -> Rgb<T> {
590
0
        Rgb::new(
591
0
            m_clamp(self.r, min_value, max_value),
592
0
            m_clamp(self.g, min_value, max_value),
593
0
            m_clamp(self.b, min_value, max_value),
594
        )
595
0
    }
596
597
    /// Min function to define min
598
    #[inline]
599
0
    pub fn min(&self, other_min: T) -> Rgb<T> {
600
0
        Rgb::new(
601
0
            m_min(self.r, other_min),
602
0
            m_min(self.g, other_min),
603
0
            m_min(self.b, other_min),
604
        )
605
0
    }
606
607
    /// Max function to define max
608
    #[inline]
609
0
    pub fn max(&self, other_max: T) -> Rgb<T> {
610
0
        Rgb::new(
611
0
            m_max(self.r, other_max),
612
0
            m_max(self.g, other_max),
613
0
            m_max(self.b, other_max),
614
        )
615
0
    }
616
617
    /// Clamp function to clamp each channel within a given range
618
    #[inline]
619
    #[allow(clippy::manual_clamp)]
620
0
    pub fn clamp_p(&self, min_value: Rgb<T>, max_value: Rgb<T>) -> Rgb<T> {
621
0
        Rgb::new(
622
0
            m_clamp(self.r, max_value.r, min_value.r),
623
0
            m_clamp(self.g, max_value.g, min_value.g),
624
0
            m_clamp(self.b, max_value.b, min_value.b),
625
        )
626
0
    }
627
628
    /// Min function to define min
629
    #[inline]
630
0
    pub fn min_p(&self, other_min: Rgb<T>) -> Rgb<T> {
631
0
        Rgb::new(
632
0
            m_min(self.r, other_min.r),
633
0
            m_min(self.g, other_min.g),
634
0
            m_min(self.b, other_min.b),
635
        )
636
0
    }
637
638
    /// Max function to define max
639
    #[inline]
640
0
    pub fn max_p(&self, other_max: Rgb<T>) -> Rgb<T> {
641
0
        Rgb::new(
642
0
            m_max(self.r, other_max.r),
643
0
            m_max(self.g, other_max.g),
644
0
            m_max(self.b, other_max.b),
645
        )
646
0
    }
647
}
648
649
impl<T> Rgb<T>
650
where
651
    T: Float + 'static,
652
    f32: AsPrimitive<T>,
653
{
654
    #[inline]
655
0
    pub fn sqrt(&self) -> Rgb<T> {
656
0
        let zeros = 0f32.as_();
657
0
        Rgb::new(
658
0
            if self.r.partial_cmp(&zeros).unwrap_or(Ordering::Less) == Ordering::Less {
659
0
                0f32.as_()
660
            } else {
661
0
                self.r.sqrt()
662
            },
663
0
            if self.g.partial_cmp(&zeros).unwrap_or(Ordering::Less) == Ordering::Less {
664
0
                0f32.as_()
665
            } else {
666
0
                self.g.sqrt()
667
            },
668
0
            if self.b.partial_cmp(&zeros).unwrap_or(Ordering::Less) == Ordering::Less {
669
0
                0f32.as_()
670
            } else {
671
0
                self.b.sqrt()
672
            },
673
        )
674
0
    }
675
676
    #[inline]
677
0
    pub fn cbrt(&self) -> Rgb<T> {
678
0
        Rgb::new(self.r.cbrt(), self.g.cbrt(), self.b.cbrt())
679
0
    }
680
}
681
682
impl<T> Pow<T> for Rgb<T>
683
where
684
    T: Float,
685
{
686
    type Output = Rgb<T>;
687
688
    #[inline]
689
0
    fn pow(self, rhs: T) -> Self::Output {
690
0
        Rgb::<T>::new(self.r.powf(rhs), self.g.powf(rhs), self.b.powf(rhs))
691
0
    }
692
}
693
694
impl<T> Pow<Rgb<T>> for Rgb<T>
695
where
696
    T: Float,
697
{
698
    type Output = Rgb<T>;
699
700
    #[inline]
701
0
    fn pow(self, rhs: Rgb<T>) -> Self::Output {
702
0
        Rgb::<T>::new(self.r.powf(rhs.r), self.g.powf(rhs.g), self.b.powf(rhs.b))
703
0
    }
704
}
705
706
impl<T> Rgb<T> {
707
0
    pub fn cast<V>(self) -> Rgb<V>
708
0
    where
709
0
        T: AsPrimitive<V>,
710
0
        V: Copy + 'static,
711
    {
712
0
        Rgb::new(self.r.as_(), self.g.as_(), self.b.as_())
713
0
    }
714
}
715
716
impl<T> Rgb<T>
717
where
718
    T: Float + 'static,
719
{
720
0
    pub fn round(self) -> Rgb<T> {
721
0
        Rgb::new(self.r.round(), self.g.round(), self.b.round())
722
0
    }
723
}