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);