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`]. |
18 | pub 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 | |
767 | impl 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 | |
995 | impl 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 | |