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 ⌈x⌉
151 fn _ceil(self) -> Self;
152 /// perform ⌊x⌋
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 ⌈x⌉
191 fn __ceil(self) -> Self;
192 /// perform ⌊x⌋
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!();