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}