Skip to main content

hpt_types/
type_promote.rs

1use crate::into_scalar::Cast;
2use crate::into_vec::IntoVec;
3#[cfg(any(
4    all(not(target_feature = "avx2"), target_feature = "sse"),
5    target_arch = "arm",
6    target_arch = "aarch64",
7    target_feature = "neon"
8))]
9use crate::simd::_128bit::common::*;
10#[cfg(target_feature = "avx2")]
11use crate::simd::_256bit::common::*;
12use crate::traits::SimdMath;
13use crate::vectors::traits::SimdCompare;
14use crate::vectors::traits::VecTrait;
15use half::bf16;
16use half::f16;
17use hpt_macros::{
18    float_out_binary, float_out_binary_simd_with_lhs_scalar, float_out_binary_simd_with_rhs_scalar,
19    float_out_unary, impl_bitwise_out, impl_cmp, impl_eval, impl_normal_out_binary,
20    impl_normal_out_simd, impl_normal_out_simd_with_lhs_scalar,
21    impl_normal_out_simd_with_rhs_scalar, impl_normal_out_unary, impl_normal_out_unary_simd,
22    simd_cmp, simd_eval, simd_float_out_unary,
23};
24use num_complex::{Complex32, Complex64};
25use num_traits::float::Float;
26#[cfg(feature = "cuda")]
27mod cuda_imports {
28    use super::*;
29    use crate::cuda_types::scalar::Scalar;
30    use hpt_macros::{
31        float_out_binary_cuda, float_out_unary_cuda, impl_cmp_cuda, impl_cuda_bitwise_out,
32        impl_cuda_normal_out_binary, impl_normal_out_unary_cuda,
33    };
34    float_out_binary_cuda!();
35    impl_cuda_normal_out_binary!();
36    impl_normal_out_unary_cuda!();
37    impl_cuda_bitwise_out!();
38    impl_cmp_cuda!();
39    float_out_unary_cuda!();
40}
41
42use hpt_macros::{float_out_binary_simd, simd_bitwise};
43
44/// this trait is used to perform type promotion in dynamic graph
45pub trait FloatOutBinary<RHS = Self> {
46    /// the output type
47    type Output;
48    /// perform a / b
49    fn _div(self, rhs: RHS) -> Self::Output;
50    /// perform log<sub>b</sub>(x)
51    fn _log(self, base: RHS) -> Self::Output;
52    /// perform hypot(x, y)
53    fn _hypot(self, rhs: RHS) -> Self::Output;
54    /// perform a<sup>b</sup>
55    fn _pow(self, rhs: RHS) -> Self::Output;
56}
57
58/// this trait is used to perform type promotion for float out binary operations
59pub trait FloatOutBinaryPromote<RHS = Self> {
60    /// the output type
61    type Output;
62    /// the intermediate type
63    type Intermediate;
64}
65
66/// internal trait for float out binary
67pub trait FloatOutBinary2 {
68    /// perform a / b
69    fn __div(self, rhs: Self) -> Self;
70    /// perform log<sub>b</sub>(x)
71    fn __log(self, base: Self) -> Self;
72    /// perform hypot(x, y)
73    fn __hypot(self, rhs: Self) -> Self;
74    /// perform a<sup>b</sup>
75    fn __pow(self, rhs: Self) -> Self;
76}
77
78float_out_binary!();
79float_out_binary_simd!();
80float_out_binary_simd_with_rhs_scalar!();
81float_out_binary_simd_with_lhs_scalar!();
82
83/// this trait is used to perform normal operations that don't require type promotion
84pub trait NormalOut<RHS = Self> {
85    /// the output type
86    type Output;
87    /// perform a + b
88    fn _add(self, rhs: RHS) -> Self::Output;
89    /// perform a - b
90    fn _sub(self, rhs: RHS) -> Self::Output;
91    /// perform self * a + b, fused multiply add
92    /// if the hardware supports it, it can speed up the calculation and reduce the rounding error
93    fn _mul_add(self, a: RHS, b: RHS) -> Self::Output;
94    /// perform a * b
95    fn _mul(self, rhs: RHS) -> Self::Output;
96    /// perform a % b
97    fn _rem(self, rhs: RHS) -> Self::Output;
98    /// perform max(x, y)
99    fn _max(self, rhs: RHS) -> Self::Output;
100    /// perform min(x, y)
101    fn _min(self, rhs: RHS) -> Self::Output;
102    /// restrict the value of x to the range [min, max]
103    fn _clamp(self, min: RHS, max: RHS) -> Self::Output;
104}
105
106/// internal trait for normal out
107pub trait NormalOut2 {
108    /// perform a + b
109    fn __add(self, rhs: Self) -> Self;
110    /// perform a - b
111    fn __sub(self, rhs: Self) -> Self;
112    /// perform self * a + b, fused multiply add
113    /// if the hardware supports it, it can speed up the calculation and reduce the rounding error
114    fn __mul_add(self, a: Self, b: Self) -> Self;
115    /// perform a * b
116    fn __mul(self, rhs: Self) -> Self;
117    /// perform a % b
118    fn __rem(self, rhs: Self) -> Self;
119    /// perform max(x, y)
120    fn __max(self, rhs: Self) -> Self;
121    /// perform min(x, y)
122    fn __min(self, rhs: Self) -> Self;
123    /// restrict the value of x to the range [min, max]
124    fn __clamp(self, min: Self, max: Self) -> Self;
125}
126
127/// this trait is used to perform type promotion for normal out operations
128pub trait NormalOutPromote<RHS = Self> {
129    /// the output type
130    type Output;
131    /// the intermediate type
132    type Intermediate;
133}
134
135impl_normal_out_binary!();
136
137impl_normal_out_simd!();
138
139impl_normal_out_simd_with_rhs_scalar!();
140
141impl_normal_out_simd_with_lhs_scalar!();
142
143//~^ NormalOutUnary is not implemented for {Self}
144/// this trait is used to perform normal unary operations that don't require type promotion
145pub trait NormalOutUnary {
146    /// perform x<sup>2</sup>
147    fn _square(self) -> Self;
148    /// perform |x|
149    fn _abs(self) -> Self;
150    /// perform &lceil;x&rceil;
151    fn _ceil(self) -> Self;
152    /// perform &lfloor;x&rfloor;
153    fn _floor(self) -> Self;
154    /// perform -x
155    fn _neg(self) -> Self;
156    /// perform rounding
157    fn _round(self) -> Self;
158    /// get the sign of x
159    fn _signum(self) -> Self;
160    /// perform truncation
161    fn _trunc(self) -> Self;
162
163    /// Perform the leaky ReLU (Rectified Linear Unit) activation function.
164    ///
165    /// Formula: f(x) = x if x > 0 else alpha * x
166    fn _leaky_relu(self, alpha: Self) -> Self;
167
168    /// Perform the ReLU (Rectified Linear Unit) activation function.
169    ///
170    /// Formula: f(x) = max(0, x)
171    fn _relu(self) -> Self;
172
173    /// Perform the ReLU6 activation function.
174    ///
175    /// Formula: f(x) = min(6, max(0, x))
176    fn _relu6(self) -> Self;
177
178    /// Perform the copysign function.
179    ///
180    /// Formula: f(x, y) = x * sign(y)
181    fn _copysign(self, rhs: Self) -> Self;
182}
183
184/// internal trait for normal out unary
185pub trait NormalOutUnary2 {
186    /// perform x<sup>2</sup>
187    fn __square(self) -> Self;
188    /// perform |x|
189    fn __abs(self) -> Self;
190    /// perform &lceil;x&rceil;
191    fn __ceil(self) -> Self;
192    /// perform &lfloor;x&rfloor;
193    fn __floor(self) -> Self;
194    /// perform -x
195    fn __neg(self) -> Self;
196    /// perform rounding
197    fn __round(self) -> Self;
198    /// get the sign of x
199    fn __signum(self) -> Self;
200    /// perform truncation
201    fn __trunc(self) -> Self;
202    /// Perform the leaky ReLU (Rectified Linear Unit) activation function.
203    ///
204    /// Formula: f(x) = x if x > 0 else alpha * x
205    fn __leaky_relu(self, alpha: Self) -> Self;
206
207    /// Perform the ReLU (Rectified Linear Unit) activation function.
208    ///
209    /// Formula: f(x) = max(0, x)
210    fn __relu(self) -> Self;
211
212    /// Perform the ReLU6 activation function.
213    ///
214    /// Formula: f(x) = min(6, max(0, x))
215    fn __relu6(self) -> Self;
216
217    /// Perform the copysign function.
218    ///
219    /// Formula: f(x, y) = x * sign(y)
220    fn __copysign(self, rhs: Self) -> Self;
221}
222
223impl_normal_out_unary!();
224
225impl_normal_out_unary_simd!();
226
227/// this trait is used to perform bitwise operations
228pub trait BitWiseOut<RHS = Self> {
229    /// the output type
230    type Output;
231    /// perform a & b
232    fn _bitand(self, rhs: RHS) -> Self::Output;
233    /// perform a | b
234    fn _bitor(self, rhs: RHS) -> Self::Output;
235    /// perform a ^ b
236    fn _bitxor(self, rhs: RHS) -> Self::Output;
237    /// perform !a
238    fn _not(self) -> Self::Output;
239    /// perform a << b
240    fn _shl(self, rhs: RHS) -> Self::Output;
241    /// perform a >> b
242    fn _shr(self, rhs: RHS) -> Self::Output;
243}
244
245/// internal trait for bitwise out
246pub trait BitWiseOut2 {
247    /// perform a & b
248    fn __bitand(self, rhs: Self) -> Self;
249    /// perform a | b
250    fn __bitor(self, rhs: Self) -> Self;
251    /// perform a ^ b
252    fn __bitxor(self, rhs: Self) -> Self;
253    /// perform !a
254    fn __not(self) -> Self;
255    /// perform a << b
256    fn __shl(self, rhs: Self) -> Self;
257    /// perform a >> b
258    fn __shr(self, rhs: Self) -> Self;
259}
260
261impl_bitwise_out!();
262
263simd_bitwise!();
264
265/// this trait is used to perform comparison operations
266pub trait Cmp<RHS = Self> {
267    /// the output type
268    type Output;
269    /// perform a == b
270    fn _eq(self, rhs: RHS) -> Self::Output;
271    /// perform a != b
272    fn _ne(self, rhs: RHS) -> Self::Output;
273    /// perform a < b
274    fn _lt(self, rhs: RHS) -> Self::Output;
275    /// perform a <= b
276    fn _le(self, rhs: RHS) -> Self::Output;
277    /// perform a > b
278    fn _gt(self, rhs: RHS) -> Self::Output;
279    /// perform a >= b
280    fn _ge(self, rhs: RHS) -> Self::Output;
281}
282impl_cmp!();
283
284/// this trait is used to perform comparison operations on simd
285pub trait SimdCmp<RHS = Self> {
286    /// the output type
287    type Output;
288    /// perform a == b, return a mask
289    ///
290    /// # Note
291    ///
292    /// The mask may not be a boolean value, the type is based on the byte width of the simd
293    fn _eq(self, rhs: RHS) -> Self::Output;
294    /// perform a != b, return a mask
295    ///
296    /// # Note
297    ///
298    /// The mask may not be a boolean value, the type is based on the byte width of the simd
299    fn _ne(self, rhs: RHS) -> Self::Output;
300    /// perform a < b, return a mask
301    ///
302    /// # Note
303    ///
304    /// The mask may not be a boolean value, the type is based on the byte width of the simd
305    fn _lt(self, rhs: RHS) -> Self::Output;
306    /// perform a <= b, return a mask
307    ///
308    /// # Note
309    ///
310    /// The mask may not be a boolean value, the type is based on the byte width of the simd
311    fn _le(self, rhs: RHS) -> Self::Output;
312    /// perform a > b, return a mask
313    ///
314    /// # Note
315    ///
316    /// The mask may not be a boolean value, the type is based on the byte width of the simd
317    fn _gt(self, rhs: RHS) -> Self::Output;
318    /// perform a >= b, return a mask
319    ///
320    /// # Note
321    ///
322    /// The mask may not be a boolean value, the type is based on the byte width of the simd
323    fn _ge(self, rhs: RHS) -> Self::Output;
324}
325
326/// this trait is used to perform comparison operations on simd
327pub trait SimdCmpPromote<RHS = Self> {
328    /// the output type
329    type Output;
330}
331
332simd_cmp!();
333
334/// this trait is used to perform evaluation operations
335pub trait Eval {
336    /// the output type
337    type Output;
338    /// check if the value is nan
339    fn _is_nan(&self) -> Self::Output;
340    /// check if the value is finite
341    fn _is_true(&self) -> Self::Output;
342    /// check if the value is infinite
343    fn _is_inf(&self) -> Self::Output;
344}
345
346/// internal trait for eval
347pub trait Eval2 {
348    /// the output type
349    type Output;
350    /// check if the value is nan
351    fn __is_nan(&self) -> Self::Output;
352    /// check if the value is finite
353    fn __is_true(&self) -> Self::Output;
354    /// check if the value is infinite
355    fn __is_inf(&self) -> Self::Output;
356}
357
358impl_eval!();
359simd_eval!();
360
361//~^ FloatOutUnary is not implemented for {Self}
362/// This trait is used to perform various unary floating-point operations.
363pub trait FloatOutUnary {
364    /// The output type.
365    type Output;
366
367    /// Perform the natural exponential function: e<sup>x</sup>.
368    fn _exp(self) -> Self::Output;
369
370    /// Perform the natural exponential function: e<sup>x</sup> - 1.
371    fn _expm1(self) -> Self::Output;
372
373    /// Perform the base-2 exponential function: 2<sup>x</sup>.
374    fn _exp2(self) -> Self::Output;
375
376    /// Perform the base-10 exponential function: 10<sup>x</sup>.
377    fn _exp10(self) -> Self::Output;
378
379    /// Perform the natural logarithm: ln(x).
380    fn _ln(self) -> Self::Output;
381
382    /// Perform the natural logarithm: ln(x + 1).
383    fn _log1p(self) -> Self::Output;
384
385    /// Perform the CELU (Continuously Differentiable Exponential Linear Unit) activation function.
386    ///
387    /// Formula: f(x) = max(0, x) + min(0, alpha * (e<sup>(x / alpha)</sup> - 1))
388    fn _celu(self, alpha: Self::Output) -> Self::Output;
389
390    /// Perform the base-2 logarithm: log<sub>2</sub>(x).
391    fn _log2(self) -> Self::Output;
392
393    /// Perform the base-10 logarithm: log<sub>10</sub>(x).
394    fn _log10(self) -> Self::Output;
395
396    /// Perform the square root: √x.
397    fn _sqrt(self) -> Self::Output;
398
399    /// Perform the sine function: sin(x).
400    fn _sin(self) -> Self::Output;
401
402    /// Perform the cosine function: cos(x).
403    fn _cos(self) -> Self::Output;
404
405    /// Perform the sine and cosine functions: sin(x) and cos(x).
406    fn _sincos(self) -> (Self::Output, Self::Output);
407
408    /// Perform the tangent function: tan(x).
409    fn _tan(self) -> Self::Output;
410
411    /// Perform the inverse sine (arcsin) function: asin(x).
412    fn _asin(self) -> Self::Output;
413
414    /// Perform the inverse cosine (arccos) function: acos(x).
415    fn _acos(self) -> Self::Output;
416
417    /// Perform the inverse tangent (arctan) function: atan(x).
418    fn _atan(self) -> Self::Output;
419
420    /// Perform the inverse tangent function: atan2(y, x).
421    fn _atan2(self, rhs: Self::Output) -> Self::Output;
422
423    /// Perform the hyperbolic sine function: sinh(x).
424    fn _sinh(self) -> Self::Output;
425
426    /// Perform the hyperbolic cosine function: cosh(x).
427    fn _cosh(self) -> Self::Output;
428
429    /// Perform the hyperbolic tangent function: tanh(x).
430    fn _tanh(self) -> Self::Output;
431
432    /// Perform the inverse hyperbolic sine (arsinh) function: asinh(x).
433    fn _asinh(self) -> Self::Output;
434
435    /// Perform the inverse hyperbolic cosine (arcosh) function: acosh(x).
436    fn _acosh(self) -> Self::Output;
437
438    /// Perform the inverse hyperbolic tangent (artanh) function: atanh(x).
439    fn _atanh(self) -> Self::Output;
440
441    /// Perform the reciprocal function: 1 / x.
442    fn _recip(self) -> Self::Output;
443
444    /// Perform the error function (erf).
445    fn _erf(self) -> Self::Output;
446
447    /// Perform the sigmoid function: 1 / (1 + e<sup>-x</sup>).
448    fn _sigmoid(self) -> Self::Output;
449
450    /// Perform the ELU (Exponential Linear Unit) activation function.
451    ///
452    /// Formula: f(x) = x if x > 0 else alpha * (e<sup>x</sup> - 1)
453    fn _elu(self, alpha: Self::Output) -> Self::Output;
454
455    /// Perform the GELU (Gaussian Error Linear Unit) activation function.
456    fn _gelu(self) -> Self::Output;
457
458    /// Perform the SELU (Scaled Exponential Linear Unit) activation function.
459    ///
460    /// Formula: f(x) = scale * (x if x > 0 else alpha * (e<sup>x</sup> - 1))
461    fn _selu(self, alpha: Self::Output, scale: Self::Output) -> Self::Output;
462
463    /// Perform the hard sigmoid activation function.
464    ///
465    /// Formula: f(x) = min(1, max(0, 0.2 * x + 0.5))
466    fn _hard_sigmoid(self) -> Self::Output;
467
468    /// Perform the hard swish activation function.
469    ///
470    /// Formula: f(x) = x * min(1, max(0, 0.2 * x + 0.5))
471    fn _hard_swish(self) -> Self::Output;
472
473    /// Perform the softplus activation function.
474    ///
475    /// Formula: f(x) = ln(1 + e<sup>x</sup>)
476    fn _softplus(self) -> Self::Output;
477
478    /// Perform the softsign activation function.
479    ///
480    /// Formula: f(x) = x / (1 + |x|)
481    fn _softsign(self) -> Self::Output;
482
483    /// Perform the mish activation function.
484    ///
485    /// Formula: f(x) = x * tanh(ln(1 + e<sup>x</sup>))
486    fn _mish(self) -> Self::Output;
487
488    /// Perform the cube root function: ∛x.
489    fn _cbrt(self) -> Self::Output;
490}
491
492/// internal trait for float out unary
493pub trait FloatOutUnary2 {
494    /// Perform the natural exponential function: e<sup>x</sup>.
495    fn __exp(self) -> Self;
496
497    /// Perform the natural exponential function: e<sup>x</sup> - 1.
498    fn __expm1(self) -> Self;
499
500    /// Perform the base-2 exponential function: 2<sup>x</sup>.
501    fn __exp2(self) -> Self;
502
503    /// Perform the base-10 exponential function: 10<sup>x</sup>.
504    fn __exp10(self) -> Self;
505
506    /// Perform the natural logarithm: ln(x).
507    fn __ln(self) -> Self;
508
509    /// Perform the natural logarithm: ln(x + 1).
510    fn __log1p(self) -> Self;
511
512    /// Perform the CELU (Continuously Differentiable Exponential Linear Unit) activation function.
513    ///
514    /// Formula: f(x) = max(0, x) + min(0, alpha * (e<sup>(x / alpha)</sup> - 1))
515    fn __celu(self, alpha: Self) -> Self;
516
517    /// Perform the base-2 logarithm: log<sub>2</sub>(x).
518    fn __log2(self) -> Self;
519
520    /// Perform the base-10 logarithm: log<sub>10</sub>(x).
521    fn __log10(self) -> Self;
522
523    /// Perform the square root: √x.
524    fn __sqrt(self) -> Self;
525
526    /// Perform the sine function: sin(x).
527    fn __sin(self) -> Self;
528
529    /// Perform the cosine function: cos(x).
530    fn __cos(self) -> Self;
531
532    /// Perform the sine and cosine functions: sin(x) and cos(x).
533    fn __sincos(self) -> (Self, Self)
534    where
535        Self: Sized;
536
537    /// Perform the tangent function: tan(x).
538    fn __tan(self) -> Self;
539
540    /// Perform the inverse sine (arcsin) function: asin(x).
541    fn __asin(self) -> Self;
542
543    /// Perform the inverse cosine (arccos) function: acos(x).
544    fn __acos(self) -> Self;
545
546    /// Perform the inverse tangent (arctan) function: atan(x).
547    fn __atan(self) -> Self;
548
549    /// Perform the inverse tangent function: atan2(y, x).
550    fn __atan2(self, rhs: Self) -> Self;
551
552    /// Perform the hyperbolic sine function: sinh(x).
553    fn __sinh(self) -> Self;
554
555    /// Perform the hyperbolic cosine function: cosh(x).
556    fn __cosh(self) -> Self;
557
558    /// Perform the hyperbolic tangent function: tanh(x).
559    fn __tanh(self) -> Self;
560
561    /// Perform the inverse hyperbolic sine (arsinh) function: asinh(x).
562    fn __asinh(self) -> Self;
563
564    /// Perform the inverse hyperbolic cosine (arcosh) function: acosh(x).
565    fn __acosh(self) -> Self;
566
567    /// Perform the inverse hyperbolic tangent (artanh) function: atanh(x).
568    fn __atanh(self) -> Self;
569
570    /// Perform the reciprocal function: 1 / x.
571    fn __recip(self) -> Self;
572
573    /// Perform the error function (erf).
574    fn __erf(self) -> Self;
575
576    /// Perform the sigmoid function: 1 / (1 + e<sup>-x</sup>).
577    fn __sigmoid(self) -> Self;
578
579    /// Perform the ELU (Exponential Linear Unit) activation function.
580    ///
581    /// Formula: f(x) = x if x > 0 else alpha * (e<sup>x</sup> - 1)
582    fn __elu(self, alpha: Self) -> Self;
583
584    /// Perform the GELU (Gaussian Error Linear Unit) activation function.
585    fn __gelu(self) -> Self;
586
587    /// Perform the SELU (Scaled Exponential Linear Unit) activation function.
588    ///
589    /// Formula: f(x) = scale * (x if x > 0 else alpha * (e<sup>x</sup> - 1))
590    fn __selu(self, alpha: Self, scale: Self) -> Self;
591
592    /// Perform the hard sigmoid activation function.
593    ///
594    /// Formula: f(x) = min(1, max(0, 0.2 * x + 0.5))
595    fn __hard_sigmoid(self) -> Self;
596
597    /// Perform the hard swish activation function.
598    ///
599    /// Formula: f(x) = x * min(1, max(0, 0.2 * x + 0.5))
600    fn __hard_swish(self) -> Self;
601
602    /// Perform the softplus activation function.
603    ///
604    /// Formula: f(x) = ln(1 + e<sup>x</sup>)
605    fn __softplus(self) -> Self;
606
607    /// Perform the softsign activation function.
608    ///
609    /// Formula: f(x) = x / (1 + |x|)
610    fn __softsign(self) -> Self;
611
612    /// Perform the mish activation function.
613    ///
614    /// Formula: f(x) = x * tanh(ln(1 + e<sup>x</sup>))
615    fn __mish(self) -> Self;
616
617    /// Perform the cube root function: ∛x.
618    fn __cbrt(self) -> Self;
619}
620
621/// this trait is used to promote the float out unary trait to the output type
622pub trait FloatOutUnaryPromote {
623    /// the output type
624    type Output;
625    /// the intermediate type
626    type Intermediate;
627}
628
629float_out_unary!();
630
631simd_float_out_unary!();