dasp_sample/
types.rs

1//! A collection of custom, non-std **Sample** types.
2
3pub use self::i11::I11;
4pub use self::i20::I20;
5pub use self::i24::I24;
6pub use self::i48::I48;
7pub use self::u11::U11;
8pub use self::u20::U20;
9pub use self::u24::U24;
10pub use self::u48::U48;
11
12macro_rules! impl_from {
13    ($T:ident: $Rep:ident from {$U:ident : $URep:ty}) => {
14        impl From<$U> for $T {
15            #[inline]
16            fn from(other: $U) -> Self {
17                $T(other.inner() as $Rep)
18            }
19        }
20    };
21    ($T:ident: $Rep:ident from $U:ident) => {
22        impl From<$U> for $T {
23            #[inline]
24            fn from(other: $U) -> Self {
25                $T(other as $Rep)
26            }
27        }
28    };
29}
30
31macro_rules! impl_froms {
32    ($T:ident: $Rep:ident, {$U:ident : $URep:ty}, $($rest:tt)*) => {
33        impl_from!($T: $Rep from {$U: $URep});
34        impl_froms!($T: $Rep, $($rest)*);
35    };
36    ($T:ident: $Rep:ident, {$U:ident : $URep:ty}) => {
37        impl_from!($T: $Rep from {$U: $URep});
38    };
39    ($T:ident: $Rep:ident, $U:ident, $($rest:tt)*) => {
40        impl_from!($T: $Rep from $U);
41        impl_froms!($T: $Rep, $($rest)*);
42    };
43    ($T:ident: $Rep:ident, $U:ident) => {
44        impl_from!($T: $Rep from $U);
45    };
46    ($T:ident: $Rep:ident,) => {};
47}
48
49macro_rules! impl_neg {
50    ($T:ident) => {
51        impl ::core::ops::Neg for $T {
52            type Output = $T;
53            #[inline]
54            fn neg(self) -> $T {
55                $T(-self.0)
56            }
57        }
58    };
59}
60
61macro_rules! new_sample_type {
62    ($T:ident: $Rep:ident, eq: $EQ:expr, min: $MIN:expr, max: $MAX:expr, total: $TOTAL:expr, from: $($rest:tt)*) => {
63        pub const MIN: $T = $T($MIN);
64        pub const MAX: $T = $T($MAX);
65        pub const EQUILIBRIUM: $T = $T($EQ);
66        const MIN_REP: $Rep = $MIN;
67        const MAX_REP: $Rep = $MAX;
68        const TOTAL: $Rep = $TOTAL;
69
70        #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
71        pub struct $T($Rep);
72
73        impl From<$Rep> for $T {
74            #[inline]
75            fn from(val: $Rep) -> Self {
76                $T(val).wrap_overflow()
77            }
78        }
79
80        impl $T {
81            /// Construct a new sample if the given value is within range.
82            ///
83            /// Returns `None` if `val` is out of range.
84            #[inline]
85            pub fn new(val: $Rep) -> Option<Self> {
86                if val > MAX_REP || val < MIN_REP {
87                    None
88                } else {
89                    Some($T(val))
90                }
91            }
92
93            /// Constructs a new sample without checking for overflowing.
94            ///
95            /// This should *only* be used if the user can guarantee the sample will be within
96            /// range and they require the extra performance.
97            ///
98            /// If this function is used, the sample crate can't guarantee that the returned sample
99            /// or any interacting samples will remain within their MIN and MAX bounds.
100            pub fn new_unchecked(s: $Rep) -> Self {
101                $T(s)
102            }
103
104            /// Return the internal value used to represent the sample type.
105            #[inline]
106            pub fn inner(self) -> $Rep {
107                self.0
108            }
109
110            /// Wraps self once in the case that self has overflowed.
111            #[inline]
112            fn wrap_overflow_once(self) -> Self {
113                if      self.0 > MAX_REP { $T(self.0 - TOTAL) }
114                else if self.0 < MIN_REP { $T(self.0 + TOTAL) }
115                else                     { self }
116            }
117
118            /// Wraps self in the case that self has overflowed.
119            #[inline]
120            fn wrap_overflow(mut self) -> Self {
121                while self.0 > MAX_REP {
122                    self.0 -= TOTAL;
123                }
124                while self.0 < MIN_REP {
125                    self.0 += TOTAL;
126                }
127                self
128            }
129        }
130
131        impl ::core::ops::Add<$T> for $T {
132            type Output = $T;
133            #[inline]
134            fn add(self, other: Self) -> Self {
135                if cfg!(debug_assertions) {
136                    $T::new(self.0 + other.0).expect("arithmetic operation overflowed")
137                } else {
138                    $T(self.0 + other.0).wrap_overflow_once()
139                }
140            }
141        }
142
143        impl ::core::ops::Sub<$T> for $T {
144            type Output = $T;
145            #[inline]
146            fn sub(self, other: Self) -> Self {
147                if cfg!(debug_assertions) {
148                    $T::new(self.0 - other.0).expect("arithmetic operation overflowed")
149                } else {
150                    $T(self.0 - other.0).wrap_overflow_once()
151                }
152            }
153        }
154
155        impl ::core::ops::Mul<$T> for $T {
156            type Output = $T;
157            #[inline]
158            fn mul(self, other: Self) -> Self {
159                if cfg!(debug_assertions) {
160                    $T::new(self.0 * other.0).expect("arithmetic operation overflowed")
161                } else {
162                    $T::from(self.0 * other.0)
163                }
164            }
165        }
166
167        impl ::core::ops::Div<$T> for $T {
168            type Output = $T;
169            #[inline]
170            fn div(self, other: Self) -> Self {
171                $T(self.0 / other.0)
172            }
173        }
174
175        impl ::core::ops::Not for $T {
176            type Output = $T;
177            #[inline]
178            fn not(self) -> $T {
179                $T(!self.0)
180            }
181        }
182
183        impl ::core::ops::Rem<$T> for $T {
184            type Output = $T;
185            #[inline]
186            fn rem(self, other: Self) -> Self {
187                $T(self.0 % other.0)
188            }
189        }
190
191        impl ::core::ops::Shl<$T> for $T {
192            type Output = $T;
193            #[inline]
194            fn shl(self, other: Self) -> Self {
195                // TODO: Needs review
196                $T(self.0 << other.0)
197            }
198        }
199
200        impl ::core::ops::Shr<$T> for $T {
201            type Output = $T;
202            #[inline]
203            fn shr(self, other: Self) -> Self {
204                // TODO: Needs review
205                $T(self.0 >> other.0)
206            }
207        }
208
209        impl ::core::ops::BitAnd<$T> for $T {
210            type Output = $T;
211            #[inline]
212            fn bitand(self, other: Self) -> Self {
213                $T(self.0 & other.0)
214            }
215        }
216
217        impl ::core::ops::BitOr<$T> for $T {
218            type Output = $T;
219            #[inline]
220            fn bitor(self, other: Self) -> Self {
221                $T(self.0 | other.0)
222            }
223        }
224
225        impl ::core::ops::BitXor<$T> for $T {
226            type Output = $T;
227            #[inline]
228            fn bitxor(self, other: Self) -> Self {
229                $T(self.0 ^ other.0)
230            }
231        }
232
233        impl_froms!($T: $Rep, $($rest)*);
234    };
235}
236
237pub mod i11 {
238    new_sample_type!(I11: i16, eq: 0, min: -1024, max: 1023, total: 2048,
239                     from: i8, u8);
240    impl_neg!(I11);
241}
242
243pub mod i20 {
244    use super::{I11, U11};
245    new_sample_type!(I20: i32, eq: 0, min: -524_288, max: 524_287, total: 1_048_576,
246                     from: i8, {I11:i16}, i16, u8, {U11:i16}, u16);
247}
248
249pub mod i24 {
250    use super::{I20, U20};
251    new_sample_type!(I24: i32, eq: 0, min: -8_388_608, max: 8_388_607, total: 16_777_216,
252                     from: i8, i16, {I20:i32}, u8, u16, {U20:i32});
253    impl_neg!(I24);
254}
255
256pub mod i48 {
257    use super::{I20, I24, U20, U24};
258    new_sample_type!(I48: i64, eq: 0, min: -140_737_488_355_328, max: 140_737_488_355_327, total: 281_474_976_710_656,
259                     from: i8, i16, {I20:i32}, {I24:i32}, i32, u8, u16, {U20:i32}, {U24:i32}, u32);
260    impl_neg!(I48);
261}
262
263pub mod u11 {
264    new_sample_type!(U11: i16, eq: 1024, min: 0, max: 2047, total: 2048,
265                     from: u8);
266    impl_neg!(U11);
267}
268
269pub mod u20 {
270    new_sample_type!(U20: i32, eq: 524_288, min: 0, max: 1_048_575, total: 1_048_576,
271                     from: u8, u16);
272}
273
274pub mod u24 {
275    use super::U20;
276    new_sample_type!(U24: i32, eq: 8_388_608, min: 0, max: 16_777_215, total: 16_777_216,
277                     from: u8, u16, {U20:i32});
278}
279
280pub mod u48 {
281    use super::{U20, U24};
282    new_sample_type!(U48: i64, eq: 140_737_488_355_328, min: 0, max: 281_474_976_710_655, total: 281_474_976_710_656,
283                     from: u8, u16, {U20:i32}, {U24:i32}, u32);
284}