vexide_core/float/
mod.rs

1//! Floating point arithmetic.
2//!
3//! This module provides implementations of math functions of floating point
4//! primitive types (`f32`, `f64`) through the [`Float`] trait.
5
6#[cfg(all(target_vendor = "vex", not(feature = "force_rust_libm")))]
7mod newlib;
8
9#[cfg(any(not(target_vendor = "vex"), feature = "force_rust_libm"))]
10mod rust;
11
12/// Used to make [`powi_impl`] generic across f32 and f64.
13pub(crate) trait One {
14    const ONE: Self;
15}
16
17impl One for f64 {
18    const ONE: Self = 1.0;
19}
20
21impl One for f32 {
22    const ONE: Self = 1.0;
23}
24
25/// Implementation of an integer power function using exponentiation by squaring.
26///
27/// Adapted from <https://github.com/rust-num/num-traits/blob/7ec3d41d39b28190ec1d42db38021107b3951f3a/src/pow.rs#L23>
28#[inline]
29pub(crate) fn powi_impl<T: One + Copy + core::ops::Mul<T, Output = T>>(
30    mut base: T,
31    mut exp: usize,
32) -> T {
33    if exp == 0 {
34        return T::ONE;
35    }
36
37    while exp & 1 == 0 {
38        base = base * base;
39        exp >>= 1;
40    }
41    if exp == 1 {
42        return base;
43    }
44
45    let mut acc = base;
46    while exp > 1 {
47        exp >>= 1;
48        base = base * base;
49        if exp & 1 == 1 {
50            acc = acc * base;
51        }
52    }
53    acc
54}
55
56/// Floating-point math functions
57///
58/// This extension trait defines the missing implementations of floating point
59/// math in `core` present in rust's `std` crate.
60pub trait Float: Sized {
61    /// Returns the largest integer less than or equal to `self`.
62    ///
63    /// This function always returns the precise result.
64    #[must_use = "method returns a new number and does not mutate the original value"]
65    fn floor(self) -> Self;
66
67    /// Returns the smallest integer greater than or equal to `self`.
68    ///
69    /// This function always returns the precise result.
70    #[must_use = "method returns a new number and does not mutate the original value"]
71    fn ceil(self) -> Self;
72
73    /// Returns the nearest integer to `self`. If a value is half-way between two
74    /// integers, round away from `0.0`.
75    ///
76    /// This function always returns the precise result.
77    #[must_use = "method returns a new number and does not mutate the original value"]
78    fn round(self) -> Self;
79
80    /// Returns the nearest integer to a number. Rounds half-way cases to the number
81    /// with an even least significant digit.
82    ///
83    /// This function always returns the precise result.
84    #[must_use = "method returns a new number and does not mutate the original value"]
85    fn round_ties_even(self) -> Self;
86
87    /// Returns the integer part of `self`.
88    /// This means that non-integer numbers are always truncated towards zero.
89    ///
90    /// This function always returns the precise result.
91    #[must_use = "method returns a new number and does not mutate the original value"]
92    fn trunc(self) -> Self;
93
94    /// Returns the fractional part of `self`.
95    ///
96    /// This function always returns the precise result.
97    #[must_use = "method returns a new number and does not mutate the original value"]
98    fn fract(self) -> Self;
99
100    /// Computes the absolute value of `self`.
101    ///
102    /// This function always returns the precise result.
103    #[must_use = "method returns a new number and does not mutate the original value"]
104    fn abs(self) -> Self;
105
106    /// Returns a number that represents the sign of `self`.
107    ///
108    /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
109    /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
110    /// - NaN if the number is NaN
111    #[must_use = "method returns a new number and does not mutate the original value"]
112    fn signum(self) -> Self;
113
114    /// Returns a number composed of the magnitude of `self` and the sign of
115    /// `sign`.
116    ///
117    /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
118    /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of
119    /// `sign` is returned. Note, however, that conserving the sign bit on NaN
120    /// across arithmetical operations is not generally guaranteed.
121    /// See [explanation of NaN as a special value](primitive@f32) for more info.
122    #[must_use = "method returns a new number and does not mutate the original value"]
123    fn copysign(self, sign: Self) -> Self;
124
125    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
126    /// error, yielding a more accurate result than an unfused multiply-add.
127    ///
128    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
129    /// the target architecture has a dedicated `fma` CPU instruction. However,
130    /// this is not always true, and will be heavily dependant on designing
131    /// algorithms with specific target hardware in mind.
132    #[must_use = "method returns a new number and does not mutate the original value"]
133    fn mul_add(self, a: Self, b: Self) -> Self;
134
135    /// Calculates Euclidean division, the matching method for `rem_euclid`.
136    ///
137    /// This computes the integer `n` such that
138    /// `self = n * rhs + self.rem_euclid(rhs)`.
139    /// In other words, the result is `self / rhs` rounded to the integer `n`
140    /// such that `self >= n * rhs`.
141    #[must_use = "method returns a new number and does not mutate the original value"]
142    fn div_euclid(self, rhs: Self) -> Self;
143
144    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
145    ///
146    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
147    /// most cases. However, due to a floating point round-off error it can
148    /// result in `r == rhs.abs()`, violating the mathematical definition, if
149    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
150    /// This result is not an element of the function's codomain, but it is the
151    /// closest floating point number in the real numbers and thus fulfills the
152    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
153    /// approximately.
154    ///
155    /// # Precision
156    ///
157    /// The result of this operation is guaranteed to be the rounded
158    /// infinite-precision result.
159    #[must_use = "method returns a new number and does not mutate the original value"]
160    fn rem_euclid(self, rhs: Self) -> Self;
161
162    /// Raises a number to an integer power.
163    ///
164    /// Using this function is generally faster than using `powf`.
165    /// It might have a different sequence of rounding operations than `powf`,
166    /// so the results are not guaranteed to agree.
167    ///
168    /// # Platform-specific precision
169    ///
170    /// The precision of this function varies by platform and Rust version.
171    #[must_use = "method returns a new number and does not mutate the original value"]
172    fn powi(self, n: i32) -> Self;
173
174    /// Raises a number to a floating point power.
175    ///
176    /// # Platform-specific precision
177    ///
178    /// The precision of this function varies by platform and Rust version.
179    #[must_use = "method returns a new number and does not mutate the original value"]
180    fn powf(self, n: Self) -> Self;
181
182    /// Returns the square root of a number.
183    ///
184    /// Returns NaN if `self` is a negative number other than `-0.0`.
185    ///
186    /// # Precision
187    ///
188    /// The result of this operation is guaranteed to be the rounded
189    /// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
190    /// and guaranteed not to change.
191    #[must_use = "method returns a new number and does not mutate the original value"]
192    fn sqrt(self) -> Self;
193
194    /// Returns `e^(self)`, (the exponential function).
195    ///
196    /// # Platform-specific precision
197    ///
198    /// The precision of this function varies by platform and Rust version.
199    #[must_use = "method returns a new number and does not mutate the original value"]
200    fn exp(self) -> Self;
201
202    /// Returns `2^(self)`.
203    ///
204    /// # Platform-specific precision
205    ///
206    /// The precision of this function varies by platform and Rust version.
207    #[must_use = "method returns a new number and does not mutate the original value"]
208    fn exp2(self) -> Self;
209
210    /// Returns the natural logarithm of the number.
211    ///
212    /// # Platform-specific precision
213    ///
214    /// The precision of this function varies by platform and Rust version.
215    #[must_use = "method returns a new number and does not mutate the original value"]
216    fn ln(self) -> Self;
217
218    /// Returns the logarithm of the number with respect to an arbitrary base.
219    ///
220    /// The result might not be correctly rounded owing to implementation details;
221    /// `self.log2()` can produce more accurate results for base 2, and
222    /// `self.log10()` can produce more accurate results for base 10.
223    ///
224    /// # Platform-specific precision
225    ///
226    /// The precision of this function varies by platform and Rust version.
227    #[must_use = "method returns a new number and does not mutate the original value"]
228    fn log(self, base: Self) -> Self;
229
230    /// Returns the base 2 logarithm of the number.
231    ///
232    /// # Platform-specific precision
233    ///
234    /// The precision of this function varies by platform and Rust version.
235    #[must_use = "method returns a new number and does not mutate the original value"]
236    fn log2(self) -> Self;
237
238    /// Returns the base 10 logarithm of the number.
239    ///
240    /// # Platform-specific precision
241    ///
242    /// The precision of this function varies by platform and Rust version.
243    #[must_use = "method returns a new number and does not mutate the original value"]
244    fn log10(self) -> Self;
245
246    /// The positive difference of two numbers.
247    ///
248    /// * If `self <= other`: `0.0`
249    /// * Else: `self - other`
250    ///
251    /// # Platform-specific precision
252    ///
253    /// The precision of this function varies by platform and Rust version.
254    /// This function currently corresponds to the `fdim` function from libm.
255    #[deprecated(
256        since = "0.2.0",
257        note = "you probably meant `(self - other).abs()`: \
258                this operation is `(self - other).max(0.0)` \
259                except that `abs_sub` also propagates NaNs (also \
260                known as `fdim` in C). If you truly need the positive \
261                difference, consider using that expression or the C function \
262                `fdim`, depending on how you wish to handle NaN."
263    )]
264    #[must_use = "method returns a new number and does not mutate the original value"]
265    fn abs_sub(self, other: Self) -> Self;
266
267    /// Returns the cube root of a number.
268    ///
269    /// # Platform-specific precision
270    ///
271    /// The precision of this function varies by platform and Rust version.
272    #[must_use = "method returns a new number and does not mutate the original value"]
273    fn cbrt(self) -> Self;
274
275    /// Compute the distance between the origin and a point (`x`, `y`) on the
276    /// Euclidean plane. Equivalently, compute the length of the hypotenuse of a
277    /// right-angle triangle with other sides having length `x.abs()` and
278    /// `y.abs()`.
279    ///
280    /// # Platform-specific precision
281    ///
282    /// The precision of this function varies by platform and Rust version.
283    #[must_use = "method returns a new number and does not mutate the original value"]
284    fn hypot(self, other: Self) -> Self;
285
286    /// Computes the sine of a number (in radians).
287    ///
288    /// # Platform-specific precision
289    ///
290    /// The precision of this function varies by platform and Rust version.
291    #[must_use = "method returns a new number and does not mutate the original value"]
292    fn sin(self) -> Self;
293
294    /// Computes the cosine of a number (in radians).
295    ///
296    /// # Platform-specific precision
297    ///
298    /// The precision of this function varies by platform and Rust version.
299    #[must_use = "method returns a new number and does not mutate the original value"]
300    fn cos(self) -> Self;
301
302    /// Computes the tangent of a number (in radians).
303    ///
304    /// # Platform-specific precision
305    ///
306    /// The precision of this function varies by platform and Rust version.
307    #[must_use = "method returns a new number and does not mutate the original value"]
308    fn tan(self) -> Self;
309
310    /// Computes the arcsine of a number. Return value is in radians in
311    /// the range [-pi/2, pi/2] or NaN if the number is outside the range
312    /// [-1, 1].
313    ///
314    /// # Platform-specific precision
315    ///
316    /// The precision of this function varies by platform and Rust version.
317    #[must_use = "method returns a new number and does not mutate the original value"]
318    fn asin(self) -> Self;
319
320    /// Computes the arccosine of a number. Return value is in radians in
321    /// the range [0, pi] or NaN if the number is outside the range
322    /// [-1, 1].
323    ///
324    /// # Platform-specific precision
325    ///
326    /// The precision of this function varies by platform and Rust version.
327    #[must_use = "method returns a new number and does not mutate the original value"]
328    fn acos(self) -> Self;
329
330    /// Computes the arctangent of a number. Return value is in radians in the
331    /// range [-pi/2, pi/2];
332    ///
333    /// # Platform-specific precision
334    ///
335    /// The precision of this function varies by platform and Rust version.
336    #[must_use = "method returns a new number and does not mutate the original value"]
337    fn atan(self) -> Self;
338
339    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
340    ///
341    /// * `x = 0`, `y = 0`: `0`
342    /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
343    /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
344    /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
345    ///
346    /// # Platform-specific precision
347    ///
348    /// The precision of this function varies by platform and Rust version.
349    #[must_use = "method returns a new number and does not mutate the original value"]
350    fn atan2(self, other: Self) -> Self;
351
352    /// Simultaneously computes the sine and cosine of the number, `x`. Returns
353    /// `(sin(x), cos(x))`.
354    ///
355    /// # Platform-specific precision
356    ///
357    /// The precision of this function varies by platform and Rust version.
358    #[must_use = "method returns a new number and does not mutate the original value"]
359    fn sin_cos(self) -> (Self, Self);
360
361    /// Returns `e^(self) - 1` in a way that is accurate even if the
362    /// number is close to zero.
363    ///
364    /// # Platform-specific precision
365    ///
366    /// The precision of this function varies by platform and Rust version.
367    #[must_use = "method returns a new number and does not mutate the original value"]
368    fn exp_m1(self) -> Self;
369
370    /// Returns `ln(1+n)` (natural logarithm) more accurately than if
371    /// the operations were performed separately.
372    ///
373    /// # Platform-specific precision
374    ///
375    /// The precision of this function varies by platform and Rust version.
376    #[must_use = "method returns a new number and does not mutate the original value"]
377    fn ln_1p(self) -> Self;
378
379    /// Hyperbolic sine function.
380    ///
381    /// # Platform-specific precision
382    ///
383    /// The precision of this function varies by platform and Rust version.
384    #[must_use = "method returns a new number and does not mutate the original value"]
385    fn sinh(self) -> Self;
386
387    /// Hyperbolic cosine function.
388    ///
389    /// # Platform-specific precision
390    ///
391    /// The precision of this function varies by platform and Rust version.
392    #[must_use = "method returns a new number and does not mutate the original value"]
393    fn cosh(self) -> Self;
394
395    /// Hyperbolic tangent function.
396    ///
397    /// # Platform-specific precision
398    ///
399    /// The precision of this function varies by platform and Rust version.
400    #[must_use = "method returns a new number and does not mutate the original value"]
401    fn tanh(self) -> Self;
402
403    /// Inverse hyperbolic sine function.
404    ///
405    /// # Platform-specific precision
406    ///
407    /// The precision of this function varies by platform and Rust version.
408    #[must_use = "method returns a new number and does not mutate the original value"]
409    fn asinh(self) -> Self;
410
411    /// Inverse hyperbolic cosine function.
412    ///
413    /// # Platform-specific precision
414    ///
415    /// The precision of this function varies by platform and Rust version.
416    #[must_use = "method returns a new number and does not mutate the original value"]
417    fn acosh(self) -> Self;
418
419    /// Inverse hyperbolic tangent function.
420    ///
421    /// # Platform-specific precision
422    ///
423    /// The precision of this function varies by platform and Rust version.
424    #[must_use = "method returns a new number and does not mutate the original value"]
425    fn atanh(self) -> Self;
426}