core_maths/
lib.rs

1//! Extension trait for full float functionality in `#[no_std]` backed by [`libm`].
2//!
3//! Method signatures, implementation, and documentation are copied from as `std` 1.72,
4//! with calls to instrinsics replaced by their `libm` equivalents.
5//!
6//! # Usage
7//! ```rust
8//! #[allow(unused_imports)] // will be unused on std targets
9//! use core_maths::*;
10//!
11//! 3.9.floor();
12//! ```
13
14#![no_std]
15#![warn(missing_docs)]
16
17/// See [`crate`].
18pub trait CoreFloat: Sized + Copy {
19    /// Returns the largest integer less than or equal to `self`.
20    ///
21    /// This implementation uses `libm` instead of the Rust intrinsic.
22    ///
23    /// # Examples
24    ///
25    /// ```
26    /// use core_maths::*;
27    /// let f = 3.7_f64;
28    /// let g = 3.0_f64;
29    /// let h = -3.7_f64;
30    ///
31    /// assert_eq!(CoreFloat::floor(f), 3.0);
32    /// assert_eq!(CoreFloat::floor(g), 3.0);
33    /// assert_eq!(CoreFloat::floor(h), -4.0);
34    /// ```
35    fn floor(self) -> Self;
36
37    /// Returns the smallest integer greater than or equal to `self`.
38    ///
39    /// This implementation uses `libm` instead of the Rust intrinsic.
40    ///
41    /// # Examples
42    ///
43    /// ```
44    /// use core_maths::*;
45    /// let f = 3.01_f64;
46    /// let g = 4.0_f64;
47    ///
48    /// assert_eq!(CoreFloat::ceil(f), 4.0);
49    /// assert_eq!(CoreFloat::ceil(g), 4.0);
50    /// ```
51    fn ceil(self) -> Self;
52
53    /// Returns the nearest integer to `self`. If a value is half-way between two
54    /// integers, round away from `0.0`.
55    ///
56    /// This implementation uses `libm` instead of the Rust intrinsic.
57    ///
58    /// # Examples
59    ///
60    /// ```
61    /// use core_maths::*;
62    /// let f = 3.3_f64;
63    /// let g = -3.3_f64;
64    /// let h = -3.7_f64;
65    /// let i = 3.5_f64;
66    /// let j = 4.5_f64;
67    ///
68    /// assert_eq!(CoreFloat::round(f), 3.0);
69    /// assert_eq!(CoreFloat::round(g), -3.0);
70    /// assert_eq!(CoreFloat::round(h), -4.0);
71    /// assert_eq!(CoreFloat::round(i), 4.0);
72    /// assert_eq!(CoreFloat::round(j), 5.0);
73    /// ```
74    fn round(self) -> Self;
75
76    /// Returns the integer part of `self`.
77    /// This means that non-integer numbers are always truncated towards zero.
78    ///
79    /// This implementation uses `libm` instead of the Rust intrinsic.
80    ///
81    /// # Examples
82    ///
83    /// ```
84    /// use core_maths::*;
85    /// let f = 3.7_f64;
86    /// let g = 3.0_f64;
87    /// let h = -3.7_f64;
88    ///
89    /// assert_eq!(CoreFloat::trunc(f), 3.0);
90    /// assert_eq!(CoreFloat::trunc(g), 3.0);
91    /// assert_eq!(CoreFloat::trunc(h), -3.0);
92    /// ```
93    fn trunc(self) -> Self;
94
95    /// Returns the fractional part of `self`.
96    ///
97    /// This implementation uses `libm` instead of the Rust intrinsic.
98    ///
99    /// # Examples
100    ///
101    /// ```
102    /// use core_maths::*;
103    /// let x = 3.6_f64;
104    /// let y = -3.6_f64;
105    /// let abs_difference_x = (CoreFloat::fract(x) - CoreFloat::abs(0.6));
106    /// let abs_difference_y = (CoreFloat::fract(y) - CoreFloat::abs(-0.6));
107    ///
108    /// assert!(abs_difference_x < 1e-10);
109    /// assert!(abs_difference_y < 1e-10);
110    /// ```
111    fn fract(self) -> Self;
112
113    /// Computes the absolute value of `self`.
114    ///
115    /// This implementation uses `libm` instead of the Rust intrinsic.
116    ///
117    /// # Examples
118    ///
119    /// ```
120    /// use core_maths::*;
121    /// let x = 3.5_f64;
122    /// let y = -3.5_f64;
123    ///
124    /// let abs_difference_x = (CoreFloat::abs(x) - CoreFloat::abs(x));
125    /// let abs_difference_y = (CoreFloat::abs(y) - (CoreFloat::abs(-y)));
126    ///
127    /// assert!(abs_difference_x < 1e-10);
128    /// assert!(abs_difference_y < 1e-10);
129    ///
130    /// assert!(f64::NAN.abs().is_nan());
131    /// ```
132    fn abs(self) -> Self;
133
134    /// Returns a number that represents the sign of `self`.
135    ///
136    /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
137    /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
138    /// - NaN if the number is NaN
139    ///
140    /// This method does not use an intrinsic in `std`, so its code is copied.
141    ///
142    /// # Examples
143    ///
144    /// ```
145    /// use core_maths::*;
146    /// let f = 3.5_f64;
147    ///
148    /// assert_eq!(CoreFloat::signum(f), 1.0);
149    /// assert_eq!(CoreFloat::signum(f64::NEG_INFINITY), -1.0);
150    ///
151    /// assert!(CoreFloat::signum(f64::NAN).is_nan());
152    /// ```
153    fn signum(self) -> Self;
154
155    /// Returns a number composed of the magnitude of `self` and the sign of
156    /// `sign`.
157    ///
158    /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
159    /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of
160    /// `sign` is returned. Note, however, that conserving the sign bit on NaN
161    /// across arithmetical operations is not generally guaranteed.
162    /// See [explanation of NaN as a special value](primitive@f32) for more info.
163    ///
164    /// This implementation uses `libm` instead of the Rust intrinsic.
165    ///
166    /// # Examples
167    ///
168    /// ```
169    /// use core_maths::*;
170    /// let f = 3.5_f64;
171    ///
172    /// assert_eq!(CoreFloat::copysign(f, 0.42), 3.5_f64);
173    /// assert_eq!(CoreFloat::copysign(f, -0.42), -3.5_f64);
174    /// assert_eq!(CoreFloat::copysign(-f, 0.42), 3.5_f64);
175    /// assert_eq!(CoreFloat::copysign(-f, -0.42), -3.5_f64);
176    ///
177    /// assert!(CoreFloat::copysign(f64::NAN, 1.0).is_nan());
178    /// ```
179    fn copysign(self, sign: Self) -> Self;
180
181    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
182    /// error, yielding a more accurate result than an unfused multiply-add.
183    ///
184    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
185    /// the target architecture has a dedicated `fma` CPU instruction. However,
186    /// this is not always true, and will be heavily dependant on designing
187    /// algorithms with specific target hardware in mind.
188    ///
189    /// This implementation uses `libm` instead of the Rust intrinsic.
190    ///
191    /// # Examples
192    ///
193    /// ```
194    /// use core_maths::*;
195    /// let m = 10.0_f64;
196    /// let x = 4.0_f64;
197    /// let b = 60.0_f64;
198    ///
199    /// // 100.0
200    /// let abs_difference = (CoreFloat::mul_add(m, x, b) - ((m * x) + b)).abs();
201    ///
202    /// assert!(abs_difference < 1e-10);
203    /// ```
204    fn mul_add(self, a: Self, b: Self) -> Self;
205
206    /// Calculates Euclidean division, the matching method for `rem_euclid`.
207    ///
208    /// This computes the integer `n` such that
209    /// `self = n * rhs + self.rem_euclid(rhs)`.
210    /// In other words, the result is `self / rhs` rounded to the integer `n`
211    /// such that `self >= n * rhs`.
212    ///
213    /// This method does not use an intrinsic in `std`, so its code is copied.
214    ///
215    /// # Examples
216    ///
217    /// ```
218    /// use core_maths::*;
219    /// let a: f64 = 7.0;
220    /// let b = 4.0;
221    /// assert_eq!(CoreFloat::div_euclid(a, b), 1.0); // 7.0 > 4.0 * 1.0
222    /// assert_eq!(CoreFloat::div_euclid(-a, b), -2.0); // -7.0 >= 4.0 * -2.0
223    /// assert_eq!(CoreFloat::div_euclid(a, -b), -1.0); // 7.0 >= -4.0 * -1.0
224    /// assert_eq!(CoreFloat::div_euclid(-a, -b), 2.0); // -7.0 >= -4.0 * 2.0
225    /// ```
226    fn div_euclid(self, rhs: Self) -> Self;
227
228    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
229    ///
230    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
231    /// most cases. However, due to a floating point round-off error it can
232    /// result in `r == rhs.abs()`, violating the mathematical definition, if
233    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
234    /// This result is not an element of the function's codomain, but it is the
235    /// closest floating point number in the real numbers and thus fulfills the
236    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
237    /// approximately.
238    ///
239    /// This method does not use an intrinsic in `std`, so its code is copied.
240    ///
241    /// # Examples
242    ///
243    /// ```
244    /// use core_maths::*;
245    /// let a: f64 = 7.0;
246    /// let b = 4.0;
247    /// assert_eq!(CoreFloat::rem_euclid(a, b), 3.0);
248    /// assert_eq!(CoreFloat::rem_euclid(-a, b), 1.0);
249    /// assert_eq!(CoreFloat::rem_euclid(a, -b), 3.0);
250    /// assert_eq!(CoreFloat::rem_euclid(-a, -b), 1.0);
251    /// // limitation due to round-off error
252    /// assert!(CoreFloat::rem_euclid(-f64::EPSILON, 3.0) != 0.0);
253    /// ```
254    fn rem_euclid(self, rhs: Self) -> Self;
255
256    /// Raises a number to an integer power.
257    ///
258    /// Using this function is generally faster than using `powf`.
259    /// It might have a different sequence of rounding operations than `powf`,
260    /// so the results are not guaranteed to agree.
261    ///
262    /// This method is not available in `libm`, so it uses a custom implementation.
263    ///
264    /// # Examples
265    ///
266    /// ```
267    /// use core_maths::*;
268    /// let x = 2.0_f64;
269    /// let abs_difference = (CoreFloat::powi(x, 2) - (x * x)).abs();
270    ///
271    /// assert!(abs_difference < 1e-10);
272    /// ```
273    fn powi(self, n: i32) -> Self;
274
275    /// Raises a number to a floating point power.
276    ///
277    /// This implementation uses `libm` instead of the Rust intrinsic.
278    ///
279    /// # Examples
280    ///
281    /// ```
282    /// use core_maths::*;
283    /// let x = 2.0_f64;
284    /// let abs_difference = (CoreFloat::powf(x, 2.0) - (x * x)).abs();
285    ///
286    /// assert!(abs_difference < 1e-10);
287    /// ```
288    fn powf(self, n: Self) -> Self;
289
290    /// Returns the square root of a number.
291    ///
292    /// Returns NaN if `self` is a negative number other than `-0.0`.
293    ///
294    /// This implementation uses `libm` instead of the Rust intrinsic.
295    ///
296    /// # Examples
297    ///
298    /// ```
299    /// use core_maths::*;
300    /// let positive = 4.0_f64;
301    /// let negative = -4.0_f64;
302    /// let negative_zero = -0.0_f64;
303    ///
304    /// let abs_difference = (CoreFloat::sqrt(positive) - 2.0).abs();
305    ///
306    /// assert!(abs_difference < 1e-10);
307    /// assert!(CoreFloat::sqrt(negative).is_nan());
308    /// assert!(CoreFloat::sqrt(negative_zero) == negative_zero);
309    /// ```
310    fn sqrt(self) -> Self;
311
312    /// Returns `e^(self)`, (the exponential function).
313    ///
314    /// This implementation uses `libm` instead of the Rust intrinsic.
315    ///
316    /// # Examples
317    ///
318    /// ```
319    /// use core_maths::*;
320    /// let one = 1.0_f64;
321    /// // e^1
322    /// let e = CoreFloat::exp(one);
323    ///
324    /// // ln(e) - 1 == 0
325    /// let abs_difference = (e.ln() - 1.0).abs();
326    ///
327    /// assert!(abs_difference < 1e-10);
328    /// ```
329    fn exp(self) -> Self;
330
331    /// Returns `2^(self)`.
332    ///
333    /// This implementation uses `libm` instead of the Rust intrinsic.
334    ///
335    /// # Examples
336    ///
337    /// ```
338    /// use core_maths::*;
339    /// let f = 2.0_f64;
340    ///
341    /// // 2^2 - 4 == 0
342    /// let abs_difference = (CoreFloat::exp2(f) - 4.0).abs();
343    ///
344    /// assert!(abs_difference < 1e-10);
345    /// ```
346    fn exp2(self) -> Self;
347
348    /// Returns the natural logarithm of the number.
349    ///
350    /// This implementation uses `libm` instead of the Rust intrinsic.
351    ///
352    /// # Examples
353    ///
354    /// ```
355    /// use core_maths::*;
356    /// let one = 1.0_f64;
357    /// // e^1
358    /// let e = one.exp();
359    ///
360    /// // ln(e) - 1 == 0
361    /// let abs_difference = (CoreFloat::ln(e) - 1.0).abs();
362    ///
363    /// assert!(abs_difference < 1e-10);
364    /// ```
365    fn ln(self) -> Self;
366
367    /// Returns the logarithm of the number with respect to an arbitrary base.
368    ///
369    /// The result might not be correctly rounded owing to implementation details;
370    /// `self.log2()` can produce more accurate results for base 2, and
371    /// `self.log10()` can produce more accurate results for base 10.
372    ///
373    /// This method does not use an intrinsic in `std`, so its code is copied.
374    ///
375    /// # Examples
376    ///
377    /// ```
378    /// use core_maths::*;
379    /// let twenty_five = 25.0_f64;
380    ///
381    /// // log5(25) - 2 == 0
382    /// let abs_difference = (CoreFloat::log(twenty_five, 5.0) - 2.0).abs();
383    ///
384    /// assert!(abs_difference < 1e-10);
385    /// ```
386    fn log(self, base: Self) -> Self;
387
388    /// Returns the base 2 logarithm of the number.
389    ///
390    /// This implementation uses `libm` instead of the Rust intrinsic.
391    ///
392    /// # Examples
393    ///
394    /// ```
395    /// use core_maths::*;
396    /// let four = 4.0_f64;
397    ///
398    /// // log2(4) - 2 == 0
399    /// let abs_difference = (CoreFloat::log2(four) - 2.0).abs();
400    ///
401    /// assert!(abs_difference < 1e-10);
402    /// ```
403    fn log2(self) -> Self;
404
405    /// Returns the base 10 logarithm of the number.
406    ///
407    /// This implementation uses `libm` instead of the Rust intrinsic.
408    ///
409    /// # Examples
410    ///
411    /// ```
412    /// use core_maths::*;
413    /// let hundred = 100.0_f64;
414    ///
415    /// // log10(100) - 2 == 0
416    /// let abs_difference = (CoreFloat::log10(hundred) - 2.0).abs();
417    ///
418    /// assert!(abs_difference < 1e-10);
419    /// ```
420    fn log10(self) -> Self;
421
422    /// Returns the cube root of a number.
423    ///
424    /// This implementation uses `libm` instead of the Rust intrinsic.
425    ///
426    /// # Examples
427    ///
428    /// ```
429    /// use core_maths::*;
430    /// let x = 8.0_f64;
431    ///
432    /// // x^(1/3) - 2 == 0
433    /// let abs_difference = (CoreFloat::cbrt(x) - 2.0).abs();
434    ///
435    /// assert!(abs_difference < 1e-10);
436    /// ```
437    fn cbrt(self) -> Self;
438
439    /// Compute the distance between the origin and a point (`x`, `y`) on the
440    /// Euclidean plane. Equivalently, compute the length of the hypotenuse of a
441    /// right-angle triangle with other sides having length `x.abs()` and
442    /// `y.abs()`.
443    ///
444    /// This implementation uses `libm` instead of the Rust intrinsic.
445    ///
446    /// # Examples
447    ///
448    /// ```
449    /// use core_maths::*;
450    /// let x = 2.0_f64;
451    /// let y = 3.0_f64;
452    ///
453    /// // sqrt(x^2 + y^2)
454    /// let abs_difference = (CoreFloat::hypot(x, y) - (x.powi(2) + y.powi(2)).sqrt()).abs();
455    ///
456    /// assert!(abs_difference < 1e-10);
457    /// ```
458    fn hypot(self, other: Self) -> Self;
459
460    /// Computes the sine of a number (in radians).
461    ///
462    /// This implementation uses `libm` instead of the Rust intrinsic.
463    ///
464    /// # Examples
465    ///
466    /// ```
467    /// use core_maths::*;
468    /// let x = std::f64::consts::FRAC_PI_2;
469    ///
470    /// let abs_difference = (CoreFloat::sin(x) - 1.0).abs();
471    ///
472    /// assert!(abs_difference < 1e-10);
473    /// ```
474    fn sin(self) -> Self;
475
476    /// Computes the cosine of a number (in radians).
477    ///
478    /// This implementation uses `libm` instead of the Rust intrinsic.
479    ///
480    /// # Examples
481    ///
482    /// ```
483    /// use core_maths::*;
484    /// let x = 2.0 * std::f64::consts::PI;
485    ///
486    /// let abs_difference = (CoreFloat::cos(x) - 1.0).abs();
487    ///
488    /// assert!(abs_difference < 1e-10);
489    /// ```
490    fn cos(self) -> Self;
491
492    /// Computes the tangent of a number (in radians).
493    ///
494    /// This implementation uses `libm` instead of the Rust intrinsic.
495    ///
496    /// # Examples
497    ///
498    /// ```
499    /// use core_maths::*;
500    /// let x = std::f64::consts::FRAC_PI_4;
501    ///
502    /// let abs_difference = (CoreFloat::tan(x) - 1.0).abs();
503    ///
504    /// assert!(abs_difference < 1e-14);
505    /// ```
506    fn tan(self) -> Self;
507
508    /// Computes the arcsine of a number. Return value is in radians in
509    /// the range [-pi/2, pi/2] or NaN if the number is outside the range
510    /// [-1, 1].
511    ///
512    /// This implementation uses `libm` instead of the Rust intrinsic.
513    ///
514    /// # Examples
515    ///
516    /// ```
517    /// use core_maths::*;
518    /// let f = std::f64::consts::FRAC_PI_2;
519    ///
520    /// // asin(sin(pi/2))
521    /// let abs_difference = (CoreFloat::asin(f.sin()) - std::f64::consts::FRAC_PI_2).abs();
522    ///
523    /// assert!(abs_difference < 1e-10);
524    /// ```
525    fn asin(self) -> Self;
526
527    /// Computes the arccosine of a number. Return value is in radians in
528    /// the range [0, pi] or NaN if the number is outside the range
529    /// [-1, 1].
530    ///
531    /// This implementation uses `libm` instead of the Rust intrinsic.
532    ///
533    /// # Examples
534    ///
535    /// ```
536    /// use core_maths::*;
537    /// let f = std::f64::consts::FRAC_PI_4;
538    ///
539    /// // acos(cos(pi/4))
540    /// let abs_difference = (CoreFloat::acos(f.cos()) - std::f64::consts::FRAC_PI_4).abs();
541    ///
542    /// assert!(abs_difference < 1e-10);
543    /// ```
544    fn acos(self) -> Self;
545
546    /// Computes the arctangent of a number. Return value is in radians in the
547    /// range [-pi/2, pi/2];
548    ///
549    /// This implementation uses `libm` instead of the Rust intrinsic.
550    ///
551    /// # Examples
552    ///
553    /// ```
554    /// use core_maths::*;
555    /// let f = 1.0_f64;
556    ///
557    /// // atan(tan(1))
558    /// let abs_difference = (CoreFloat::atan(f.tan()) - 1.0).abs();
559    ///
560    /// assert!(abs_difference < 1e-10);
561    /// ```
562    fn atan(self) -> Self;
563
564    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
565    ///
566    /// * `x = 0`, `y = 0`: `0`
567    /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
568    /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
569    /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
570    ///
571    /// This implementation uses `libm` instead of the Rust intrinsic.
572    ///
573    /// # Examples
574    ///
575    /// ```
576    /// use core_maths::*;
577    /// // Positive angles measured counter-clockwise
578    /// // from positive x axis
579    /// // -pi/4 radians (45 deg clockwise)
580    /// let x1 = 3.0_f64;
581    /// let y1 = -3.0_f64;
582    ///
583    /// // 3pi/4 radians (135 deg counter-clockwise)
584    /// let x2 = -3.0_f64;
585    /// let y2 = 3.0_f64;
586    ///
587    /// let abs_difference_1 = (CoreFloat::atan2(y1, x1) - (-std::f64::consts::FRAC_PI_4)).abs();
588    /// let abs_difference_2 = (CoreFloat::atan2(y2, x2) - (3.0 * std::f64::consts::FRAC_PI_4)).abs();
589    ///
590    /// assert!(abs_difference_1 < 1e-10);
591    /// assert!(abs_difference_2 < 1e-10);
592    /// ```
593    fn atan2(self, other: Self) -> Self;
594
595    /// Simultaneously computes the sine and cosine of the number, `x`. Returns
596    /// `(sin(x), cos(x))`.
597    ///
598    /// This implementation uses `libm` instead of the Rust intrinsic.
599    ///
600    /// # Examples
601    ///
602    /// ```
603    /// use core_maths::*;
604    /// let x = std::f64::consts::FRAC_PI_4;
605    /// let f = CoreFloat::sin_cos(x);
606    ///
607    /// let abs_difference_0 = (f.0 - x.sin()).abs();
608    /// let abs_difference_1 = (f.1 - x.cos()).abs();
609    ///
610    /// assert!(abs_difference_0 < 1e-10);
611    /// assert!(abs_difference_1 < 1e-10);
612    /// ```
613    fn sin_cos(self) -> (Self, Self) {
614        (self.sin(), self.cos())
615    }
616
617    /// Returns `e^(self) - 1` in a way that is accurate even if the
618    /// number is close to zero.
619    ///
620    /// This implementation uses `libm` instead of the Rust intrinsic.
621    ///
622    /// # Examples
623    ///
624    /// ```
625    /// use core_maths::*;
626    /// let x = 1e-16_f64;
627    ///
628    /// // for very small x, e^x is approximately 1 + x + x^2 / 2
629    /// let approx = x + x * x / 2.0;
630    /// let abs_difference = (CoreFloat::exp_m1(x) - approx).abs();
631    ///
632    /// assert!(abs_difference < 1e-20);
633    /// ```
634    fn exp_m1(self) -> Self;
635
636    /// Returns `ln(1+n)` (natural logarithm) more accurately than if
637    /// the operations were performed separately.
638    ///
639    /// This implementation uses `libm` instead of the Rust intrinsic.
640    ///
641    /// # Examples
642    ///
643    /// ```
644    /// use core_maths::*;
645    /// let x = 1e-16_f64;
646    ///
647    /// // for very small x, ln(1 + x) is approximately x - x^2 / 2
648    /// let approx = x - x * x / 2.0;
649    /// let abs_difference = (CoreFloat::ln_1p(x) - approx).abs();
650    ///
651    /// assert!(abs_difference < 1e-20);
652    /// ```
653    fn ln_1p(self) -> Self;
654
655    /// Hyperbolic sine function.
656    ///
657    /// This implementation uses `libm` instead of the Rust intrinsic.
658    ///
659    /// # Examples
660    ///
661    /// ```
662    /// use core_maths::*;
663    /// let e = std::f64::consts::E;
664    /// let x = 1.0_f64;
665    ///
666    /// let f = CoreFloat::sinh(x);
667    /// // Solving sinh() at 1 gives `(e^2-1)/(2e)`
668    /// let g = ((e * e) - 1.0) / (2.0 * e);
669    /// let abs_difference = (f - g).abs();
670    ///
671    /// assert!(abs_difference < 1e-10);
672    /// ```
673    fn sinh(self) -> Self;
674
675    /// Hyperbolic cosine function.
676    ///
677    /// This implementation uses `libm` instead of the Rust intrinsic.
678    ///
679    /// # Examples
680    ///
681    /// ```
682    /// use core_maths::*;
683    /// let e = std::f64::consts::E;
684    /// let x = 1.0_f64;
685    /// let f = CoreFloat::cosh(x);
686    /// // Solving cosh() at 1 gives this result
687    /// let g = ((e * e) + 1.0) / (2.0 * e);
688    /// let abs_difference = (f - g).abs();
689    ///
690    /// // Same result
691    /// assert!(abs_difference < 1.0e-10);
692    /// ```
693    fn cosh(self) -> Self;
694
695    /// Hyperbolic tangent function.
696    ///
697    /// This implementation uses `libm` instead of the Rust intrinsic.
698    ///
699    /// # Examples
700    ///
701    /// ```
702    /// use core_maths::*;
703    /// let e = std::f64::consts::E;
704    /// let x = 1.0_f64;
705    ///
706    /// let f = CoreFloat::tanh(x);
707    /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))`
708    /// let g = (1.0 - e.powi(-2)) / (1.0 + e.powi(-2));
709    /// let abs_difference = (f - g).abs();
710    ///
711    /// assert!(abs_difference < 1.0e-10);
712    /// ```
713    fn tanh(self) -> Self;
714
715    /// Inverse hyperbolic sine function.
716    ///
717    /// This method does not use an intrinsic in `std`, so its code is copied.
718    ///
719    /// # Examples
720    ///
721    /// ```
722    /// use core_maths::*;
723    /// let x = 1.0_f64;
724    /// let f = CoreFloat::asinh(x.sinh());
725    ///
726    /// let abs_difference = (f - x).abs();
727    ///
728    /// assert!(abs_difference < 1.0e-10);
729    /// ```
730    fn asinh(self) -> Self;
731
732    /// Inverse hyperbolic cosine function.
733    ///
734    /// This method does not use an intrinsic in `std`, so its code is copied.
735    ///
736    /// # Examples
737    ///
738    /// ```
739    /// use core_maths::*;
740    /// let x = 1.0_f64;
741    /// let f = CoreFloat::acosh(x.cosh());
742    ///
743    /// let abs_difference = (f - x).abs();
744    ///
745    /// assert!(abs_difference < 1.0e-10);
746    /// ```
747    fn acosh(self) -> Self;
748
749    /// Inverse hyperbolic tangent function.
750    ///
751    /// This method does not use an intrinsic in `std`, so its code is copied.
752    ///
753    /// # Examples
754    ///
755    /// ```
756    /// use core_maths::*;
757    /// let e = std::f64::consts::E;
758    /// let f = CoreFloat::atanh(e.tanh());
759    ///
760    /// let abs_difference = (f - e).abs();
761    ///
762    /// assert!(abs_difference < 1.0e-10);
763    /// ```
764    fn atanh(self) -> Self;
765}
766
767impl CoreFloat for f32 {
768    #[inline]
769    fn floor(self) -> Self {
770        libm::floorf(self)
771    }
772
773    #[inline]
774    fn ceil(self) -> Self {
775        libm::ceilf(self)
776    }
777
778    #[inline]
779    fn round(self) -> Self {
780        libm::roundf(self)
781    }
782
783    #[inline]
784    fn trunc(self) -> Self {
785        libm::truncf(self)
786    }
787
788    #[inline]
789    fn fract(self) -> Self {
790        self - self.trunc()
791    }
792
793    #[inline]
794    fn abs(self) -> Self {
795        libm::fabsf(self)
796    }
797
798    #[inline]
799    fn signum(self) -> Self {
800        if self.is_nan() {
801            Self::NAN
802        } else {
803            1.0_f32.copysign(self)
804        }
805    }
806
807    #[inline]
808    fn copysign(self, sign: Self) -> Self {
809        libm::copysignf(self, sign)
810    }
811
812    #[inline]
813    fn mul_add(self, a: Self, b: Self) -> Self {
814        libm::fmaf(self, a, b)
815    }
816
817    #[inline]
818    fn div_euclid(self, rhs: Self) -> Self {
819        let q = (self / rhs).trunc();
820        if self % rhs < 0.0 {
821            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
822        }
823        q
824    }
825
826    #[inline]
827    fn rem_euclid(self, rhs: Self) -> Self {
828        let r = self % rhs;
829        if r < 0.0 {
830            r + rhs.abs()
831        } else {
832            r
833        }
834    }
835
836    #[inline]
837    fn powi(self, exp: i32) -> Self {
838        if exp == 0 {
839            return 1.0;
840        }
841
842        let mut base = if exp < 0 { self.recip() } else { self };
843        let mut exp = exp.unsigned_abs();
844        let mut acc = 1.0;
845
846        while exp > 1 {
847            if (exp & 1) == 1 {
848                acc *= base;
849            }
850            exp /= 2;
851            base = base * base;
852        }
853
854        // since exp!=0, finally the exp must be 1.
855        // Deal with the final bit of the exponent separately, since
856        // squaring the base afterwards is not necessary and may cause a
857        // needless overflow.
858        acc * base
859    }
860
861    #[inline]
862    fn powf(self, n: Self) -> Self {
863        libm::powf(self, n)
864    }
865
866    #[inline]
867    fn sqrt(self) -> Self {
868        libm::sqrtf(self)
869    }
870
871    #[inline]
872    fn exp(self) -> Self {
873        libm::expf(self)
874    }
875
876    #[inline]
877    fn exp2(self) -> Self {
878        libm::exp2f(self)
879    }
880
881    #[inline]
882    fn ln(self) -> Self {
883        libm::logf(self)
884    }
885
886    #[inline]
887    fn log(self, base: Self) -> Self {
888        self.ln() / base.ln()
889    }
890
891    #[inline]
892    fn log2(self) -> Self {
893        libm::log2f(self)
894    }
895
896    #[inline]
897    fn log10(self) -> Self {
898        libm::log10f(self)
899    }
900
901    #[inline]
902    fn cbrt(self) -> Self {
903        libm::cbrtf(self)
904    }
905
906    #[inline]
907    fn hypot(self, other: Self) -> Self {
908        libm::hypotf(self, other)
909    }
910
911    #[inline]
912    fn sin(self) -> Self {
913        libm::sinf(self)
914    }
915
916    #[inline]
917    fn cos(self) -> Self {
918        libm::cosf(self)
919    }
920
921    #[inline]
922    fn tan(self) -> Self {
923        libm::tanf(self)
924    }
925
926    #[inline]
927    fn asin(self) -> Self {
928        libm::asinf(self)
929    }
930
931    #[inline]
932    fn acos(self) -> Self {
933        libm::acosf(self)
934    }
935
936    #[inline]
937    fn atan(self) -> Self {
938        libm::atanf(self)
939    }
940
941    #[inline]
942    fn atan2(self, other: Self) -> Self {
943        libm::atan2f(self, other)
944    }
945
946    #[inline]
947    fn exp_m1(self) -> Self {
948        libm::expm1f(self)
949    }
950
951    #[inline]
952    fn ln_1p(self) -> Self {
953        libm::log1pf(self)
954    }
955
956    #[inline]
957    fn sinh(self) -> Self {
958        libm::sinhf(self)
959    }
960
961    #[inline]
962    fn cosh(self) -> Self {
963        libm::coshf(self)
964    }
965
966    #[inline]
967    fn tanh(self) -> Self {
968        libm::tanhf(self)
969    }
970
971    #[inline]
972    fn asinh(self) -> Self {
973        let ax = self.abs();
974        let ix = 1.0 / ax;
975        (ax + (ax / (Self::hypot(1.0, ix) + ix)))
976            .ln_1p()
977            .copysign(self)
978    }
979
980    #[inline]
981    fn acosh(self) -> Self {
982        if self < 1.0 {
983            Self::NAN
984        } else {
985            (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
986        }
987    }
988
989    #[inline]
990    fn atanh(self) -> Self {
991        0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
992    }
993}
994
995impl CoreFloat for f64 {
996    #[inline]
997    fn floor(self) -> Self {
998        libm::floor(self)
999    }
1000
1001    #[inline]
1002    fn ceil(self) -> Self {
1003        libm::ceil(self)
1004    }
1005
1006    #[inline]
1007    fn round(self) -> Self {
1008        libm::round(self)
1009    }
1010
1011    #[inline]
1012    fn trunc(self) -> Self {
1013        libm::trunc(self)
1014    }
1015
1016    #[inline]
1017    fn fract(self) -> Self {
1018        self - self.trunc()
1019    }
1020
1021    #[inline]
1022    fn abs(self) -> Self {
1023        libm::fabs(self)
1024    }
1025
1026    #[inline]
1027    fn signum(self) -> Self {
1028        if self.is_nan() {
1029            Self::NAN
1030        } else {
1031            1.0_f64.copysign(self)
1032        }
1033    }
1034
1035    #[inline]
1036    fn copysign(self, sign: Self) -> Self {
1037        libm::copysign(self, sign)
1038    }
1039
1040    #[inline]
1041    fn mul_add(self, a: Self, b: Self) -> Self {
1042        libm::fma(self, a, b)
1043    }
1044
1045    #[inline]
1046    fn div_euclid(self, rhs: Self) -> Self {
1047        let q = (self / rhs).trunc();
1048        if self % rhs < 0.0 {
1049            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
1050        }
1051        q
1052    }
1053
1054    #[inline]
1055    fn rem_euclid(self, rhs: Self) -> Self {
1056        let r = self % rhs;
1057        if r < 0.0 {
1058            r + rhs.abs()
1059        } else {
1060            r
1061        }
1062    }
1063
1064    #[inline]
1065    fn powi(self, exp: i32) -> Self {
1066        if exp == 0 {
1067            return 1.0;
1068        }
1069
1070        let mut base = if exp < 0 { self.recip() } else { self };
1071        let mut exp = exp.unsigned_abs();
1072        let mut acc = 1.0;
1073
1074        while exp > 1 {
1075            if (exp & 1) == 1 {
1076                acc *= base;
1077            }
1078            exp /= 2;
1079            base = base * base;
1080        }
1081
1082        // since exp!=0, finally the exp must be 1.
1083        // Deal with the final bit of the exponent separately, since
1084        // squaring the base afterwards is not necessary and may cause a
1085        // needless overflow.
1086        acc * base
1087    }
1088
1089    #[inline]
1090    fn powf(self, n: Self) -> Self {
1091        libm::pow(self, n)
1092    }
1093
1094    #[inline]
1095    fn sqrt(self) -> Self {
1096        libm::sqrt(self)
1097    }
1098
1099    #[inline]
1100    fn exp(self) -> Self {
1101        libm::exp(self)
1102    }
1103
1104    #[inline]
1105    fn exp2(self) -> Self {
1106        libm::exp2(self)
1107    }
1108
1109    #[inline]
1110    fn ln(self) -> Self {
1111        libm::log(self)
1112    }
1113
1114    #[inline]
1115    fn log(self, base: Self) -> Self {
1116        self.ln() / base.ln()
1117    }
1118
1119    #[inline]
1120    fn log2(self) -> Self {
1121        libm::log2(self)
1122    }
1123
1124    #[inline]
1125    fn log10(self) -> Self {
1126        libm::log10(self)
1127    }
1128
1129    #[inline]
1130    fn cbrt(self) -> Self {
1131        libm::cbrt(self)
1132    }
1133
1134    #[inline]
1135    fn hypot(self, other: Self) -> Self {
1136        libm::hypot(self, other)
1137    }
1138
1139    #[inline]
1140    fn sin(self) -> Self {
1141        libm::sin(self)
1142    }
1143
1144    #[inline]
1145    fn cos(self) -> Self {
1146        libm::cos(self)
1147    }
1148
1149    #[inline]
1150    fn tan(self) -> Self {
1151        libm::tan(self)
1152    }
1153
1154    #[inline]
1155    fn asin(self) -> Self {
1156        libm::asin(self)
1157    }
1158
1159    #[inline]
1160    fn acos(self) -> Self {
1161        libm::acos(self)
1162    }
1163
1164    #[inline]
1165    fn atan(self) -> Self {
1166        libm::atan(self)
1167    }
1168
1169    #[inline]
1170    fn atan2(self, other: Self) -> Self {
1171        libm::atan2(self, other)
1172    }
1173
1174    #[inline]
1175    fn exp_m1(self) -> Self {
1176        libm::expm1(self)
1177    }
1178
1179    #[inline]
1180    fn ln_1p(self) -> Self {
1181        libm::log1p(self)
1182    }
1183
1184    #[inline]
1185    fn sinh(self) -> Self {
1186        libm::sinh(self)
1187    }
1188
1189    #[inline]
1190    fn cosh(self) -> Self {
1191        libm::cosh(self)
1192    }
1193
1194    #[inline]
1195    fn tanh(self) -> Self {
1196        libm::tanh(self)
1197    }
1198
1199    #[inline]
1200    fn asinh(self) -> Self {
1201        let ax = self.abs();
1202        let ix = 1.0 / ax;
1203        (ax + (ax / (Self::hypot(1.0, ix) + ix)))
1204            .ln_1p()
1205            .copysign(self)
1206    }
1207
1208    #[inline]
1209    fn acosh(self) -> Self {
1210        if self < 1.0 {
1211            Self::NAN
1212        } else {
1213            (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
1214        }
1215    }
1216
1217    #[inline]
1218    fn atanh(self) -> Self {
1219        0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
1220    }
1221}