fpmath/
lib.rs

1#![warn(
2    rust_2018_idioms,
3    trivial_casts,
4    trivial_numeric_casts,
5    unreachable_pub,
6    unused_qualifications
7)]
8#![no_std]
9
10//! A pure-Rust floating point math library with support for native floating
11//! point and soft-floats.
12//!
13//! This crate is `no_std`.
14//!
15//! The following math functions are implemented:
16//!
17//! * Sign operations ([`abs`], [`copysign`]).
18//! * Rounding ([`round`], [`trunc`], [`ceil`], [`floor`]).
19//! * Exponential ([`exp`], [`exp_m1`], [`exp2`], [`exp10`]).
20//! * Logarithmic ([`log`], [`log_1p`], [`log2`], [`log10`]).
21//! * Power ([`pow`], [`powi`]).
22//! * Trigonometric
23//!   - Radians ([`sin`], [`cos`], [`sin_cos`], [`tan`]).
24//!   - Degrees ([`sind`], [`cosd`], [`sind_cosd`], [`tand`]).
25//!   - Half-revolutions ([`sinpi`], [`cospi`], [`sinpi_cospi`], [`tanpi`]).
26//! * Inverse trigonometric
27//!   - Radians ([`asin`], [`acos`], [`atan`], [`atan2`]).
28//!   - Degrees ([`asind`], [`acosd`], [`atand`], [`atan2d`]).
29//!   - Half-revolutions ([`asinpi`], [`acospi`], [`atanpi`], [`atan2pi`]).
30//! * Hyperbolic ([`sinh`], [`cosh`], [`sinh_cosh`], [`tanh`]).
31//! * Inverse hyperbolic ([`asinh`], [`acosh`], [`atanh`]).
32//! * Gamma ([`tgamma`], [`lgamma`]).
33//!
34//! All functions are implemted for the native floating point types [`prim@f32`]
35//! and [`prim@f64`].
36//!
37//! The soft-float types [`SoftF32`] and [`SoftF64`] are also provided. They
38//! also support all the above functions and provide consistent bit-to-bit
39//! behavior across platforms. They are available when the `soft-float` feature
40//! is enabled (disabled by default).
41//!
42//! The [`FloatMath`] trait is used to identify types that support the math
43//! functions.
44
45// TODO:
46// * Error function and complementary (erf, erfc)
47// * Bessel functions (j0, y0, j1, y1, jn, yn)
48
49// Uncomment to use `dbg!`
50//extern crate std;
51
52macro_rules! horner {
53    ($outer_x:ident, $inner_x:ident, [$coef:expr]) => {
54        $outer_x * $coef
55    };
56    ($outer_x:ident, $inner_x:ident, [$coef0:expr, $($coefs:expr),+]) => {
57        $outer_x * ($coef0 + horner!($inner_x, $inner_x, [$($coefs),+]))
58    };
59}
60
61#[cfg(test)]
62macro_rules! assert_is_nan {
63    ($value:expr) => {{
64        let value = $value;
65        if !$crate::traits::Float::is_nan(value) {
66            panic!("assertion failed: `({value:?}).is_nan()`");
67        }
68    }};
69}
70
71#[cfg(test)]
72macro_rules! assert_total_eq {
73    ($lhs:expr, $rhs:expr) => {
74        let [lhs, rhs] = [$lhs, $rhs];
75        let lhs = $crate::traits::Float::purify(lhs);
76        let rhs = $crate::traits::Float::purify(rhs);
77        let lhs_raw = $crate::traits::Float::to_raw(lhs);
78        let rhs_raw = $crate::traits::Float::to_raw(rhs);
79        if lhs_raw != rhs_raw {
80            panic!("assertion failed: `{lhs:?} == {rhs:?}` (using totalOrder)");
81        }
82    };
83}
84
85mod double;
86mod f32;
87mod f64;
88mod generic;
89mod host_f32;
90mod host_f64;
91mod int;
92#[cfg(feature = "soft-float")]
93mod soft_f32;
94#[cfg(feature = "soft-float")]
95mod soft_f64;
96mod traits;
97
98#[cfg(feature = "soft-float")]
99pub use soft_f32::SoftF32;
100#[cfg(feature = "soft-float")]
101pub use soft_f64::SoftF64;
102
103mod sealed {
104    pub trait SealedMath {}
105}
106
107/// Floating point types with math functions.
108pub trait FloatMath: sealed::SealedMath + Sized {
109    /// See the [`abs`] function.
110    fn abs(x: Self) -> Self;
111
112    /// See the [`copysign`] function.
113    fn copysign(x: Self, y: Self) -> Self;
114
115    /// See the [`round`] function.
116    fn round(x: Self) -> Self;
117
118    /// See the [`trunc`] function.
119    fn trunc(x: Self) -> Self;
120
121    /// See the [`ceil`] function.
122    fn ceil(x: Self) -> Self;
123
124    /// See the [`floor`] function.
125    fn floor(x: Self) -> Self;
126
127    /// See the [`scalbn`] function.
128    fn scalbn(x: Self, y: i32) -> Self;
129
130    /// See the [`frexp`] function.
131    fn frexp(x: Self) -> (Self, i32);
132
133    /// See the [`hypot`] function.
134    fn hypot(x: Self, y: Self) -> Self;
135
136    /// See the [`sqrt`] function.
137    fn sqrt(x: Self) -> Self;
138
139    /// See the [`cbrt`] function.
140    fn cbrt(x: Self) -> Self;
141
142    /// See the [`exp`] function.
143    fn exp(x: Self) -> Self;
144
145    /// See the [`exp_m1`] function.
146    fn exp_m1(x: Self) -> Self;
147
148    /// See the [`exp2`] function.
149    fn exp2(x: Self) -> Self;
150
151    /// See the [`exp10`] function.
152    fn exp10(x: Self) -> Self;
153
154    /// See the [`log`] function.
155    fn log(x: Self) -> Self;
156
157    /// See the [`log_1p`] function.
158    fn log_1p(x: Self) -> Self;
159
160    /// See the [`log2`] function.
161    fn log2(x: Self) -> Self;
162
163    /// See the [`log10`] function.
164    fn log10(x: Self) -> Self;
165
166    /// See the [`pow`] function.
167    fn pow(x: Self, y: Self) -> Self;
168
169    /// See the [`powi`] function.
170    fn powi(x: Self, y: i32) -> Self;
171
172    /// See the [`sin`] function.
173    fn sin(x: Self) -> Self;
174
175    /// See the [`cos`] function.
176    fn cos(x: Self) -> Self;
177
178    /// See the [`sin_cos`] function.
179    fn sin_cos(x: Self) -> (Self, Self);
180
181    /// See the [`tan`] function.
182    fn tan(x: Self) -> Self;
183
184    /// See the [`sind`] function.
185    fn sind(x: Self) -> Self;
186
187    /// See the [`cosd`] function.
188    fn cosd(x: Self) -> Self;
189
190    /// See the [`sind_cosd`] function.
191    fn sind_cosd(x: Self) -> (Self, Self);
192
193    /// See the [`tand`] function.
194    fn tand(x: Self) -> Self;
195
196    /// See the [`sinpi`] function.
197    fn sinpi(x: Self) -> Self;
198
199    /// See the [`cospi`] function.
200    fn cospi(x: Self) -> Self;
201
202    /// See the [`sinpi_cospi`] function.
203    fn sinpi_cospi(x: Self) -> (Self, Self);
204
205    /// See the [`tanpi`] function.
206    fn tanpi(x: Self) -> Self;
207
208    /// See the [`asin`] function.
209    fn asin(x: Self) -> Self;
210
211    /// See the [`acos`] function.
212    fn acos(x: Self) -> Self;
213
214    /// See the [`atan`] function.
215    fn atan(x: Self) -> Self;
216
217    /// See the [`atan2`] function.
218    fn atan2(y: Self, x: Self) -> Self;
219
220    /// See the [`asind`] function.
221    fn asind(x: Self) -> Self;
222
223    /// See the [`acosd`] function.
224    fn acosd(x: Self) -> Self;
225
226    /// See the [`atand`] function.
227    fn atand(x: Self) -> Self;
228
229    /// See the [`atan2d`] function.
230    fn atan2d(y: Self, x: Self) -> Self;
231
232    /// See the [`asinpi`] function.
233    fn asinpi(x: Self) -> Self;
234
235    /// See the [`acospi`] function.
236    fn acospi(x: Self) -> Self;
237
238    /// See the [`atanpi`] function.
239    fn atanpi(x: Self) -> Self;
240
241    /// See the [`atan2pi`] function.
242    fn atan2pi(y: Self, x: Self) -> Self;
243
244    /// See the [`sinh`] function.
245    fn sinh(x: Self) -> Self;
246
247    /// See the [`cosh`] function.
248    fn cosh(x: Self) -> Self;
249
250    /// See the [`sinh_cosh`] function.
251    fn sinh_cosh(x: Self) -> (Self, Self);
252
253    /// See the [`tanh`] function.
254    fn tanh(x: Self) -> Self;
255
256    /// See the [`asinh`] function.
257    fn asinh(x: Self) -> Self;
258
259    /// See the [`acosh`] function.
260    fn acosh(x: Self) -> Self;
261
262    /// See the [`atanh`] function.
263    fn atanh(x: Self) -> Self;
264
265    /// See the [`tgamma`] function.
266    fn tgamma(x: Self) -> Self;
267
268    /// See the [`lgamma`] function.
269    fn lgamma(x: Self) -> (Self, i8);
270}
271
272/// Calculates the absolute value of `x`
273#[inline]
274pub fn abs<F: FloatMath>(x: F) -> F {
275    F::abs(x)
276}
277
278/// Returns a value with the magnitude of `x` and the sign of `y`
279#[inline]
280pub fn copysign<F: FloatMath>(x: F, y: F) -> F {
281    F::copysign(x, y)
282}
283
284/// Rounds `x` to the nearest integer, ties round away from zero
285pub fn round<F: FloatMath>(x: F) -> F {
286    F::round(x)
287}
288
289/// Rounds `x` to the nearest integer that is not greater in magnitude than `x`
290pub fn trunc<F: FloatMath>(x: F) -> F {
291    F::trunc(x)
292}
293
294/// Rounds `x` to the nearest integer that is not less than `x`
295pub fn ceil<F: FloatMath>(x: F) -> F {
296    F::ceil(x)
297}
298
299/// Rounds `x` to the nearest integer that is not greater than `x`
300pub fn floor<F: FloatMath>(x: F) -> F {
301    F::floor(x)
302}
303
304/// Calculates `x` times two raised to `y`.
305pub fn scalbn<F: FloatMath>(x: F, y: i32) -> F {
306    F::scalbn(x, y)
307}
308
309/// Splits `x` into mantissa and exponent.
310///
311/// Returns `(m, e)` such as:
312/// * `0.5 <= m < 1.0`
313/// * `x = m * 2^e`
314///
315/// When `x` is zero, infinity or NaN, returns `x` as mantissa and zero as
316/// exponent.
317pub fn frexp<F: FloatMath>(x: F) -> (F, i32) {
318    F::frexp(x)
319}
320
321/// Calculates the Pythagorean addition of `x` and `y` with and error of less
322/// than 1 ULP
323///
324/// The Pythagorean addition of `x` and `y` is equal to the length of the
325/// hypotenuse of a triangle with sides of length `x` and `y`.
326///
327/// Special cases:
328/// * Returns positive infinity if `x` or `y` is infinity
329/// * Returns NaN if `x` or `y` is NaN and neither is infinity
330pub fn hypot<F: FloatMath>(x: F, y: F) -> F {
331    F::hypot(x, y)
332}
333
334/// Calculates the square root of `x` with an error of less than 0.5 ULP.
335///
336/// Special cases:
337/// * Returns negative zero if `x` is negative zero
338/// * Returns positive infinity if `x` is positive infinity
339/// * Returns NaN if `x` is NaN or negative non-zero (including infinity)
340pub fn sqrt<F: FloatMath>(x: F) -> F {
341    F::sqrt(x)
342}
343
344/// Calculates the cube root of `x` with and error of less than 1 ULP.
345///
346/// Special cases:
347/// * Returns negative zero if `x` is negative zero
348/// * Returns positive infinity if `x` is positive infinity
349/// * Returns negative infinity if `x` is negative infinity
350/// * Returns NaN if `x` is NaN
351pub fn cbrt<F: FloatMath>(x: F) -> F {
352    F::cbrt(x)
353}
354
355/// Calculates Euler's number raised to `x` with an error of less than 1 ULP
356///
357/// Special cases:
358/// * Returns positive infinity if `x` is positive infinity
359/// * Returns zero if `x` is negative infinity
360/// * Returns NaN if `x` is NaN
361pub fn exp<F: FloatMath>(x: F) -> F {
362    F::exp(x)
363}
364
365/// Calculates `exp(x) - 1.0` with an error of less than 1 ULP
366///
367/// Special cases:
368/// * Returns negative zero if `x` is negative zero
369/// * Returns positive infinity if `x` is positive infinity
370/// * Returns minus one if `x` is negative infinity
371/// * Returns NaN if `x` is NaN
372pub fn exp_m1<F: FloatMath>(x: F) -> F {
373    F::exp_m1(x)
374}
375
376/// Calculates 2 raised to `x` with an error of less than 1 ULP
377///
378/// Special cases:
379/// * Returns positive infinity if `x` is positive infinity
380/// * Returns zero if `x` is negative infinity
381/// * Returns NaN if `x` is NaN
382pub fn exp2<F: FloatMath>(x: F) -> F {
383    F::exp2(x)
384}
385
386/// Calculates 10 raised to `x` with an error of less than 1 ULP
387///
388/// Special cases:
389/// * Returns positive infinity if `x` is positive infinity
390/// * Returns zero if `x` is negative infinity
391/// * Returns NaN if `x` is NaN
392pub fn exp10<F: FloatMath>(x: F) -> F {
393    F::exp10(x)
394}
395
396/// Calculates the natural logarithm of `x` with an error of less than 1 ULP
397///
398/// Special cases:
399/// * Returns negative infinity if `x` is positive or negative zero
400/// * Returns positive infinity if `x` is positive infinity
401/// * Returns NaN if `x` is NaN or negative non-zero (including infinity)
402pub fn log<F: FloatMath>(x: F) -> F {
403    F::log(x)
404}
405
406/// Calculates the natural logarithm of `x + 1` with an error of less than 1 ULP
407///
408/// Special cases:
409/// * Returns negative zero if `x` is negative zero
410/// * Returns negative infinity if `x` is minus one
411/// * Returns positive infinity if `x` is positive infinity
412/// * Returns NaN if `x` is NaN or less than minus one (including negative
413///   infinity)
414pub fn log_1p<F: FloatMath>(x: F) -> F {
415    F::log_1p(x)
416}
417
418/// Calculates the base-2 logarithm of `x` with an error of less than 1 ULP
419///
420/// Special cases:
421/// * Returns negative infinity if `x` is positive or negative zero
422/// * Returns positive infinity if `x` is positive infinity
423/// * Returns NaN if `x` is NaN or negative non-zero (including infinity)
424pub fn log2<F: FloatMath>(x: F) -> F {
425    F::log2(x)
426}
427
428/// Calculates the base-10 logarithm of `x` with an error of less than 1 ULP
429///
430/// Special cases:
431/// * Returns negative infinity if `x` is positive or negative zero
432/// * Returns positive infinity if `x` is positive infinity
433/// * Returns NaN if `x` is NaN or negative non-zero (including infinity)
434pub fn log10<F: FloatMath>(x: F) -> F {
435    F::log10(x)
436}
437
438/// Calculates `x` raised to `y` with an error of less than 1 ULP
439///
440/// Special cases:
441/// * Returns 1 when `x` is 1 or `y` is zero
442/// * Returns 1 when `x` is -1 and `y` is positive or negative infinity
443/// * Returns NaN when `x` is NaN and `y` is not zero
444/// * Returns NaN when `y` is NaN and `z` is not 1
445/// * Returns positive zero when `x` is positive zero and `y` is positive
446/// * Returns positive zero when `x` is positive infinity and `y` is negative
447/// * Returns positive infinity when `x` is positive infinity and `y` is
448///   positive
449/// * Returns positive infinity when `x` is positive zero and `y` is negative
450/// * Returns positive zero when `x` is negative zero and `y` is positive and
451///   not an odd integer
452/// * Returns positive zero when `x` is negative infinity and `y` is negative
453///   and not an odd integer
454/// * Returns positive infinity when `x` is negative infinity and `y` is
455///   positive and not an odd integer
456/// * Returns positive infinity when `x` is negative zero and `y` is negative
457///   and not an odd integer
458/// * Returns negative zero when `x` is negative zero and `y` is positive and an
459///   odd integer
460/// * Returns negative zero when `x` is negative infinity and `y` is negative
461///   and an odd integer
462/// * Returns negative infinity when `x` is negative infinity and `y` is
463///   positive and an odd integer
464/// * Returns negative infinity when `x` is negative zero and `y` is negative
465///   and an odd integer
466/// * Returns positive zero when the absolute value of `x` is less than one and
467///   `y` is positive infinity
468/// * Returns positive zero when the absolute value of `x` is greater than one
469///   and `y` is negative infinity
470/// * Returns positive infinity when the absolute value of `x` is less than one
471///   and `y` is negative infinity
472/// * Returns positive infinity when the absolute value of `x` is greater than
473///   one and `y` is positive infinity
474/// * Returns NaN when `x` is negative and `y` is finite and not integer
475pub fn pow<F: FloatMath>(x: F, y: F) -> F {
476    F::pow(x, y)
477}
478
479/// Calculates `x` raised to `y` with an error of less than 1 ULP
480///
481/// Special cases:
482/// * Returns 1 when `x` is 1 or `y` is zero
483/// * Returns NaN when `x` is NaN and `y` is not zero
484/// * Returns NaN when `y` is NaN and `z` is not 1
485/// * Returns positive zero when `x` is positive zero and `y` is positive
486/// * Returns positive zero when `x` is positive infinity and `y` is negative
487/// * Returns positive infinity when `x` is positive infinity and `y` is
488///   positive
489/// * Returns positive infinity when `x` is positive zero and `y` is negative
490/// * Returns positive zero when `x` is negative zero and `y` is positive and
491///   even
492/// * Returns positive zero when `x` is negative infinity and `y` is negative
493///   and even
494/// * Returns positive infinity when `x` is negative infinity and `y` is
495///   positive and even
496/// * Returns positive infinity when `x` is negative zero and `y` is negative
497///   and even
498/// * Returns negative zero when `x` is negative zero and `y` is positive and
499///   odd
500/// * Returns negative zero when `x` is negative infinity and `y` is negative
501///   and odd
502/// * Returns negative infinity when `x` is negative infinity and `y` is
503///   positive and odd
504/// * Returns negative infinity when `x` is negative zero and `y` is negative
505///   and odd
506pub fn powi<F: FloatMath>(x: F, y: i32) -> F {
507    F::powi(x, y)
508}
509
510/// Calculates the sine of `x` radians with an error of less than 1 ULP
511///
512/// Special cases:
513/// * Returns negative zero if `x` is negative zero
514/// * Returns NaN if `x` is infinity or NaN
515pub fn sin<F: FloatMath>(x: F) -> F {
516    F::sin(x)
517}
518
519/// Calculates the cosine of `x` radians with an error of less than 1 ULP
520///
521/// Special cases:
522/// * Returns NaN if `x` is infinity or NaN
523pub fn cos<F: FloatMath>(x: F) -> F {
524    F::cos(x)
525}
526
527/// Calculates the sine and the cosine of `x` radians
528///
529/// The same accuracy and special cases of [`sin`] and [`cos`] also
530/// apply to this function. Using this function can be faster than
531/// using [`sin`] and [`cos`] separately.
532pub fn sin_cos<F: FloatMath>(x: F) -> (F, F) {
533    F::sin_cos(x)
534}
535
536/// Calculates the tangent of `x` radians with an error of less than 1 ULP
537///
538/// Special cases:
539/// * Returns negative zero if `x` is negative zero
540/// * Returns NaN if `x` is infinity or NaN
541pub fn tan<F: FloatMath>(x: F) -> F {
542    F::tan(x)
543}
544
545/// Calculates the sine of `x` degrees with an error of less than 1 ULP
546///
547/// Special cases:
548/// * Returns negative zero if `x` is negative zero
549/// * Returns NaN if `x` is infinity or NaN
550pub fn sind<F: FloatMath>(x: F) -> F {
551    F::sind(x)
552}
553
554/// Calculates the cosine of `x` degrees with an error of less than 1 ULP
555///
556/// Special cases:
557/// * Returns NaN if `x` is infinity or NaN
558pub fn cosd<F: FloatMath>(x: F) -> F {
559    F::cosd(x)
560}
561
562/// Calculates the sine and the cosine of `x` degrees
563///
564/// The same accuracy and special cases of [`sind`] and [`cosd`] also apply to
565/// this function. Using this function can be faster than using [`sind`] and
566/// [`cosd`] separately.
567pub fn sind_cosd<F: FloatMath>(x: F) -> (F, F) {
568    F::sind_cosd(x)
569}
570
571/// Calculates the tangent of `x` degrees with an error of less than 1 ULP
572///
573/// Special cases:
574/// * Returns negative zero if `x` is negative zero
575/// * Returns NaN if `x` is infinity or NaN
576pub fn tand<F: FloatMath>(x: F) -> F {
577    F::tand(x)
578}
579
580/// Calculates the sine of `x` half-revolutions with an error of less
581/// than 1 ULP
582///
583/// Special cases:
584/// * Returns negative zero if `x` is negative zero
585/// * Returns NaN if `x` is infinity or NaN
586pub fn sinpi<F: FloatMath>(x: F) -> F {
587    F::sinpi(x)
588}
589
590/// Calculates the cosine of `x` half-revolutions with an error of
591/// less than 1 ULP
592///
593/// Special cases:
594/// * Returns NaN if `x` is infinity or NaN
595pub fn cospi<F: FloatMath>(x: F) -> F {
596    F::cospi(x)
597}
598
599/// Calculates the sine and the cosine of `x` half-revolutions
600///
601/// The same accuracy and special cases of [`sinpi`] and [`cospi`] also apply to
602/// this function. Using this function can be faster than using [`sinpi`] and
603/// [`cospi`] separately.
604pub fn sinpi_cospi<F: FloatMath>(x: F) -> (F, F) {
605    F::sinpi_cospi(x)
606}
607
608/// Calculates the tangent of `x` half-revolutions with an error of less than 1
609/// ULP
610///
611/// Special cases:
612/// * Returns negative zero if `x` is negative zero
613/// * Returns NaN if `x` is infinity or NaN
614pub fn tanpi<F: FloatMath>(x: F) -> F {
615    F::tanpi(x)
616}
617
618/// Calculates the arcsine of `x`, returning the result in radians, with an
619/// error of less than 1 ULP
620///
621/// Special cases:
622/// * Returns negative zero if `x` is negative zero
623/// * Returns NaN if `x` is NaN or greater than one in magnitude (including
624///   infinity)
625pub fn asin<F: FloatMath>(x: F) -> F {
626    F::asin(x)
627}
628
629/// Calculates the arccosine of `x`, returning the result in radians, with an
630/// error of less than 1 ULP
631///
632/// Special cases:
633/// * Returns NaN if `x` is NaN or greater than one in magnitude (including
634///   infinity)
635pub fn acos<F: FloatMath>(x: F) -> F {
636    F::acos(x)
637}
638
639/// Calculates the arctangent of `x`, returning the result in radians,
640/// with an error of less than 1 ULP
641///
642/// Special cases:
643/// * Returns negative zero if `x` is negative zero
644/// * Returns NaN if `x` is NaN
645/// * Returns π/2 if `x` is positive infinity
646/// * Returns -π/2 if `x` is negative infinity
647pub fn atan<F: FloatMath>(x: F) -> F {
648    F::atan(x)
649}
650
651/// Calculates the 2-argument arctangent of `x` and 'y', returning the
652/// result in radians with an error of less than 1 ULP
653///
654/// Special cases:
655/// * Returns NaN if `x` is NaN or `y` is NaN
656/// * Returns positive zero if `y` is positive zero `x` is positive (zero,
657///   finite or infinity)
658/// * Returns negative zero if `y` is negative zero `x` is positive (zero,
659///   finite or infinity)
660/// * Returns π if `y` is positive zero `x` is positive (zero, finite or
661///   infinity)
662/// * Returns -π if `y` is negative zero `x` is negative (zero, finite or
663///   infinity)
664/// * Returns π/2 if `y` is positive infinity and `x` is zero or finite
665/// * Returns -π/2 if `y` is negative infinity and `x` is zero or finite
666/// * Returns positive zero if `x` is positive infinity and `y` is positive
667///   (zero or finite)
668/// * Returns negative zero if `x` is positive infinity and `y` is negative
669///   (zero or finite)
670/// * Returns π if `x` is negative infinity and `y` is positive (zero or finite)
671/// * Returns -π if `x` is negative infinity and `y` is negative (zero or
672///   finite)
673/// * Returns π/4 if `x` is positive infinity and `y` is positive infinity
674/// * Returns -π/4 if `x` is positive infinity and `y` is negative infinity
675/// * Returns 3π/4 if `x` is negative infinity and `y` is positive infinity
676/// * Returns -3π/4 if `x` is negative infinity and `y` is negative infinity
677pub fn atan2<F: FloatMath>(y: F, x: F) -> F {
678    F::atan2(y, x)
679}
680
681/// Calculates the arcsine of `x`, returning the result in degrees, with an
682/// error of less than 1 ULP
683///
684/// Special cases:
685/// * Returns negative zero if `x` is negative zero
686/// * Returns NaN if `x` is NaN or greater than one in magnitude (including
687///   infinity)
688pub fn asind<F: FloatMath>(x: F) -> F {
689    F::asind(x)
690}
691
692/// Calculates the arccosine of `x`, returning the result in degrees, with an
693/// error of less than 1 ULP
694///
695/// Special cases:
696/// * Returns NaN if `x` is NaN or greater than one in magnitude (including
697///   infinity)
698pub fn acosd<F: FloatMath>(x: F) -> F {
699    F::acosd(x)
700}
701
702/// Calculates the arctangent of `x`, returning the result in degrees, with an
703/// error of less than 1 ULP
704///
705/// Special cases:
706/// * Returns negative zero if `x` is negative zero
707/// * Returns NaN if `x` is NaN
708/// * Returns 90 if `x` is positive infinity
709/// * Returns -90 if `x` is negative infinity
710pub fn atand<F: FloatMath>(x: F) -> F {
711    F::atand(x)
712}
713
714/// Calculates the 2-argument arctangent of `x` and 'y', returning the result in
715/// degrees, with an error of less than 1 ULP
716///
717/// Special cases:
718/// * Returns NaN if `x` is NaN or `y` is NaN
719/// * Returns positive zero if `y` is positive zero `x` is positive (zero,
720///   finite or infinity)
721/// * Returns negative zero if `y` is negative zero `x` is positive (zero,
722///   finite or infinity)
723/// * Returns 180 if `y` is positive zero `x` is positive (zero, finite or
724///   infinity)
725/// * Returns -180 if `y` is negative zero `x` is negative (zero, finite or
726///   infinity)
727/// * Returns 90 if `y` is positive infinity and `x` is zero or finite
728/// * Returns -90 if `y` is negative infinity and `x` is zero or finite
729/// * Returns positive zero if `x` is positive infinity and `y` is positive
730///   (zero or finite)
731/// * Returns negative zero if `x` is positive infinity and `y` is negative
732///   (zero or finite)
733/// * Returns 180 if `x` is negative infinity and `y` is positive (zero or
734///   finite)
735/// * Returns -180 if `x` is negative infinity and `y` is negative (zero or
736///   finite)
737/// * Returns 45 if `x` is positive infinity and `y` is positive infinity
738/// * Returns -45 if `x` is positive infinity and `y` is negative infinity
739/// * Returns 135 if `x` is negative infinity and `y` is positive infinity
740/// * Returns -135 if `x` is negative infinity and `y` is negative infinity
741pub fn atan2d<F: FloatMath>(y: F, x: F) -> F {
742    F::atan2d(y, x)
743}
744
745/// Calculates the arcsine of `x`, returning the result in half-revolutions,
746/// with an error of less than 1 ULP
747///
748/// Special cases:
749/// * Returns negative zero if `x` is negative zero
750/// * Returns NaN if `x` is NaN or greater than one in magnitude (including
751///   infinity)
752pub fn asinpi<F: FloatMath>(x: F) -> F {
753    F::asinpi(x)
754}
755
756/// Calculates the arccosine of `x`, returning the result in half-revolutions,
757/// with an error of less than 1 ULP
758///
759/// Special cases:
760/// * Returns NaN if `x` is NaN or greater than one in magnitude (including
761///   infinity)
762pub fn acospi<F: FloatMath>(x: F) -> F {
763    F::acospi(x)
764}
765
766/// Calculates the arctangent of `x`, returning the result in half-revolutions,
767/// with an error of less than 1 ULP
768///
769/// Special cases:
770/// * Returns negative zero if `x` is negative zero
771/// * Returns NaN if `x` is NaN
772/// * Returns 0.5 if `x` is positive infinity
773/// * Returns -0.5 if `x` is negative infinity
774pub fn atanpi<F: FloatMath>(x: F) -> F {
775    F::atanpi(x)
776}
777
778/// Calculates the 2-argument arctangent of `x` and 'y', returning the result in
779/// half-revolutions, with an error of less than 1 ULP
780///
781/// Special cases:
782/// * Returns NaN if `x` is NaN or `y` is NaN
783/// * Returns positive zero if `y` is positive zero `x` is positive (zero,
784///   finite or infinity)
785/// * Returns negative zero if `y` is negative zero `x` is positive (zero,
786///   finite or infinity)
787/// * Returns 1 if `y` is positive zero `x` is positive (zero, finite or
788///   infinity)
789/// * Returns -1 if `y` is negative zero `x` is negative (zero, finite or
790///   infinity)
791/// * Returns 0.5 if `y` is positive infinity and `x` is zero or finite
792/// * Returns -0.5 if `y` is negative infinity and `x` is zero or finite
793/// * Returns positive zero if `x` is positive infinity and `y` is positive
794///   (zero or finite)
795/// * Returns negative zero if `x` is positive infinity and `y` is negative
796///   (zero or finite)
797/// * Returns 1 if `x` is negative infinity and `y` is positive (zero or finite)
798/// * Returns -1 if `x` is negative infinity and `y` is negative (zero or
799///   finite)
800/// * Returns 0.25 if `x` is positive infinity and `y` is positive infinity
801/// * Returns -0.25 if `x` is positive infinity and `y` is negative infinity
802/// * Returns 0.75 if `x` is negative infinity and `y` is positive infinity
803/// * Returns -0.75 if `x` is negative infinity and `y` is negative infinity
804pub fn atan2pi<F: FloatMath>(y: F, x: F) -> F {
805    F::atan2pi(y, x)
806}
807
808/// Calculates the hyperbolic sine of `x` with an error of less than 1 ULP
809///
810/// Special cases:
811/// * Returns negative zero if `x` is negative zero
812/// * Returns positive infinity if `x` is positive infinity
813/// * Returns negative infinity if `x` is negative infinity
814/// * Returns NaN if `x` is NaN
815pub fn sinh<F: FloatMath>(x: F) -> F {
816    F::sinh(x)
817}
818
819/// Calculates the hyperbolic cosine of `x` with an error of less than 1 ULP
820///
821/// Special cases:
822/// * Returns positive infinity if `x` is positive or negative infinity
823/// * Returns NaN if `x` is NaN
824pub fn cosh<F: FloatMath>(x: F) -> F {
825    F::cosh(x)
826}
827
828/// Calculates the hyerbolic sine and hyerbolic cosine of `x`
829///
830/// The same accuracy and special cases of [`sinh`] and [`cosh`] also apply to
831/// this function. Using this function can be faster than using [`sinh`] and
832/// [`cosh`] separately.
833pub fn sinh_cosh<F: FloatMath>(x: F) -> (F, F) {
834    F::sinh_cosh(x)
835}
836
837/// Calculates the hyperbolic tangent of `x` with an error of less than 1 ULP
838///
839/// Special cases:
840/// * Returns negative zero if `x` is negative zero
841/// * Returns one if `x` is positive infinity
842/// * Returns minus one if `x` is negative infinity
843/// * Returns NaN if `x` is NaN
844pub fn tanh<F: FloatMath>(x: F) -> F {
845    F::tanh(x)
846}
847
848/// Calculates the hyperbolic arcsine of `x` with an error of less than 1 ULP
849///
850/// Special cases:
851/// * Returns NaN if `x` is NaN
852/// * Returns negative zero if `x` is negative zero
853/// * Returns positive infinity if `x` is positive infinity
854/// * Returns negative infinity if `x` is negative infinity
855pub fn asinh<F: FloatMath>(x: F) -> F {
856    F::asinh(x)
857}
858
859/// Calculates the hyperbolic arccosine of `x` with an error of less than 1 ULP
860///
861/// Special cases:
862/// * Returns NaN if `x` is NaN or less than one (including negative infinity)
863/// * Returns positive infinity if `x` is positive infinity
864pub fn acosh<F: FloatMath>(x: F) -> F {
865    F::acosh(x)
866}
867
868/// Calculates the hyperbolic arctangent of `x` with an error of less than 1 ULP
869///
870/// Special cases:
871/// * Returns NaN if `x` is NaN or greater than 1 in magnitude
872/// * Returns negative zero if `x` is negative zero
873/// * Returns positive infinity if `x` is 1
874/// * Returns negative infinity if `x` is -1
875pub fn atanh<F: FloatMath>(x: F) -> F {
876    F::atanh(x)
877}
878
879/// Calculates the gamma function of `x`
880///
881/// When `x` is greater than 0.5, the error is less than 1 ULP, otherwise the
882/// error is less than 2 ULP.
883///
884/// Special cases:
885/// * Returns NaN if `x` is NaN, negative infinity or a negative integer
886/// * Returns positive infinity if `x` is positive infinity
887/// * Returns positive infinity if `x` is positive zero
888/// * Returns negative infinity if `x` is negative zero
889pub fn tgamma<F: FloatMath>(x: F) -> F {
890    F::tgamma(x)
891}
892
893/// Calculates the logarithm of the absolute value of the gamma function of `x`
894///
895/// The integer field of the returned tuple is `1` when the gamma function of
896/// `x` is positive, `-1` when the gamma function of `x` is negative, and `0`
897/// when the sign of the gamma function of `x` is not defined.
898///
899/// The error is less than 2 ULP in most cases. However, for some negative
900/// values of `x`, the error can be in the order of 200 ULP.
901///
902/// Special cases:
903/// * Returns NaN if `x` is NaN or negative infinity
904/// * Returns positive infinity if `x` is positive infinity
905/// * Returns positive infinity if `x` is zero or a negative integer
906///
907/// The sign is considered undefined when `x` is NaN, a negative integer or
908/// negative infinity.
909pub fn lgamma<F: FloatMath>(x: F) -> (F, i8) {
910    F::lgamma(x)
911}