cuda_std/
float.rs

1//! Trait for float intrinsics for making floats work in no_std gpu environments.
2//!
3//! Float functions are mapped directly to libdevice intrinsics on nvptx and
4//! their std counterparts on non-nvptx.
5
6/// std float intrinsics implemented using libdevice intrinsics so they can be used
7/// from GPU no_std crates. Falls back to stdlib implementation on non-nvptx.
8pub 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    /// Returns the largest integer less than or equal to a number.
80    #[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    /// Returns the smallest integer greater than or equal to a number.
87    #[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    /// Returns the nearest integer to a number. Round half-way cases away from
94    /// `0.0`.
95    #[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    /// Returns the integer part of a number.
102    #[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    /// Returns the fractional part of a number.
109    #[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    /// Computes the absolute value of `self`. Returns `NAN` if the
116    /// number is `NAN`.
117    #[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    /// Returns a number that represents the sign of `self`.
128    ///
129    /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
130    /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
131    /// - `NAN` if the number is `NAN`intrinsics
132    #[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    /// Returns a number composed of the magnitude of `self` and the sign of
143    /// `sign`.
144    ///
145    /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
146    /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
147    /// `sign` is returned.
148    #[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    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
155    /// error, yielding a more accurate result than an unfused multiply-add.
156    ///
157    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
158    /// the target architecture has a dedicated `fma` CPU instruction. However,
159    /// this is not always true, and will be heavily dependant on designing
160    /// algorithms with specific target hardware in mind.
161    #[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    /// Calculates Euclidean division, the matching method for `rem_euclid`.
172    ///
173    /// This computes the integer `n` such that
174    /// `self = n * rhs + self.rem_euclid(rhs)`.
175    /// In other words, the result is `self / rhs` rounded to the integer `n`
176    /// such that `self >= n * rhs`.
177    #[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    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
188    ///
189    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
190    /// most cases. However, due to a floating point round-off error it can
191    /// result in `r == rhs.abs()`, violating the mathematical definition, if
192    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
193    /// This result is not an element of the function's codomain, but it is the
194    /// closest floating point number in the real numbers and thus fulfills the
195    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
196    /// approximatively.
197    #[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    /// Raises a number to an integer power.
209    ///
210    /// Using this function is generally faster than using `powf`intrinsics
211    #[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    /// Raises a number to a floating point power.
218    #[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    /// Returns the square root of a number.
229    ///
230    /// Returns NaN if `self` is a negative number other than `-0.0`.
231    #[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    /// Returns `e^(self)`, (the exponential function).
238    #[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    /// Returns `2^(self)`.
245    #[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    /// Returns the natural logarithm of the number.
252    #[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    /// Returns the logarithm of the number with respect to an arbitrary base.
263    ///
264    /// The result might not be correctly rounded owing to implementation details;
265    /// `self.log2()` can produce more accurate results for base 2, and
266    /// `self.log10()` can produce more accurate results for base 10.
267    #[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    /// Returns the base 2 logarithm of the number.
274    #[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    /// Returns the base 10 logarithm of the number.
281    #[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    /// Returns the cube root of a number.
288    #[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    /// Calculates the length of the hypotenuse of a right-angle triangle given
295    /// legs of length `x` and `y`.
296    #[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    /// Computes the sine of a number (in radians).
303    #[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    /// Computes the cosine of a number (in radians).
310    #[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    /// Computes the tangent of a number (in radians).
317    #[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    /// Computes the arcsine of a number. Return value is in radians in
324    /// the range [-pi/2, pi/2] or NaN if the number is outside the range
325    /// [-1, 1].
326    #[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    /// Computes the arccosine of a number. Return value is in radians in
333    /// the range [0, pi] or NaN if the number is outside the range
334    /// [-1, 1].
335    #[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    /// Computes the arctangent of a number. Return value is in radians in the
342    /// range [-pi/2, pi/2];intrinsics
343    #[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    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
350    ///
351    /// * `x = 0`, `y = 0`: `0`
352    /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
353    /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
354    /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`intrinsics
355    #[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    /// Simultaneously computes the sine and cosine of the number, `x`. Returns
362    /// `(sin(x), cos(x))`.
363    #[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    /// Returns `e^(self) - 1` in a way that is accurate even if the
380    /// number is close to zero.
381    #[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    /// Returns `ln(1+n)` (natural logarithm) more accurately than if
392    /// the operations were performed separately.
393    #[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    /// Hyperbolic sine function.
404    #[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    /// Hyperbolic cosine function.
411    #[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    /// Hyperbolic tangent function.
418    #[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    /// Inverse hyperbolic sine function.
425    #[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    /// Inverse hyperbolic cosine function.
432    #[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    /// Inverse hyperbolic tangent function.
439    #[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    /// Returns the largest integer less than or equal to a number.
448    #[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    /// Returns the smallest integer greater than or equal to a number.
455    #[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    /// Returns the nearest integer to a number. Round half-way cases away from
462    /// `0.0`.
463    #[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    /// Returns the integer part of a number.
470    #[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    /// Returns the fractional part of a number.
477    #[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    /// Computes the absolute value of `self`. Returns `NAN` if the
484    /// number is `NAN`.
485    #[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    /// Returns a number that represents the sign of `self`.
496    ///
497    /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
498    /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
499    /// - `NAN` if the number is `NAN`intrinsics
500    #[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    /// Returns a number composed of the magnitude of `self` and the sign of
511    /// `sign`.
512    ///
513    /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
514    /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
515    /// `sign` is returned.
516    #[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    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
523    /// error, yielding a more accurate result than an unfused multiply-add.
524    ///
525    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
526    /// the target architecture has a dedicated `fma` CPU instruction. However,
527    /// this is not always true, and will be heavily dependant on designing
528    /// algorithms with specific target hardware in mind.
529    #[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    /// Calculates Euclidean division, the matching method for `rem_euclid`.
540    ///
541    /// This computes the integer `n` such that
542    /// `self = n * rhs + self.rem_euclid(rhs)`.
543    /// In other words, the result is `self / rhs` rounded to the integer `n`
544    /// such that `self >= n * rhs`.
545    #[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    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
556    ///
557    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
558    /// most cases. However, due to a floating point round-off error it can
559    /// result in `r == rhs.abs()`, violating the mathematical definition, if
560    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
561    /// This result is not an element of the function's codomain, but it is the
562    /// closest floating point number in the real numbers and thus fulfills the
563    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
564    /// approximatively.
565    #[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    /// Raises a number to an integer power.
577    ///
578    /// Using this function is generally faster than using `powf`intrinsics
579    #[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    /// Raises a number to a floating point power.
586    #[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    /// Returns the square root of a number.
597    ///
598    /// Returns NaN if `self` is a negative number other than `-0.0`.
599    #[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    /// Returns `e^(self)`, (the exponential function).
606    #[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    /// Returns `2^(self)`.
613    #[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    /// Returns the natural logarithm of the number.
620    #[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    /// Returns the logarithm of the number with respect to an arbitrary base.
631    ///
632    /// The result might not be correctly rounded owing to implementation details;
633    /// `self.log2()` can produce more accurate results for base 2, and
634    /// `self.log10()` can produce more accurate results for base 10.
635    #[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    /// Returns the base 2 logarithm of the number.
642    #[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    /// Returns the base 10 logarithm of the number.
649    #[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    /// Returns the cube root of a number.
656    #[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    /// Calculates the length of the hypotenuse of a right-angle triangle given
663    /// legs of length `x` and `y`.
664    #[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    /// Computes the sine of a number (in radians).
671    #[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    /// Computes the cosine of a number (in radians).
678    #[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    /// Computes the tangent of a number (in radians).
685    #[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    /// Computes the arcsine of a number. Return value is in radians in
692    /// the range [-pi/2, pi/2] or NaN if the number is outside the range
693    /// [-1, 1].
694    #[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    /// Computes the arccosine of a number. Return value is in radians in
701    /// the range [0, pi] or NaN if the number is outside the range
702    /// [-1, 1].
703    #[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    /// Computes the arctangent of a number. Return value is in radians in the
710    /// range [-pi/2, pi/2];intrinsics
711    #[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    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
718    ///
719    /// * `x = 0`, `y = 0`: `0`
720    /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
721    /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
722    /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`intrinsics
723    #[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    /// Simultaneously computes the sine and cosine of the number, `x`. Returns
730    /// `(sin(x), cos(x))`.
731    #[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    /// Returns `e^(self) - 1` in a way that is accurate even if the
748    /// number is close to zero.
749    #[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    /// Returns `ln(1+n)` (natural logarithm) more accurately than if
760    /// the operations were performed separately.
761    #[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    /// Hyperbolic sine function.
772    #[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    /// Hyperbolic cosine function.
779    #[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    /// Hyperbolic tangent function.
786    #[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    /// Inverse hyperbolic sine function.
793    #[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    /// Inverse hyperbolic cosine function.
800    #[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    /// Inverse hyperbolic tangent function.
807    #[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}