Skip to main content

hpt_types/scalars/
impls.rs

1use crate::type_promote::FloatOutUnary2;
2use crate::type_promote::{BitWiseOut2, Eval2, FloatOutBinary2, NormalOut2, NormalOutUnary2};
3use num_complex::ComplexFloat;
4macro_rules! impl_int_traits {
5    ($type:ty, [$($abs:tt)*], [$($neg:tt)*], [$($signum:tt)*]) => {
6        impl FloatOutBinary2 for $type {
7            #[inline(always)]
8            fn __div(self, rhs: Self) -> Self {
9                if rhs == 0 {
10                    panic!("Division by zero for {}", stringify!($typ>));
11                } else {
12                    self / rhs
13                }
14            }
15            #[inline(always)]
16            fn __log(self, _: Self) -> Self {
17                panic!("Logarithm operation is not supported for {}", stringify!($type));
18            }
19            #[inline(always)]
20            fn __hypot(self, _: Self) -> Self {
21                panic!("Hypot operation is not supported for {}", stringify!($type));
22            }
23            #[inline(always)]
24            fn __pow(self, rhs: Self) -> Self {
25                self.pow(rhs as u32)
26            }
27        }
28
29        impl NormalOut2 for $type {
30            #[inline(always)]
31            fn __add(self, rhs: Self) -> Self {
32                self.wrapping_add(rhs)
33            }
34
35            #[inline(always)]
36            fn __sub(self, rhs: Self) -> Self {
37                self.wrapping_sub(rhs)
38            }
39
40            #[inline(always)]
41            fn __mul_add(self, a: Self, b: Self) -> Self {
42                (self * a) + b
43            }
44
45            #[inline(always)]
46            fn __mul(self, rhs: Self) -> Self {
47                self.wrapping_mul(rhs)
48            }
49
50            #[inline(always)]
51            fn __rem(self, rhs: Self) -> Self {
52                self.wrapping_rem(rhs)
53            }
54
55            #[inline(always)]
56            fn __max(self, rhs: Self) -> Self {
57                self.max(rhs)
58            }
59
60            #[inline(always)]
61            fn __min(self, rhs: Self) -> Self {
62                self.min(rhs)
63            }
64
65            #[inline(always)]
66            fn __clamp(self, min: Self, max: Self) -> Self {
67                self.clamp(min, max)
68            }
69        }
70
71        impl NormalOutUnary2 for $type {
72            #[inline(always)]
73            fn __square(self) -> Self {
74                self.wrapping_mul(self)
75            }
76
77            #[inline(always)]
78            fn __abs(self) -> Self {
79                self$($abs)*
80            }
81
82            #[inline(always)]
83            fn __ceil(self) -> Self {
84                self
85            }
86
87            #[inline(always)]
88            fn __floor(self) -> Self {
89                self
90            }
91
92            #[inline(always)]
93            fn __neg(self) -> Self {
94                $($neg)*self
95            }
96
97            #[inline(always)]
98            fn __round(self) -> Self {
99                self
100            }
101
102            #[inline(always)]
103            fn __signum(self) -> Self {
104                self$($signum)*
105            }
106
107            #[inline(always)]
108            fn __trunc(self) -> Self {
109                self
110            }
111
112            #[inline(always)]
113            fn __leaky_relu(self, alpha: Self) -> Self {
114                self.max(0) + alpha * self.min(0)
115            }
116
117            #[inline(always)]
118            fn __relu(self) -> Self {
119                self.max(0)
120            }
121
122            #[inline(always)]
123            fn __relu6(self) -> Self {
124                self.min(6).max(0)
125            }
126
127            #[inline(always)]
128            fn __copysign(self, _: Self) -> Self {
129                panic!("copysign is not supported for integer types")
130            }
131        }
132
133        impl BitWiseOut2 for $type {
134            #[inline(always)]
135            fn __bitand(self, rhs: Self) -> Self {
136                self & rhs
137            }
138
139            #[inline(always)]
140            fn __bitor(self, rhs: Self) -> Self {
141                self | rhs
142            }
143
144            #[inline(always)]
145            fn __bitxor(self, rhs: Self) -> Self {
146                self ^ rhs
147            }
148
149            #[inline(always)]
150            fn __not(self) -> Self {
151                !self
152            }
153
154            #[inline(always)]
155            fn __shl(self, rhs: Self) -> Self {
156                self.wrapping_shl(rhs as u32)
157            }
158
159            #[inline(always)]
160            fn __shr(self, rhs: Self) -> Self {
161                self.wrapping_shr(rhs as u32)
162            }
163        }
164
165        impl Eval2 for $type {
166            type Output = bool;
167            #[inline(always)]
168            fn __is_nan(&self) -> Self::Output {
169                false
170            }
171
172            #[inline(always)]
173            fn __is_true(&self) -> Self::Output {
174                *self != 0
175            }
176
177            #[inline(always)]
178            fn __is_inf(&self) -> Self::Output {
179                false
180            }
181        }
182    };
183}
184
185impl_int_traits!(i8, [.abs()], [-], [.signum()]);
186impl_int_traits!(i16, [.abs()], [-], [.signum()]);
187impl_int_traits!(i32, [.abs()], [-], [.signum()]);
188impl_int_traits!(i64, [.abs()], [-], [.signum()]);
189impl_int_traits!(i128, [.abs()], [-], [.signum()]);
190impl_int_traits!(isize, [.abs()], [-], [.signum()]);
191impl_int_traits!(u8, [], [], []);
192impl_int_traits!(u16, [], [], []);
193impl_int_traits!(u32, [], [], []);
194impl_int_traits!(u64, [], [], []);
195impl_int_traits!(u128, [], [], []);
196impl_int_traits!(usize, [], [], []);
197
198use num_complex::Complex;
199macro_rules! impl_complex {
200    ($type:ident) => {
201        impl FloatOutBinary2 for Complex<$type> {
202            #[inline(always)]
203            fn __div(self, rhs: Self) -> Self {
204                self / rhs
205            }
206            #[inline(always)]
207            fn __log(self, base: Self) -> Self {
208                self.log(base.re)
209            }
210            #[inline(always)]
211            fn __hypot(self, _: Self) -> Self {
212                panic!("Hypot operation is not supported for complex numbers");
213            }
214            #[inline(always)]
215            fn __pow(self, rhs: Self) -> Self {
216                self.powf(rhs.re)
217            }
218        }
219
220        impl NormalOut2 for Complex<$type> {
221            #[inline(always)]
222            fn __add(self, rhs: Self) -> Self {
223                self + rhs
224            }
225
226            #[inline(always)]
227            fn __sub(self, rhs: Self) -> Self {
228                self - rhs
229            }
230
231            #[inline(always)]
232            fn __mul_add(self, a: Self, b: Self) -> Self {
233                (self * a) + b
234            }
235
236            #[inline(always)]
237            fn __mul(self, rhs: Self) -> Self {
238                self * rhs
239            }
240
241            #[inline(always)]
242            fn __rem(self, rhs: Self) -> Self {
243                self % rhs
244            }
245
246            #[inline(always)]
247            fn __max(self, rhs: Self) -> Self {
248                if self.norm() >= rhs.norm() {
249                    self
250                } else {
251                    rhs
252                }
253            }
254
255            #[inline(always)]
256            fn __min(self, rhs: Self) -> Self {
257                if self.norm() <= rhs.norm() {
258                    self
259                } else {
260                    rhs
261                }
262            }
263
264            #[inline(always)]
265            fn __clamp(self, min: Self, max: Self) -> Self {
266                let norm = self.norm();
267                if norm < min.norm() {
268                    self * (min.norm() / norm)
269                } else if norm > max.norm() {
270                    self * (max.norm() / norm)
271                } else {
272                    self
273                }
274            }
275        }
276
277        impl NormalOutUnary2 for Complex<$type> {
278            #[inline(always)]
279            fn __square(self) -> Self {
280                self * self
281            }
282
283            #[inline(always)]
284            fn __abs(self) -> Self {
285                self.abs().into()
286            }
287
288            #[inline(always)]
289            fn __ceil(self) -> Self {
290                Complex::<$type>::new(self.re.ceil(), self.im.ceil())
291            }
292
293            #[inline(always)]
294            fn __floor(self) -> Self {
295                Complex::<$type>::new(self.re.floor(), self.im.floor())
296            }
297
298            #[inline(always)]
299            fn __neg(self) -> Self {
300                -self
301            }
302
303            #[inline(always)]
304            fn __round(self) -> Self {
305                Complex::<$type>::new(self.re.round(), self.im.round())
306            }
307
308            #[inline(always)]
309            fn __signum(self) -> Self {
310                if self == Complex::<$type>::new(0.0, 0.0) {
311                    self
312                } else {
313                    self / Complex::<$type>::from(self.norm())
314                }
315            }
316
317            #[inline(always)]
318            fn __trunc(self) -> Self {
319                Complex::<$type>::new(self.re.trunc(), self.im.trunc())
320            }
321
322            #[inline(always)]
323            fn __leaky_relu(self, alpha: Self) -> Self {
324                let norm = self.norm();
325                if norm > 0.0 {
326                    self
327                } else {
328                    self * alpha
329                }
330            }
331
332            #[inline(always)]
333            fn __relu(self) -> Self {
334                let norm = self.norm();
335                if norm > 0.0 {
336                    self
337                } else {
338                    Complex::<$type>::new(0.0, 0.0)
339                }
340            }
341
342            #[inline(always)]
343            fn __relu6(self) -> Self {
344                let norm = self.norm();
345                if norm > 6.0 {
346                    self * (6.0 / norm)
347                } else if norm > 0.0 {
348                    self
349                } else {
350                    Complex::<$type>::new(0.0, 0.0)
351                }
352            }
353
354            #[inline(always)]
355            fn __copysign(self, _: Self) -> Self {
356                panic!("copysign is not supported for complex numbers")
357            }
358        }
359
360        impl BitWiseOut2 for Complex<$type> {
361            #[inline(always)]
362            fn __bitand(self, rhs: Self) -> Self {
363                Complex::<$type>::new(
364                    $type::from_bits(self.re.to_bits() & rhs.re.to_bits()),
365                    $type::from_bits(self.im.to_bits() & rhs.im.to_bits()),
366                )
367            }
368
369            #[inline(always)]
370            fn __bitor(self, rhs: Self) -> Self {
371                Complex::<$type>::new(
372                    $type::from_bits(self.re.to_bits() | rhs.re.to_bits()),
373                    $type::from_bits(self.im.to_bits() | rhs.im.to_bits()),
374                )
375            }
376
377            #[inline(always)]
378            fn __bitxor(self, rhs: Self) -> Self {
379                Complex::<$type>::new(
380                    $type::from_bits(self.re.to_bits() ^ rhs.re.to_bits()),
381                    $type::from_bits(self.im.to_bits() ^ rhs.im.to_bits()),
382                )
383            }
384
385            #[inline(always)]
386            fn __not(self) -> Self {
387                Complex::<$type>::new(
388                    $type::from_bits(!self.re.to_bits()),
389                    $type::from_bits(!self.im.to_bits()),
390                )
391            }
392
393            #[inline(always)]
394            fn __shl(self, _: Self) -> Self {
395                panic!("shift left is not supported for complex numbers")
396            }
397
398            #[inline(always)]
399            fn __shr(self, _: Self) -> Self {
400                panic!("shift right is not supported for complex numbers")
401            }
402        }
403
404        impl Eval2 for Complex<$type> {
405            type Output = bool;
406            #[inline(always)]
407            fn __is_nan(&self) -> Self::Output {
408                self.is_nan()
409            }
410
411            #[inline(always)]
412            fn __is_true(&self) -> Self::Output {
413                self.norm() != 0.0 && !self.is_nan()
414            }
415
416            #[inline(always)]
417            fn __is_inf(&self) -> bool {
418                self.is_infinite()
419            }
420        }
421
422        impl FloatOutUnary2 for Complex<$type> {
423            #[inline(always)]
424            fn __exp(self) -> Self {
425                self.exp()
426            }
427            #[inline(always)]
428            fn __expm1(self) -> Self {
429                self.exp() - 1.0
430            }
431            #[inline(always)]
432            fn __exp2(self) -> Self {
433                self.exp2()
434            }
435            #[inline(always)]
436            fn __ln(self) -> Self {
437                self.ln()
438            }
439            #[inline(always)]
440            fn __log1p(self) -> Self {
441                self.ln() + 1.0
442            }
443            #[inline(always)]
444            fn __celu(self, _: Self) -> Self {
445                panic!("celu is not supported for complex numbers")
446            }
447            #[inline(always)]
448            fn __log2(self) -> Self {
449                self.log2()
450            }
451            #[inline(always)]
452            fn __log10(self) -> Self {
453                self.log10()
454            }
455            #[inline(always)]
456            fn __sqrt(self) -> Self {
457                self.sqrt()
458            }
459            #[inline(always)]
460            fn __sin(self) -> Self {
461                self.sin()
462            }
463            #[inline(always)]
464            fn __cos(self) -> Self {
465                self.cos()
466            }
467            #[inline(always)]
468            fn __tan(self) -> Self {
469                self.tan()
470            }
471            #[inline(always)]
472            fn __asin(self) -> Self {
473                self.asin()
474            }
475            #[inline(always)]
476            fn __acos(self) -> Self {
477                self.acos()
478            }
479            #[inline(always)]
480            fn __atan(self) -> Self {
481                self.atan()
482            }
483            #[inline(always)]
484            fn __sinh(self) -> Self {
485                self.sinh()
486            }
487            #[inline(always)]
488            fn __cosh(self) -> Self {
489                self.cosh()
490            }
491            #[inline(always)]
492            fn __tanh(self) -> Self {
493                self.tanh()
494            }
495            #[inline(always)]
496            fn __asinh(self) -> Self {
497                self.asinh()
498            }
499            #[inline(always)]
500            fn __acosh(self) -> Self {
501                self.acosh()
502            }
503            #[inline(always)]
504            fn __atanh(self) -> Self {
505                self.atanh()
506            }
507            #[inline(always)]
508            fn __recip(self) -> Self {
509                self.recip()
510            }
511            #[inline(always)]
512            fn __erf(self) -> Self {
513                panic!("erf is not supported for complex numbers")
514            }
515
516            #[inline(always)]
517            fn __sigmoid(self) -> Self {
518                1.0 / (1.0 + (-self).exp())
519            }
520
521            fn __elu(self, _: Self) -> Self {
522                panic!("elu is not supported for complex numbers")
523            }
524
525            fn __gelu(self) -> Self {
526                panic!("gelu is not supported for complex numbers")
527            }
528
529            fn __selu(self, _: Self, _: Self) -> Self {
530                panic!("selu is not supported for complex numbers")
531            }
532
533            fn __hard_sigmoid(self) -> Self {
534                panic!("hard sigmoid is not supported for complex numbers")
535            }
536
537            fn __hard_swish(self) -> Self {
538                panic!("hard swish is not supported for complex numbers")
539            }
540
541            fn __softplus(self) -> Self {
542                panic!("softplus is not supported for complex numbers")
543            }
544
545            fn __softsign(self) -> Self {
546                self / (1.0 + self.abs())
547            }
548
549            fn __mish(self) -> Self {
550                self * ((1.0 + self.exp()).ln()).tanh()
551            }
552
553            fn __cbrt(self) -> Self {
554                panic!("cbrt is not supported for complex numbers")
555            }
556
557            fn __sincos(self) -> (Self, Self) {
558                (self.sin(), self.cos())
559            }
560
561            fn __atan2(self, _: Self) -> Self {
562                panic!("atan2 is not supported for complex numbers")
563            }
564
565            fn __exp10(self) -> Self {
566                panic!("exp10 is not supported for complex numbers")
567            }
568        }
569    };
570}
571
572impl_complex!(f32);
573impl_complex!(f64);