1#[macro_export]
10macro_rules! channel {
11 (($ty: ident, $inner: ty), $attr: meta $(,)?) => {
12 #[$attr]
13 #[derive(
14 Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default,
15 )]
16 #[repr(transparent)]
17 pub struct $ty($inner);
18
19 impl $ty {
20 fn __() {
21 struct Impl<T>(core::marker::PhantomData<fn() -> T>)
22 where
23 T: $crate::bytemuck::Pod + $crate::bytemuck::Zeroable;
24
25 const INNER: Impl<$inner> = Impl(core::marker::PhantomData);
26 }
27 }
28
29 impl From<$inner> for $ty {
30 fn from(value: $inner) -> Self {
31 Self(value)
32 }
33 }
34
35 impl From<$ty> for $inner {
36 fn from(chan: $ty) -> Self {
37 chan.0
38 }
39 }
40
41 #[allow(unsafe_code)]
42 unsafe impl $crate::bytemuck::Zeroable for $ty {}
43
44 #[allow(unsafe_code)]
45 unsafe impl $crate::bytemuck::Pod for $ty {}
46 };
47}
48
49#[macro_export]
63macro_rules! group {
64 (($ty: ident), $attr: meta $(,)?) => {
65 #[$attr]
66 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
67 #[repr(transparent)]
68 pub struct $ty<Chan, const CH: usize>([Chan; CH]);
69
70 impl<Chan, const CH: usize> Default for $ty<Chan, CH>
71 where
72 Chan: Default + Copy,
73 {
74 fn default() -> Self {
75 Self([Chan::default(); CH])
76 }
77 }
78
79 #[allow(unsafe_code)]
80 unsafe impl<Chan, const CH: usize> $crate::bytemuck::Zeroable
81 for $ty<Chan, CH>
82 where
83 Chan: $crate::bytemuck::Zeroable,
84 {
85 }
86
87 #[allow(unsafe_code)]
88 unsafe impl<Chan, const CH: usize> $crate::bytemuck::Pod
89 for $ty<Chan, CH>
90 where
91 Chan: $crate::bytemuck::Pod,
92 {
93 }
94 };
95}
96
97macro_rules! ch_int {
98 (
99 ($ty: ident, $p: ty, $b: ty, $normalize: path, $midpoint: item),
100 $docs: meta $(,)?
101 ) => {
102 #[$docs]
103 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
104 #[repr(transparent)]
105 pub struct $ty($p);
106
107 impl core::fmt::Debug for $ty {
108 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
109 {
110 core::fmt::Debug::fmt(&self.0, f)
111 }
112 }
113
114 impl core::fmt::Display for $ty {
115 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
116 {
117 core::fmt::Display::fmt(&self.0, f)
118 }
119 }
120
121 impl From<$p> for $ty {
122 fn from(value: $p) -> Self {
123 Self::new(value)
124 }
125 }
126
127 impl From<$ty> for $p {
128 fn from(chan: $ty) -> Self {
129 chan.0
130 }
131 }
132
133 impl $ty {
134 pub const MAX: Self = Self::new($normalize(<$p>::MAX));
136 pub const MID: Self = Self::MAX.midpoint(Self::MIN);
138 pub const MIN: Self = Self::new($normalize(<$p>::MIN));
140
141 pub const fn new(value: $p) -> Self {
143 Self($normalize(value))
144 }
145
146 pub const fn into_inner(self) -> $p {
148 self.0
149 }
150
151 $midpoint
152
153 pub const fn clamp(self, min: Self, max: Self) -> Self {
160 let (mut this, min, max) = (self.0, min.0, max.0);
161
162 assert!(min <= max, "min > max");
163
164 if this < min {
165 this = min;
166 }
167
168 if this > max {
169 this = max;
170 }
171
172 Self(this)
173 }
174
175 pub(crate) const fn int_multiply(&mut self, rhs: Self) {
176 let this = self.into_inner() as $b;
177 let rhs = rhs.into_inner() as $b;
178 let min = Self::MIN.into_inner() as $b;
179 let max = Self::MAX.into_inner() as $b;
180 let mut res = (this * rhs) / max;
181
182 if res < min {
183 res = min;
184 }
185
186 if res > max {
187 res = max;
188 }
189
190 *self = Self(res as $p);
191 }
192 }
193
194 impl core::ops::Add for $ty {
195 type Output = Self;
196
197 #[inline(always)]
198 fn add(self, rhs: Self) -> Self {
199 crate::ops::Sum([self, rhs]).add()
200 }
201 }
202
203 impl core::ops::AddAssign for $ty {
204 #[inline(always)]
205 fn add_assign(&mut self, rhs: Self) {
206 *self = *self + rhs;
207 }
208 }
209
210 impl core::ops::Sub for $ty {
211 type Output = Self;
212
213 #[inline(always)]
214 fn sub(self, rhs: Self) -> Self {
215 crate::ops::Difference(self, [rhs]).sub()
216 }
217 }
218
219 impl core::ops::SubAssign for $ty {
220 #[inline(always)]
221 fn sub_assign(&mut self, rhs: Self) {
222 *self = *self - rhs;
223 }
224 }
225
226 impl core::ops::Neg for $ty {
227 type Output = Self;
228
229 #[inline(always)]
230 fn neg(self) -> Self {
231 crate::ops::Negation(self).neg()
232 }
233 }
234
235 impl core::ops::Not for $ty {
236 type Output = Self;
237
238 #[inline(always)]
239 fn not(self) -> Self {
240 crate::ops::Inversion(self).inv()
241 }
242 }
243
244 impl core::ops::Mul for $ty {
245 type Output = Self;
246
247 #[inline(always)]
248 fn mul(mut self, rhs: Self) -> Self {
249 self.int_multiply(rhs);
250 self
251 }
252 }
253
254 impl core::ops::MulAssign for $ty {
255 #[inline(always)]
256 fn mul_assign(&mut self, rhs: Self) {
257 *self = *self * rhs;
258 }
259 }
260
261 #[allow(unsafe_code)]
262 unsafe impl bytemuck::Zeroable for $ty {}
263
264 #[allow(unsafe_code)]
265 unsafe impl bytemuck::Pod for $ty {}
266 };
267}
268
269macro_rules! ch_float {
270 (
271 ($ty: ident, $p: ty, $normalize: path, $min: literal, $mid: literal),
272 $docs: meta $(,)?
273 ) => {
274 #[$docs]
275 #[derive(Copy, Clone, Default)]
276 #[repr(transparent)]
277 pub struct $ty($p);
278
279 impl core::hash::Hash for $ty {
280 fn hash<H>(&self, state: &mut H)
281 where
282 H: core::hash::Hasher,
283 {
284 self.0.to_bits().hash(state)
285 }
286 }
287
288 impl core::cmp::PartialEq for $ty {
289 fn eq(&self, other: &Self) -> bool {
290 $normalize(self.into_inner()) == $normalize(other.into_inner())
291 }
292 }
293
294 impl core::cmp::Ord for $ty {
295 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
296 $normalize(self.into_inner())
297 .partial_cmp(&$normalize(other.into_inner()))
298 .unwrap()
299 }
300 }
301
302 impl core::cmp::Eq for $ty {}
303
304 impl core::cmp::PartialOrd for $ty {
305 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
306 Some(self.cmp(other))
307 }
308 }
309
310 impl core::fmt::Debug for $ty {
311 fn fmt(
312 &self,
313 f: &mut core::fmt::Formatter<'_>,
314 ) -> core::fmt::Result {
315 self.0.fmt(f)
316 }
317 }
318
319 impl core::fmt::Display for $ty {
320 fn fmt(
321 &self,
322 f: &mut core::fmt::Formatter<'_>,
323 ) -> core::fmt::Result {
324 self.0.fmt(f)
325 }
326 }
327
328 impl From<$p> for $ty {
329 fn from(value: $p) -> Self {
330 Self::new(value)
331 }
332 }
333
334 impl From<$ty> for $p {
335 fn from(chan: $ty) -> Self {
336 chan.0
337 }
338 }
339
340 impl $ty {
341 pub const MAX: Self = Self::new(1.0);
343 pub const MID: Self = Self::new($mid);
345 pub const MIN: Self = Self::new($min);
347
348 pub const fn new(value: $p) -> Self {
350 Self($normalize(value))
351 }
352
353 pub const fn into_inner(self) -> $p {
355 self.0
356 }
357
358 pub const fn midpoint(self, rhs: Self) -> Self {
362 Self($normalize((self.0 + rhs.0) / 2.0))
365 }
366
367 pub const fn clamp(self, min: Self, max: Self) -> Self {
374 Self(self.0.clamp(min.0, max.0))
375 }
376 }
377
378 impl core::ops::Add for $ty {
379 type Output = Self;
380
381 #[inline(always)]
382 fn add(self, rhs: Self) -> Self {
383 crate::ops::Sum([self, rhs]).add()
384 }
385 }
386
387 impl core::ops::AddAssign for $ty {
388 #[inline(always)]
389 fn add_assign(&mut self, rhs: Self) {
390 *self = *self + rhs;
391 }
392 }
393
394 impl core::ops::Sub for $ty {
395 type Output = Self;
396
397 #[inline(always)]
398 fn sub(self, rhs: Self) -> Self {
399 crate::ops::Difference(self, [rhs]).sub()
400 }
401 }
402
403 impl core::ops::SubAssign for $ty {
404 #[inline(always)]
405 fn sub_assign(&mut self, rhs: Self) {
406 *self = *self - rhs;
407 }
408 }
409
410 impl core::ops::Neg for $ty {
411 type Output = Self;
412
413 #[inline(always)]
414 fn neg(self) -> Self {
415 crate::ops::Negation(self).neg()
416 }
417 }
418
419 impl core::ops::Not for $ty {
420 type Output = Self;
421
422 #[inline(always)]
423 fn not(self) -> Self {
424 crate::ops::Inversion(self).inv()
425 }
426 }
427
428 impl core::ops::Mul for $ty {
429 type Output = Self;
430
431 #[inline(always)]
432 fn mul(self, rhs: Self) -> Self {
433 crate::ops::Product([self, rhs]).mul()
434 }
435 }
436
437 impl core::ops::MulAssign for $ty {
438 #[inline(always)]
439 fn mul_assign(&mut self, rhs: Self) {
440 *self = *self * rhs;
441 }
442 }
443
444 #[allow(unsafe_code)]
445 unsafe impl bytemuck::Zeroable for $ty {}
446
447 #[allow(unsafe_code)]
448 unsafe impl bytemuck::Pod for $ty {}
449 };
450}
451
452macro_rules! conversion {
453 ($from:ty, $into:ty) => {
454 impl From<$from> for $into {
455 fn from(value: $from) -> $into {
456 Conversion::<$from, $into>::conv(value)
457 }
458 }
459 };
460}