1#[cfg(not(test))]
15use crate::math::Libm;
16
17use crate::private::Sealed;
18use core::fmt::Debug;
19use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
20
21pub trait Channel:
23 Copy
24 + Clone
25 + Debug
26 + Default
27 + From<f32>
28 + PartialOrd
29 + Add<Output = Self>
30 + AddAssign
31 + Sub<Output = Self>
32 + SubAssign
33 + Mul<Output = Self>
34 + MulAssign
35 + Neg<Output = Self>
36 + From<Ch16>
37 + From<Ch24>
38 + From<Ch32>
39 + From<Ch64>
40 + Into<Ch16>
41 + Into<Ch24>
42 + Into<Ch32>
43 + Into<Ch64>
44 + Sealed
45 + Unpin
46 + Sized
47 + 'static
48{
49 const MIN: Self;
51
52 const MID: Self;
54
55 const MAX: Self;
57
58 fn to_f32(self) -> f32;
60
61 #[inline(always)]
63 fn lerp(self, rhs: Self, t: Self) -> Self {
64 self + t * (rhs - self)
65 }
66}
67
68#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
70#[repr(transparent)]
71pub struct Ch16(i16);
72
73impl Channel for Ch16 {
74 const MIN: Ch16 = Ch16(-32_768);
75 const MID: Ch16 = Ch16(0);
76 const MAX: Ch16 = Ch16(32_767);
77
78 #[inline(always)]
79 fn to_f32(self) -> f32 {
80 const MULTIPLIER: f32 = 1.0 / 32_767.5;
81 (f32::from(self.0) + 0.5) * MULTIPLIER
82 }
83}
84
85impl Ch16 {
86 #[inline(always)]
88 pub const fn new(value: i16) -> Self {
89 Self(value)
90 }
91}
92
93impl From<f32> for Ch16 {
94 #[inline(always)]
95 fn from(value: f32) -> Self {
96 Self::new((value.clamp(-1.0, 1.0) * 32_767.5).floor() as i16)
97 }
98}
99
100impl From<Ch24> for Ch16 {
101 #[inline(always)]
102 fn from(ch: Ch24) -> Self {
103 Self::new(ch.0)
104 }
105}
106
107impl From<Ch32> for Ch16 {
108 #[inline(always)]
109 fn from(ch: Ch32) -> Self {
110 Self::from(ch.0)
111 }
112}
113
114impl From<Ch64> for Ch16 {
115 #[inline(always)]
116 fn from(ch: Ch64) -> Self {
117 Self::from(ch.0 as f32)
118 }
119}
120
121impl From<Ch16> for i16 {
122 #[inline(always)]
123 fn from(ch: Ch16) -> i16 {
124 ch.0
125 }
126}
127
128impl<R: Into<Self>> Add<R> for Ch16 {
129 type Output = Self;
130
131 #[inline(always)]
132 fn add(self, rhs: R) -> Self {
133 Self::new(i16::from(self).saturating_add(i16::from(rhs.into())))
134 }
135}
136
137impl<R: Into<Self>> Sub<R> for Ch16 {
138 type Output = Self;
139
140 #[inline(always)]
141 fn sub(self, rhs: R) -> Self {
142 Self::new(i16::from(self).saturating_sub(i16::from(rhs.into())))
143 }
144}
145
146impl<R: Into<Self>> Mul<R> for Ch16 {
147 type Output = Self;
148
149 #[inline(always)]
150 fn mul(self, rhs: R) -> Self {
151 let l = i32::from(self.0);
152 let r = i32::from(rhs.into().0);
153 let v = (l * r) / 32_767;
154 Self::new(v.max(-32_768).min(32_767) as i16)
155 }
156}
157
158impl Neg for Ch16 {
159 type Output = Ch16;
160
161 #[inline(always)]
162 fn neg(self) -> Self {
163 Self::new((u16::MAX - i16::from(self) as u16) as i16)
164 }
165}
166
167#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
169#[repr(C, packed)]
170pub struct Ch24(i16, u8);
171
172impl Channel for Ch24 {
173 const MIN: Ch24 = Ch24::new(-8_388_608);
174 const MID: Ch24 = Ch24::new(0);
175 const MAX: Ch24 = Ch24::new(8_388_607);
176
177 #[inline(always)]
178 fn to_f32(self) -> f32 {
179 const MULTIPLIER: f32 = 1.0 / 8_388_607.5;
180 (i32::from(self) as f32 + 0.5) * MULTIPLIER
181 }
182}
183
184impl Ch24 {
185 #[inline(always)]
187 pub const fn new(value: i32) -> Self {
188 let value = if value < -8_388_608 {
189 -8_388_608
190 } else if value > 8_388_607 {
191 8_388_607
192 } else {
193 value
194 };
195 Self((value >> 8) as i16, value as u8)
196 }
197}
198
199impl From<f32> for Ch24 {
200 #[inline(always)]
201 fn from(value: f32) -> Self {
202 Self::new((value.clamp(-1.0, 1.0) * 8_388_607.5).floor() as i32)
203 }
204}
205
206impl From<Ch16> for Ch24 {
207 #[inline(always)]
208 fn from(ch: Ch16) -> Self {
209 Self(i16::from(ch), (i16::from(ch) >> 8) as u8 ^ 0b1000_0000)
210 }
211}
212
213impl From<Ch32> for Ch24 {
214 #[inline(always)]
215 fn from(ch: Ch32) -> Self {
216 Self::from(ch.0)
217 }
218}
219
220impl From<Ch64> for Ch24 {
221 #[inline(always)]
222 fn from(ch: Ch64) -> Self {
223 Self::from(ch.0 as f32)
224 }
225}
226
227impl From<Ch24> for i32 {
228 #[inline(always)]
229 fn from(ch: Ch24) -> i32 {
230 ((ch.0 as i32) << 8) | ch.1 as i32
231 }
232}
233
234impl<R: Into<Self>> Add<R> for Ch24 {
235 type Output = Self;
236
237 #[inline(always)]
238 fn add(self, rhs: R) -> Self {
239 Self::new(i32::from(self) + i32::from(rhs.into()))
240 }
241}
242
243impl<R: Into<Self>> Sub<R> for Ch24 {
244 type Output = Self;
245
246 #[inline(always)]
247 fn sub(self, rhs: R) -> Self {
248 Self::new(i32::from(self) - i32::from(rhs.into()))
249 }
250}
251
252impl<R: Into<Self>> Mul<R> for Ch24 {
253 type Output = Self;
254
255 #[inline(always)]
256 fn mul(self, rhs: R) -> Self {
257 let l: i64 = i32::from(self).into();
258 let r: i64 = i32::from(rhs.into()).into();
259 let v = (l * r) / 8_388_607;
260 Self::new(v.max(-8_388_608).min(8_388_607) as i32)
261 }
262}
263
264impl Neg for Ch24 {
265 type Output = Ch24;
266
267 #[inline(always)]
268 fn neg(self) -> Self {
269 Self::new((u32::MAX - i32::from(self) as u32) as i32)
270 }
271}
272
273#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
275#[repr(transparent)]
276pub struct Ch32(f32);
277
278impl Channel for Ch32 {
279 const MIN: Ch32 = Ch32(-1.0);
280 const MID: Ch32 = Ch32(0.0);
281 const MAX: Ch32 = Ch32(1.0);
282
283 #[inline(always)]
284 fn to_f32(self) -> f32 {
285 self.0
286 }
287}
288
289impl Ch32 {
290 #[inline(always)]
292 pub const fn new(value: f32) -> Self {
293 Self(value)
294 }
295}
296
297impl From<f32> for Ch32 {
298 #[inline(always)]
299 fn from(value: f32) -> Self {
300 Self::new(value)
301 }
302}
303
304impl From<Ch16> for Ch32 {
305 #[inline(always)]
306 fn from(ch: Ch16) -> Self {
307 Self::new(ch.to_f32())
308 }
309}
310
311impl From<Ch24> for Ch32 {
312 #[inline(always)]
313 fn from(ch: Ch24) -> Self {
314 Self::new(ch.to_f32())
315 }
316}
317
318impl From<Ch64> for Ch32 {
319 #[inline(always)]
320 fn from(ch: Ch64) -> Self {
321 Self::new(ch.to_f32())
322 }
323}
324
325impl From<Ch32> for f32 {
326 #[inline(always)]
327 fn from(ch: Ch32) -> f32 {
328 ch.0
329 }
330}
331
332impl<R: Into<Self>> Add<R> for Ch32 {
333 type Output = Self;
334
335 #[inline(always)]
336 fn add(self, rhs: R) -> Self {
337 Self::new(f32::from(self) + f32::from(rhs.into()))
338 }
339}
340
341impl<R: Into<Self>> Sub<R> for Ch32 {
342 type Output = Self;
343
344 #[inline(always)]
345 fn sub(self, rhs: R) -> Self {
346 Self::new(f32::from(self) - f32::from(rhs.into()))
347 }
348}
349
350impl<R: Into<Self>> Mul<R> for Ch32 {
351 type Output = Self;
352
353 #[inline(always)]
354 fn mul(self, rhs: R) -> Self {
355 Self::new(f32::from(self) * f32::from(rhs.into()))
356 }
357}
358
359impl Neg for Ch32 {
360 type Output = Ch32;
361
362 #[inline(always)]
363 fn neg(self) -> Self {
364 Self(-f32::from(self))
365 }
366}
367
368#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
370#[repr(transparent)]
371pub struct Ch64(f64);
372
373impl Channel for Ch64 {
374 const MIN: Ch64 = Ch64(-1.0);
375 const MID: Ch64 = Ch64(0.0);
376 const MAX: Ch64 = Ch64(1.0);
377
378 #[inline(always)]
379 fn to_f32(self) -> f32 {
380 self.0 as f32
381 }
382}
383
384impl Ch64 {
385 #[inline(always)]
387 pub const fn new(value: f64) -> Self {
388 Self(value)
389 }
390}
391
392impl From<f32> for Ch64 {
393 #[inline(always)]
394 fn from(value: f32) -> Self {
395 Self::new(value as f64)
396 }
397}
398
399impl From<Ch16> for Ch64 {
400 #[inline(always)]
401 fn from(ch: Ch16) -> Self {
402 Self::new(ch.to_f32() as f64)
403 }
404}
405
406impl From<Ch24> for Ch64 {
407 #[inline(always)]
408 fn from(ch: Ch24) -> Self {
409 Self::new(ch.to_f32() as f64)
410 }
411}
412
413impl From<Ch32> for Ch64 {
414 #[inline(always)]
415 fn from(ch: Ch32) -> Self {
416 Self::new(ch.0 as f64)
417 }
418}
419
420impl From<Ch64> for f64 {
421 #[inline(always)]
422 fn from(ch: Ch64) -> f64 {
423 ch.0
424 }
425}
426
427impl<R: Into<Self>> Add<R> for Ch64 {
428 type Output = Self;
429
430 #[inline(always)]
431 fn add(self, rhs: R) -> Self {
432 Self::new(self.0 + rhs.into().0)
433 }
434}
435
436impl<R: Into<Self>> Sub<R> for Ch64 {
437 type Output = Self;
438
439 #[inline(always)]
440 fn sub(self, rhs: R) -> Self {
441 Self::new(self.0 - rhs.into().0)
442 }
443}
444
445impl<R: Into<Self>> Mul<R> for Ch64 {
446 type Output = Self;
447
448 #[inline(always)]
449 fn mul(self, rhs: R) -> Self {
450 Self::new(self.0 * rhs.into().0)
451 }
452}
453
454impl Neg for Ch64 {
455 type Output = Ch64;
456
457 #[inline(always)]
458 fn neg(self) -> Self {
459 Self(-self.0)
460 }
461}
462
463impl AddAssign for Ch16 {
464 #[inline(always)]
465 fn add_assign(&mut self, rhs: Self) {
466 *self = *self + rhs;
467 }
468}
469
470impl AddAssign for Ch24 {
471 #[inline(always)]
472 fn add_assign(&mut self, rhs: Self) {
473 *self = *self + rhs;
474 }
475}
476
477impl AddAssign for Ch32 {
478 #[inline(always)]
479 fn add_assign(&mut self, rhs: Self) {
480 *self = *self + rhs;
481 }
482}
483
484impl AddAssign for Ch64 {
485 #[inline(always)]
486 fn add_assign(&mut self, rhs: Self) {
487 *self = *self + rhs;
488 }
489}
490
491impl SubAssign for Ch16 {
492 #[inline(always)]
493 fn sub_assign(&mut self, rhs: Self) {
494 *self = *self - rhs;
495 }
496}
497
498impl SubAssign for Ch24 {
499 #[inline(always)]
500 fn sub_assign(&mut self, rhs: Self) {
501 *self = *self - rhs;
502 }
503}
504
505impl SubAssign for Ch32 {
506 #[inline(always)]
507 fn sub_assign(&mut self, rhs: Self) {
508 *self = *self - rhs;
509 }
510}
511
512impl SubAssign for Ch64 {
513 #[inline(always)]
514 fn sub_assign(&mut self, rhs: Self) {
515 *self = *self - rhs;
516 }
517}
518
519impl MulAssign for Ch16 {
520 #[inline(always)]
521 fn mul_assign(&mut self, rhs: Self) {
522 *self = *self * rhs;
523 }
524}
525
526impl MulAssign for Ch24 {
527 #[inline(always)]
528 fn mul_assign(&mut self, rhs: Self) {
529 *self = *self * rhs;
530 }
531}
532
533impl MulAssign for Ch32 {
534 #[inline(always)]
535 fn mul_assign(&mut self, rhs: Self) {
536 *self = *self * rhs;
537 }
538}
539
540impl MulAssign for Ch64 {
541 #[inline(always)]
542 fn mul_assign(&mut self, rhs: Self) {
543 *self = *self * rhs;
544 }
545}
546
547#[cfg(test)]
548mod tests {
549 use super::*;
550
551 #[test]
552 fn ch16() {
553 assert_eq!(-1.0, Ch16::MIN.to_f32());
554 assert_eq!(0.000015259022, Ch16::MID.to_f32());
555 assert_eq!(1.0, Ch16::MAX.to_f32());
556
557 assert_eq!(Ch16::MIN, Ch16::from(Ch16::MIN.to_f32()));
558 assert_eq!(Ch16::MID, Ch16::from(Ch16::MID.to_f32()));
559 assert_eq!(Ch16::MAX, Ch16::from(Ch16::MAX.to_f32()));
560 }
561
562 #[test]
563 fn ch16_roundtrip() {
564 assert_eq!(-32768, i16::from(Ch16::MIN));
565 assert_eq!(0, i16::from(Ch16::MID));
566 assert_eq!(32767, i16::from(Ch16::MAX));
567
568 assert_eq!(Ch16::MIN, Ch16::new(i16::from(Ch16::MIN)));
569 assert_eq!(Ch16::MID, Ch16::new(i16::from(Ch16::MID)));
570 assert_eq!(Ch16::MAX, Ch16::new(i16::from(Ch16::MAX)));
571 }
572
573 #[test]
574 fn ch24() {
575 assert_eq!(-1.0, Ch24::MIN.to_f32());
576 assert_eq!(0.00000005960465, Ch24::MID.to_f32());
577 assert_eq!(1.0, Ch24::MAX.to_f32());
578
579 assert_eq!(Ch24::MIN, Ch24::from(Ch24::MIN.to_f32()));
580 assert_eq!(Ch24::MID, Ch24::from(Ch24::MID.to_f32()));
581 assert_eq!(Ch24::MAX, Ch24::from(Ch24::MAX.to_f32()));
582 }
583
584 #[test]
585 fn ch24_roundtrip() {
586 assert_eq!(-8388608, i32::from(Ch24::MIN));
587 assert_eq!(0, i32::from(Ch24::MID));
588 assert_eq!(8388607, i32::from(Ch24::MAX));
589
590 assert_eq!(Ch24::MIN, Ch24::new(i32::from(Ch24::MIN)));
591 assert_eq!(Ch24::MID, Ch24::new(i32::from(Ch24::MID)));
592 assert_eq!(Ch24::MAX, Ch24::new(i32::from(Ch24::MAX)));
593 }
594
595 #[test]
596 fn ch32() {
597 assert_eq!(-1.0, Ch32::MIN.to_f32());
598 assert_eq!(0.0, Ch32::MID.to_f32());
599 assert_eq!(1.0, Ch32::MAX.to_f32());
600
601 assert_eq!(Ch32::MIN, Ch32::from(Ch32::MIN.to_f32()));
602 assert_eq!(Ch32::MID, Ch32::from(Ch32::MID.to_f32()));
603 assert_eq!(Ch32::MAX, Ch32::from(Ch32::MAX.to_f32()));
604 }
605
606 #[test]
607 fn ch64() {
608 assert_eq!(-1.0, Ch64::MIN.to_f32());
609 assert_eq!(0.0, Ch64::MID.to_f32());
610 assert_eq!(1.0, Ch64::MAX.to_f32());
611
612 assert_eq!(Ch64::MIN, Ch64::from(Ch64::MIN.to_f32()));
613 assert_eq!(Ch64::MID, Ch64::from(Ch64::MID.to_f32()));
614 assert_eq!(Ch64::MAX, Ch64::from(Ch64::MAX.to_f32()));
615 }
616
617 #[test]
618 fn ch16_to_ch24() {
619 assert_eq!(Ch24::MIN, Ch24::from(Ch16::MIN));
620 assert_eq!(Ch24::new(128), Ch24::from(Ch16::MID));
621 assert_eq!(Ch24::MAX, Ch24::from(Ch16::MAX));
622 }
623
624 #[test]
625 fn ch24_to_ch16() {
626 assert_eq!(Ch16::MIN, Ch16::from(Ch24::MIN));
627 assert_eq!(Ch16::MID, Ch16::from(Ch24::MID));
628 assert_eq!(Ch16::MAX, Ch16::from(Ch24::MAX));
629 }
630
631 #[test]
632 fn ch16_arith() {
633 assert_eq!(Ch16::new(-1), Ch16::new(-32768) + Ch16::new(32767));
635 assert_eq!(Ch16::new(8192), Ch16::new(-8192) + Ch16::new(16384));
636 assert_eq!(Ch16::MAX, Ch16::MID + Ch16::MAX);
637 assert_eq!(Ch16::MIN, Ch16::new(-16384) + Ch16::new(-16384));
638 assert_eq!(Ch16::new(0), Ch16::new(-32768) - Ch16::new(-32768));
640 assert_eq!(Ch16::new(0), Ch16::new(32767) - Ch16::new(32767));
641 assert_eq!(Ch16::new(-32767), Ch16::new(0) - Ch16::new(32767));
642 assert_eq!(Ch16::new(0), Ch16::new(0) * Ch16::new(32767));
644 assert_eq!(Ch16::new(32767), Ch16::new(32767) * Ch16::new(32767));
645 assert_eq!(Ch16::new(-32768), Ch16::new(32767) * Ch16::new(-32768));
646 assert_eq!(Ch16::new(-32768), Ch16::new(-32768) * Ch16::new(32767));
647 assert_eq!(Ch16::new(32767), Ch16::new(-32768) * Ch16::new(-32768));
648 assert_eq!(Ch16::new(-16384), Ch16::new(32767) * Ch16::new(-16384));
649 assert_eq!(Ch16::MIN, -Ch16::MAX);
651 assert_eq!(Ch16::MAX, -Ch16::MIN);
652 assert_eq!(Ch16::new(-1), -Ch16::new(0));
653 assert_eq!(Ch16::new(0), -Ch16::new(-1));
654 }
655
656 #[test]
657 fn ch24_arith() {
658 assert_eq!(Ch24::new(-1), Ch24::new(-8388608) + Ch24::new(8388607));
660 assert_eq!(
661 Ch24::new(2097152),
662 Ch24::new(-2097152) + Ch24::new(4194304)
663 );
664 assert_eq!(Ch24::MAX, Ch24::MID + Ch24::MAX);
665 assert_eq!(Ch24::MIN, Ch24::new(-4194304) + Ch24::new(-4194304));
666 assert_eq!(Ch24::new(0), Ch24::new(-8388608) - Ch24::new(-8388608));
668 assert_eq!(Ch24::new(0), Ch24::new(8388607) - Ch24::new(8388607));
669 assert_eq!(Ch24::new(-8388607), Ch24::new(0) - Ch24::new(8388607));
670 assert_eq!(Ch24::new(0), Ch24::new(0) * Ch24::new(8388607));
672 assert_eq!(Ch24::new(8388607), Ch24::new(8388607) * Ch24::new(8388607));
673 assert_eq!(
674 Ch24::new(-8388608),
675 Ch24::new(8388607) * Ch24::new(-8388608)
676 );
677 assert_eq!(
678 Ch24::new(-8388608),
679 Ch24::new(-8388608) * Ch24::new(8388607)
680 );
681 assert_eq!(
682 Ch24::new(8388607),
683 Ch24::new(-8388608) * Ch24::new(-8388608)
684 );
685 assert_eq!(
686 Ch24::new(-4194304),
687 Ch24::new(8388607) * Ch24::new(-4194304)
688 );
689 assert_eq!(Ch24::MIN, -Ch24::MAX);
691 assert_eq!(Ch24::MAX, -Ch24::MIN);
692 assert_eq!(Ch24::new(-1), -Ch24::new(0));
693 assert_eq!(Ch24::new(0), -Ch24::new(-1));
694 }
695
696 #[test]
697 fn ch32_arith() {
698 assert_eq!(Ch32::new(0.0), Ch32::new(-1.0) + Ch32::new(1.0));
700 assert_eq!(Ch32::new(0.25), Ch32::new(-0.25) + Ch32::new(0.5));
701 assert_eq!(Ch32::new(1.0), Ch32::new(0.0) + Ch32::new(1.0));
702 assert_eq!(Ch32::new(-1.0), Ch32::new(-0.5) + Ch32::new(-0.5));
703 assert_eq!(Ch32::new(0.0), Ch32::new(-1.0) - Ch32::new(-1.0));
705 assert_eq!(Ch32::new(0.0), Ch32::new(1.0) - Ch32::new(1.0));
706 assert_eq!(Ch32::new(-1.0), Ch32::new(0.0) - Ch32::new(1.0));
707 assert_eq!(Ch32::new(0.0), Ch32::new(0.0) * Ch32::new(1.0));
709 assert_eq!(Ch32::new(1.0), Ch32::new(1.0) * Ch32::new(1.0));
710 assert_eq!(Ch32::new(-1.0), Ch32::new(1.0) * Ch32::new(-1.0));
711 assert_eq!(Ch32::new(1.0), Ch32::new(-1.0) * Ch32::new(-1.0));
712 assert_eq!(Ch32::new(-0.5), Ch32::new(1.0) * Ch32::new(-0.5));
713 assert_eq!(Ch32::MIN, -Ch32::MAX);
715 assert_eq!(Ch32::MAX, -Ch32::MIN);
716 assert_eq!(Ch32::new(0.0), -Ch32::new(0.0));
717 }
718
719 #[test]
720 fn ch64_arith() {
721 assert_eq!(Ch64::new(0.0), Ch64::new(-1.0) + Ch64::new(1.0));
723 assert_eq!(Ch64::new(0.25), Ch64::new(-0.25) + Ch64::new(0.5));
724 assert_eq!(Ch64::new(1.0), Ch64::new(0.0) + Ch64::new(1.0));
725 assert_eq!(Ch64::new(-1.0), Ch64::new(-0.5) + Ch64::new(-0.5));
726 assert_eq!(Ch64::new(0.0), Ch64::new(-1.0) - Ch64::new(-1.0));
728 assert_eq!(Ch64::new(0.0), Ch64::new(1.0) - Ch64::new(1.0));
729 assert_eq!(Ch64::new(-1.0), Ch64::new(0.0) - Ch64::new(1.0));
730 assert_eq!(Ch64::new(0.0), Ch64::new(0.0) * Ch64::new(1.0));
732 assert_eq!(Ch64::new(1.0), Ch64::new(1.0) * Ch64::new(1.0));
733 assert_eq!(Ch64::new(-1.0), Ch64::new(1.0) * Ch64::new(-1.0));
734 assert_eq!(Ch64::new(1.0), Ch64::new(-1.0) * Ch64::new(-1.0));
735 assert_eq!(Ch64::new(-0.5), Ch64::new(1.0) * Ch64::new(-0.5));
736 assert_eq!(Ch64::MIN, -Ch64::MAX);
738 assert_eq!(Ch64::MAX, -Ch64::MIN);
739 assert_eq!(Ch64::new(0.0), -Ch64::new(0.0));
740 }
741
742 #[test]
743 fn ch16_saturation() {
744 assert_eq!(Ch16::MAX, Ch16::new(24576) + Ch16::new(16384));
745 assert_eq!(Ch16::MIN, Ch16::new(-16384) + Ch16::new(-24576));
746 assert_eq!(Ch16::MIN, Ch16::new(-16384) - Ch16::new(24576));
747 }
748
749 #[test]
750 fn ch24_saturation() {
751 assert_eq!(Ch24::MAX, Ch24::new(6291456) + Ch24::new(4194304));
752 assert_eq!(Ch24::MIN, Ch24::new(-4194304) + Ch24::new(-6291456));
753 assert_eq!(Ch24::MIN, Ch24::new(-4194304) - Ch24::new(6291456));
754 }
755
756 #[test]
757 fn ch32_unsaturation() {
758 assert_eq!(Ch32::new(1.25), Ch32::new(0.75) + Ch32::new(0.5));
759 assert_eq!(Ch32::new(-1.25), Ch32::new(-0.5) + Ch32::new(-0.75));
760 assert_eq!(Ch32::new(-1.25), Ch32::new(-0.5) - Ch32::new(0.75));
761 }
762
763 #[test]
764 fn ch64_unsaturation() {
765 assert_eq!(Ch64::new(1.25), Ch64::new(0.75) + Ch64::new(0.5));
766 assert_eq!(Ch64::new(-1.25), Ch64::new(-0.5) + Ch64::new(-0.75));
767 assert_eq!(Ch64::new(-1.25), Ch64::new(-0.5) - Ch64::new(0.75));
768 }
769}