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}
1222