1pub trait GpuFloat: Copy + PartialOrd + private::Sealed {
9 fn floor(self) -> Self;
10 fn ceil(self) -> Self;
11 fn round(self) -> Self;
12 fn trunc(self) -> Self;
13 fn fract(self) -> Self;
14 fn abs(self) -> Self;
15 fn signum(self) -> Self;
16 fn copysign(self, sign: Self) -> Self;
17 fn mul_add(self, a: Self, b: Self) -> Self;
18 fn div_euclid(self, rhs: Self) -> Self;
19 fn rem_euclid(self, rhs: Self) -> Self;
20 fn powi(self, n: i32) -> Self;
21 fn powf(self, n: Self) -> Self;
22 fn sqrt(self) -> Self;
23 fn exp(self) -> Self;
24 fn exp2(self) -> Self;
25 fn ln(self) -> Self;
26 fn log(self, base: Self) -> Self;
27 fn log2(self) -> Self;
28 fn log10(self) -> Self;
29 fn cbrt(self) -> Self;
30 fn hypot(self, other: Self) -> Self;
31 fn sin(self) -> Self;
32 fn cos(self) -> Self;
33 fn tan(self) -> Self;
34 fn asin(self) -> Self;
35 fn acos(self) -> Self;
36 fn atan(self) -> Self;
37 fn atan2(self, other: Self) -> Self;
38 fn sin_cos(self) -> (Self, Self);
39 fn exp_m1(self) -> Self;
40 fn ln_1p(self) -> Self;
41 fn sinh(self) -> Self;
42 fn cosh(self) -> Self;
43 fn tanh(self) -> Self;
44 fn asinh(self) -> Self;
45 fn acosh(self) -> Self;
46 fn atanh(self) -> Self;
47}
48
49mod private {
50 pub trait Sealed {}
51 impl Sealed for f32 {}
52 impl Sealed for f64 {}
53}
54
55macro_rules! f32_intrinsic {
56 ($self:expr, $func:ident($($param:expr),*)) => {{
57 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
58 let val = $self.$func($($param),*);
59 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
60 let val = paste::paste! { unsafe { intrinsics::[<$func f>]($self, $($param),*)} };
61 val
62 }};
63}
64
65macro_rules! f64_intrinsic {
66 ($self:expr, $func:ident($($param:expr),*)) => {{
67 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
68 let val = $self.$func($($param),*);
69 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
70 let val = unsafe { intrinsics::$func($self, $($param),*)};
71 val
72 }};
73}
74
75#[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
76use crate::intrinsics;
77
78impl GpuFloat for f32 {
79 #[must_use = "method returns a new number and does not mutate the original value"]
81 #[inline]
82 fn floor(self) -> f32 {
83 f32_intrinsic!(self, floor())
84 }
85
86 #[must_use = "method returns a new number and does not mutate the original value"]
88 #[inline]
89 fn ceil(self) -> f32 {
90 f32_intrinsic!(self, ceil())
91 }
92
93 #[must_use = "method returns a new number and does not mutate the original value"]
96 #[inline]
97 fn round(self) -> f32 {
98 f32_intrinsic!(self, round())
99 }
100
101 #[must_use = "method returns a new number and does not mutate the original value"]
103 #[inline]
104 fn trunc(self) -> f32 {
105 f32_intrinsic!(self, trunc())
106 }
107
108 #[must_use = "method returns a new number and does not mutate the original value"]
110 #[inline]
111 fn fract(self) -> f32 {
112 self - self.trunc()
113 }
114
115 #[must_use = "method returns a new number and does not mutate the original value"]
118 #[inline]
119 fn abs(self) -> f32 {
120 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
121 let val = self.abs();
122 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
123 let val = { unsafe { intrinsics::fabsf(self) } };
124 val
125 }
126
127 #[must_use = "method returns a new number and does not mutate the original value"]
133 #[inline]
134 fn signum(self) -> f32 {
135 if self.is_nan() {
136 Self::NAN
137 } else {
138 1.0_f32.copysign(self)
139 }
140 }
141
142 #[must_use = "method returns a new number and does not mutate the original value"]
149 #[inline]
150 fn copysign(self, sign: f32) -> f32 {
151 f32_intrinsic!(self, copysign(sign))
152 }
153
154 #[must_use = "method returns a new number and does not mutate the original value"]
162 #[inline]
163 fn mul_add(self, a: f32, b: f32) -> f32 {
164 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
165 let val = self.mul_add(a, b);
166 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
167 let val = { unsafe { intrinsics::fmaf(self, a, b) } };
168 val
169 }
170
171 #[must_use = "method returns a new number and does not mutate the original value"]
178 #[inline]
179 fn div_euclid(self, rhs: f32) -> f32 {
180 let q = (self / rhs).trunc();
181 if self % rhs < 0.0 {
182 return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
183 }
184 q
185 }
186
187 #[must_use = "method returns a new number and does not mutate the original value"]
198 #[inline]
199 fn rem_euclid(self, rhs: f32) -> f32 {
200 let r = self % rhs;
201 if r < 0.0 {
202 r + rhs.abs()
203 } else {
204 r
205 }
206 }
207
208 #[must_use = "method returns a new number and does not mutate the original value"]
212 #[inline]
213 fn powi(self, n: i32) -> f32 {
214 f32_intrinsic!(self, powi(n))
215 }
216
217 #[must_use = "method returns a new number and does not mutate the original value"]
219 #[inline]
220 fn powf(self, n: f32) -> f32 {
221 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
222 let val = self.powf(n);
223 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
224 let val = { unsafe { intrinsics::powf(self, n) } };
225 val
226 }
227
228 #[must_use = "method returns a new number and does not mutate the original value"]
232 #[inline]
233 fn sqrt(self) -> f32 {
234 f32_intrinsic!(self, sqrt())
235 }
236
237 #[must_use = "method returns a new number and does not mutate the original value"]
239 #[inline]
240 fn exp(self) -> f32 {
241 f32_intrinsic!(self, exp())
242 }
243
244 #[must_use = "method returns a new number and does not mutate the original value"]
246 #[inline]
247 fn exp2(self) -> f32 {
248 f32_intrinsic!(self, exp2())
249 }
250
251 #[must_use = "method returns a new number and does not mutate the original value"]
253 #[inline]
254 fn ln(self) -> f32 {
255 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
256 let val = self.ln();
257 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
258 let val = { unsafe { intrinsics::logf(self) } };
259 val
260 }
261
262 #[must_use = "method returns a new number and does not mutate the original value"]
268 #[inline]
269 fn log(self, base: f32) -> f32 {
270 self.ln() / base.ln()
271 }
272
273 #[must_use = "method returns a new number and does not mutate the original value"]
275 #[inline]
276 fn log2(self) -> f32 {
277 f32_intrinsic!(self, log10())
278 }
279
280 #[must_use = "method returns a new number and does not mutate the original value"]
282 #[inline]
283 fn log10(self) -> f32 {
284 f32_intrinsic!(self, log10())
285 }
286
287 #[must_use = "method returns a new number and does not mutate the original value"]
289 #[inline]
290 fn cbrt(self) -> f32 {
291 f32_intrinsic!(self, cbrt())
292 }
293
294 #[must_use = "method returns a new number and does not mutate the original value"]
297 #[inline]
298 fn hypot(self, other: f32) -> f32 {
299 f32_intrinsic!(self, hypot(other))
300 }
301
302 #[must_use = "method returns a new number and does not mutate the original value"]
304 #[inline]
305 fn sin(self) -> f32 {
306 f32_intrinsic!(self, sin())
307 }
308
309 #[must_use = "method returns a new number and does not mutate the original value"]
311 #[inline]
312 fn cos(self) -> f32 {
313 f32_intrinsic!(self, cos())
314 }
315
316 #[must_use = "method returns a new number and does not mutate the original value"]
318 #[inline]
319 fn tan(self) -> f32 {
320 f32_intrinsic!(self, tan())
321 }
322
323 #[must_use = "method returns a new number and does not mutate the original value"]
327 #[inline]
328 fn asin(self) -> f32 {
329 f32_intrinsic!(self, asin())
330 }
331
332 #[must_use = "method returns a new number and does not mutate the original value"]
336 #[inline]
337 fn acos(self) -> f32 {
338 f32_intrinsic!(self, acos())
339 }
340
341 #[must_use = "method returns a new number and does not mutate the original value"]
344 #[inline]
345 fn atan(self) -> f32 {
346 f32_intrinsic!(self, atan())
347 }
348
349 #[must_use = "method returns a new number and does not mutate the original value"]
356 #[inline]
357 fn atan2(self, other: f32) -> f32 {
358 f32_intrinsic!(self, atan2(other))
359 }
360
361 #[inline]
364 fn sin_cos(self) -> (f32, f32) {
365 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
366 let val = self.sin_cos();
367 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
368 let val = {
369 let mut sptr = 0.0;
370 let mut cptr = 0.0;
371 unsafe {
372 intrinsics::sincosf(self, &mut sptr as *mut _, &mut cptr as *mut _);
373 }
374 (sptr, cptr)
375 };
376 val
377 }
378
379 #[must_use = "method returns a new number and does not mutate the original value"]
382 #[inline]
383 fn exp_m1(self) -> f32 {
384 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
385 let val = self.exp_m1();
386 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
387 let val = { unsafe { intrinsics::expm1f(self) } };
388 val
389 }
390
391 #[must_use = "method returns a new number and does not mutate the original value"]
394 #[inline]
395 fn ln_1p(self) -> f32 {
396 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
397 let val = self.ln_1p();
398 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
399 let val = { unsafe { intrinsics::log1pf(self) } };
400 val
401 }
402
403 #[must_use = "method returns a new number and does not mutate the original value"]
405 #[inline]
406 fn sinh(self) -> f32 {
407 f32_intrinsic!(self, sinh())
408 }
409
410 #[must_use = "method returns a new number and does not mutate the original value"]
412 #[inline]
413 fn cosh(self) -> f32 {
414 f32_intrinsic!(self, cosh())
415 }
416
417 #[must_use = "method returns a new number and does not mutate the original value"]
419 #[inline]
420 fn tanh(self) -> f32 {
421 f32_intrinsic!(self, tanh())
422 }
423
424 #[must_use = "method returns a new number and does not mutate the original value"]
426 #[inline]
427 fn asinh(self) -> f32 {
428 f32_intrinsic!(self, asinh())
429 }
430
431 #[must_use = "method returns a new number and does not mutate the original value"]
433 #[inline]
434 fn acosh(self) -> f32 {
435 f32_intrinsic!(self, acosh())
436 }
437
438 #[must_use = "method returns a new number and does not mutate the original value"]
440 #[inline]
441 fn atanh(self) -> f32 {
442 f32_intrinsic!(self, atanh())
443 }
444}
445
446impl GpuFloat for f64 {
447 #[must_use = "method returns a new number and does not mutate the original value"]
449 #[inline]
450 fn floor(self) -> f64 {
451 f64_intrinsic!(self, floor())
452 }
453
454 #[must_use = "method returns a new number and does not mutate the original value"]
456 #[inline]
457 fn ceil(self) -> f64 {
458 f64_intrinsic!(self, ceil())
459 }
460
461 #[must_use = "method returns a new number and does not mutate the original value"]
464 #[inline]
465 fn round(self) -> f64 {
466 f64_intrinsic!(self, round())
467 }
468
469 #[must_use = "method returns a new number and does not mutate the original value"]
471 #[inline]
472 fn trunc(self) -> f64 {
473 f64_intrinsic!(self, trunc())
474 }
475
476 #[must_use = "method returns a new number and does not mutate the original value"]
478 #[inline]
479 fn fract(self) -> f64 {
480 self - self.trunc()
481 }
482
483 #[must_use = "method returns a new number and does not mutate the original value"]
486 #[inline]
487 fn abs(self) -> f64 {
488 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
489 let val = self.abs();
490 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
491 let val = { unsafe { intrinsics::fabs(self) } };
492 val
493 }
494
495 #[must_use = "method returns a new number and does not mutate the original value"]
501 #[inline]
502 fn signum(self) -> f64 {
503 if self.is_nan() {
504 Self::NAN
505 } else {
506 1.0_f64.copysign(self)
507 }
508 }
509
510 #[must_use = "method returns a new number and does not mutate the original value"]
517 #[inline]
518 fn copysign(self, sign: f64) -> f64 {
519 f64_intrinsic!(self, copysign(sign))
520 }
521
522 #[must_use = "method returns a new number and does not mutate the original value"]
530 #[inline]
531 fn mul_add(self, a: f64, b: f64) -> f64 {
532 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
533 let val = self.mul_add(a, b);
534 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
535 let val = { unsafe { intrinsics::fma(self, a, b) } };
536 val
537 }
538
539 #[must_use = "method returns a new number and does not mutate the original value"]
546 #[inline]
547 fn div_euclid(self, rhs: f64) -> f64 {
548 let q = (self / rhs).trunc();
549 if self % rhs < 0.0 {
550 return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
551 }
552 q
553 }
554
555 #[must_use = "method returns a new number and does not mutate the original value"]
566 #[inline]
567 fn rem_euclid(self, rhs: f64) -> f64 {
568 let r = self % rhs;
569 if r < 0.0 {
570 r + rhs.abs()
571 } else {
572 r
573 }
574 }
575
576 #[must_use = "method returns a new number and does not mutate the original value"]
580 #[inline]
581 fn powi(self, n: i32) -> f64 {
582 f64_intrinsic!(self, powi(n))
583 }
584
585 #[must_use = "method returns a new number and does not mutate the original value"]
587 #[inline]
588 fn powf(self, n: f64) -> f64 {
589 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
590 let val = self.powf(n);
591 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
592 let val = { unsafe { intrinsics::pow(self, n) } };
593 val
594 }
595
596 #[must_use = "method returns a new number and does not mutate the original value"]
600 #[inline]
601 fn sqrt(self) -> f64 {
602 f64_intrinsic!(self, sqrt())
603 }
604
605 #[must_use = "method returns a new number and does not mutate the original value"]
607 #[inline]
608 fn exp(self) -> f64 {
609 f64_intrinsic!(self, exp())
610 }
611
612 #[must_use = "method returns a new number and does not mutate the original value"]
614 #[inline]
615 fn exp2(self) -> f64 {
616 f64_intrinsic!(self, exp2())
617 }
618
619 #[must_use = "method returns a new number and does not mutate the original value"]
621 #[inline]
622 fn ln(self) -> f64 {
623 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
624 let val = self.ln();
625 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
626 let val = { unsafe { intrinsics::log(self) } };
627 val
628 }
629
630 #[must_use = "method returns a new number and does not mutate the original value"]
636 #[inline]
637 fn log(self, base: f64) -> f64 {
638 self.ln() / base.ln()
639 }
640
641 #[must_use = "method returns a new number and does not mutate the original value"]
643 #[inline]
644 fn log2(self) -> f64 {
645 f64_intrinsic!(self, log10())
646 }
647
648 #[must_use = "method returns a new number and does not mutate the original value"]
650 #[inline]
651 fn log10(self) -> f64 {
652 f64_intrinsic!(self, log10())
653 }
654
655 #[must_use = "method returns a new number and does not mutate the original value"]
657 #[inline]
658 fn cbrt(self) -> f64 {
659 f64_intrinsic!(self, cbrt())
660 }
661
662 #[must_use = "method returns a new number and does not mutate the original value"]
665 #[inline]
666 fn hypot(self, other: f64) -> f64 {
667 f64_intrinsic!(self, hypot(other))
668 }
669
670 #[must_use = "method returns a new number and does not mutate the original value"]
672 #[inline]
673 fn sin(self) -> f64 {
674 f64_intrinsic!(self, sin())
675 }
676
677 #[must_use = "method returns a new number and does not mutate the original value"]
679 #[inline]
680 fn cos(self) -> f64 {
681 f64_intrinsic!(self, cos())
682 }
683
684 #[must_use = "method returns a new number and does not mutate the original value"]
686 #[inline]
687 fn tan(self) -> f64 {
688 f64_intrinsic!(self, tan())
689 }
690
691 #[must_use = "method returns a new number and does not mutate the original value"]
695 #[inline]
696 fn asin(self) -> f64 {
697 f64_intrinsic!(self, asin())
698 }
699
700 #[must_use = "method returns a new number and does not mutate the original value"]
704 #[inline]
705 fn acos(self) -> f64 {
706 f64_intrinsic!(self, acos())
707 }
708
709 #[must_use = "method returns a new number and does not mutate the original value"]
712 #[inline]
713 fn atan(self) -> f64 {
714 f64_intrinsic!(self, atan())
715 }
716
717 #[must_use = "method returns a new number and does not mutate the original value"]
724 #[inline]
725 fn atan2(self, other: f64) -> f64 {
726 f64_intrinsic!(self, atan2(other))
727 }
728
729 #[inline]
732 fn sin_cos(self) -> (f64, f64) {
733 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
734 let val = self.sin_cos();
735 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
736 let val = {
737 let mut sptr = 0.0;
738 let mut cptr = 0.0;
739 unsafe {
740 intrinsics::sincos(self, &mut sptr as *mut _, &mut cptr as *mut _);
741 }
742 (sptr, cptr)
743 };
744 val
745 }
746
747 #[must_use = "method returns a new number and does not mutate the original value"]
750 #[inline]
751 fn exp_m1(self) -> f64 {
752 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
753 let val = self.exp_m1();
754 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
755 let val = { unsafe { intrinsics::expm1(self) } };
756 val
757 }
758
759 #[must_use = "method returns a new number and does not mutate the original value"]
762 #[inline]
763 fn ln_1p(self) -> f64 {
764 #[cfg(not(any(target_arch = "nvptx", target_arch = "nvptx64")))]
765 let val = self.ln_1p();
766 #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))]
767 let val = { unsafe { intrinsics::log1p(self) } };
768 val
769 }
770
771 #[must_use = "method returns a new number and does not mutate the original value"]
773 #[inline]
774 fn sinh(self) -> f64 {
775 f64_intrinsic!(self, sinh())
776 }
777
778 #[must_use = "method returns a new number and does not mutate the original value"]
780 #[inline]
781 fn cosh(self) -> f64 {
782 f64_intrinsic!(self, cosh())
783 }
784
785 #[must_use = "method returns a new number and does not mutate the original value"]
787 #[inline]
788 fn tanh(self) -> f64 {
789 f64_intrinsic!(self, tanh())
790 }
791
792 #[must_use = "method returns a new number and does not mutate the original value"]
794 #[inline]
795 fn asinh(self) -> f64 {
796 f64_intrinsic!(self, asinh())
797 }
798
799 #[must_use = "method returns a new number and does not mutate the original value"]
801 #[inline]
802 fn acosh(self) -> f64 {
803 f64_intrinsic!(self, acosh())
804 }
805
806 #[must_use = "method returns a new number and does not mutate the original value"]
808 #[inline]
809 fn atanh(self) -> f64 {
810 f64_intrinsic!(self, atanh())
811 }
812}