bevy_math/
ops.rs

1//! This mod re-exports the correct versions of floating-point operations with
2//! unspecified precision in the standard library depending on whether the `libm`
3//! crate feature is enabled.
4//!
5//! All the functions here are named according to their versions in the standard
6//! library.
7
8#![allow(dead_code)]
9#![allow(clippy::disallowed_methods)]
10
11// Note: There are some Rust methods with unspecified precision without a `libm`
12// equivalent:
13// - `f32::powi` (integer powers)
14// - `f32::log` (logarithm with specified base)
15// - `f32::abs_sub` (actually unsure if `libm` has this, but don't use it regardless)
16//
17// Additionally, the following nightly API functions are not presently integrated
18// into this, but they would be candidates once standardized:
19// - `f32::gamma`
20// - `f32::ln_gamma`
21
22#[cfg(not(feature = "libm"))]
23mod std_ops {
24
25    /// Raises a number to a floating point power.
26    ///
27    /// Precision is specified when the `libm` feature is enabled.
28    #[inline(always)]
29    pub fn powf(x: f32, y: f32) -> f32 {
30        f32::powf(x, y)
31    }
32
33    /// Returns `e^(self)`, (the exponential function).
34    ///
35    /// Precision is specified when the `libm` feature is enabled.
36    #[inline(always)]
37    pub fn exp(x: f32) -> f32 {
38        f32::exp(x)
39    }
40
41    /// Returns `2^(self)`.
42    ///
43    /// Precision is specified when the `libm` feature is enabled.
44    #[inline(always)]
45    pub fn exp2(x: f32) -> f32 {
46        f32::exp2(x)
47    }
48
49    /// Returns the natural logarithm of the number.
50    ///
51    /// Precision is specified when the `libm` feature is enabled.
52    #[inline(always)]
53    pub fn ln(x: f32) -> f32 {
54        f32::ln(x)
55    }
56
57    /// Returns the base 2 logarithm of the number.
58    ///
59    /// Precision is specified when the `libm` feature is enabled.
60    #[inline(always)]
61    pub fn log2(x: f32) -> f32 {
62        f32::log2(x)
63    }
64
65    /// Returns the base 10 logarithm of the number.
66    ///
67    /// Precision is specified when the `libm` feature is enabled.
68    #[inline(always)]
69    pub fn log10(x: f32) -> f32 {
70        f32::log10(x)
71    }
72
73    /// Returns the cube root of a number.
74    ///
75    /// Precision is specified when the `libm` feature is enabled.
76    #[inline(always)]
77    pub fn cbrt(x: f32) -> f32 {
78        f32::cbrt(x)
79    }
80
81    /// Compute the distance between the origin and a point `(x, y)` on the Euclidean plane.
82    /// Equivalently, compute the length of the hypotenuse of a right-angle triangle with other sides having length `x.abs()` and `y.abs()`.
83    ///
84    /// Precision is specified when the `libm` feature is enabled.
85    #[inline(always)]
86    pub fn hypot(x: f32, y: f32) -> f32 {
87        f32::hypot(x, y)
88    }
89
90    /// Computes the sine of a number (in radians).
91    ///
92    /// Precision is specified when the `libm` feature is enabled.
93    #[inline(always)]
94    pub fn sin(x: f32) -> f32 {
95        f32::sin(x)
96    }
97
98    /// Computes the cosine of a number (in radians).
99    ///
100    /// Precision is specified when the `libm` feature is enabled.
101    #[inline(always)]
102    pub fn cos(x: f32) -> f32 {
103        f32::cos(x)
104    }
105
106    /// Computes the tangent of a number (in radians).
107    ///
108    /// Precision is specified when the `libm` feature is enabled.
109    #[inline(always)]
110    pub fn tan(x: f32) -> f32 {
111        f32::tan(x)
112    }
113
114    /// Computes the arcsine of a number. Return value is in radians in
115    /// the range [-pi/2, pi/2] or NaN if the number is outside the range
116    /// [-1, 1].
117    ///
118    /// Precision is specified when the `libm` feature is enabled.
119    #[inline(always)]
120    pub fn asin(x: f32) -> f32 {
121        f32::asin(x)
122    }
123
124    /// Computes the arccosine of a number. Return value is in radians in
125    /// the range [0, pi] or NaN if the number is outside the range
126    /// [-1, 1].
127    ///
128    /// Precision is specified when the `libm` feature is enabled.
129    #[inline(always)]
130    pub fn acos(x: f32) -> f32 {
131        f32::acos(x)
132    }
133
134    /// Computes the arctangent of a number. Return value is in radians in the
135    /// range [-pi/2, pi/2];
136    ///
137    /// Precision is specified when the `libm` feature is enabled.
138    #[inline(always)]
139    pub fn atan(x: f32) -> f32 {
140        f32::atan(x)
141    }
142
143    /// Computes the four-quadrant arctangent of `y` and `x` in radians.
144    ///
145    /// * `x = 0`, `y = 0`: `0`
146    /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
147    /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
148    /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
149    ///
150    /// Precision is specified when the `libm` feature is enabled.
151    #[inline(always)]
152    pub fn atan2(y: f32, x: f32) -> f32 {
153        f32::atan2(y, x)
154    }
155
156    /// Simultaneously computes the sine and cosine of the number, `x`. Returns
157    /// `(sin(x), cos(x))`.
158    ///
159    /// Precision is specified when the `libm` feature is enabled.
160    #[inline(always)]
161    pub fn sin_cos(x: f32) -> (f32, f32) {
162        f32::sin_cos(x)
163    }
164
165    /// Returns `e^(self) - 1` in a way that is accurate even if the
166    /// number is close to zero.
167    ///
168    /// Precision is specified when the `libm` feature is enabled.
169    #[inline(always)]
170    pub fn exp_m1(x: f32) -> f32 {
171        f32::exp_m1(x)
172    }
173
174    /// Returns `ln(1+n)` (natural logarithm) more accurately than if
175    /// the operations were performed separately.
176    ///
177    /// Precision is specified when the `libm` feature is enabled.
178    #[inline(always)]
179    pub fn ln_1p(x: f32) -> f32 {
180        f32::ln_1p(x)
181    }
182
183    /// Hyperbolic sine function.
184    ///
185    /// Precision is specified when the `libm` feature is enabled.
186    #[inline(always)]
187    pub fn sinh(x: f32) -> f32 {
188        f32::sinh(x)
189    }
190
191    /// Hyperbolic cosine function.
192    ///
193    /// Precision is specified when the `libm` feature is enabled.
194    #[inline(always)]
195    pub fn cosh(x: f32) -> f32 {
196        f32::cosh(x)
197    }
198
199    /// Hyperbolic tangent function.
200    ///
201    /// Precision is specified when the `libm` feature is enabled.
202    #[inline(always)]
203    pub fn tanh(x: f32) -> f32 {
204        f32::tanh(x)
205    }
206
207    /// Inverse hyperbolic sine function.
208    ///
209    /// Precision is specified when the `libm` feature is enabled.
210    #[inline(always)]
211    pub fn asinh(x: f32) -> f32 {
212        f32::asinh(x)
213    }
214
215    /// Inverse hyperbolic cosine function.
216    ///
217    /// Precision is specified when the `libm` feature is enabled.
218    #[inline(always)]
219    pub fn acosh(x: f32) -> f32 {
220        f32::acosh(x)
221    }
222
223    /// Inverse hyperbolic tangent function.
224    ///
225    /// Precision is specified when the `libm` feature is enabled.
226    #[inline(always)]
227    pub fn atanh(x: f32) -> f32 {
228        f32::atanh(x)
229    }
230}
231
232#[cfg(feature = "libm")]
233mod libm_ops {
234
235    /// Raises a number to a floating point power.
236    ///
237    /// Precision is specified when the `libm` feature is enabled.
238    #[inline(always)]
239    pub fn powf(x: f32, y: f32) -> f32 {
240        libm::powf(x, y)
241    }
242
243    /// Returns `e^(self)`, (the exponential function).
244    ///
245    /// Precision is specified when the `libm` feature is enabled.
246    #[inline(always)]
247    pub fn exp(x: f32) -> f32 {
248        libm::expf(x)
249    }
250
251    /// Returns `2^(self)`.
252    ///
253    /// Precision is specified when the `libm` feature is enabled.
254    #[inline(always)]
255    pub fn exp2(x: f32) -> f32 {
256        libm::exp2f(x)
257    }
258
259    /// Returns the natural logarithm of the number.
260    ///
261    /// Precision is specified when the `libm` feature is enabled.
262    #[inline(always)]
263    pub fn ln(x: f32) -> f32 {
264        // This isn't documented in `libm` but this is actually the base e logarithm.
265        libm::logf(x)
266    }
267
268    /// Returns the base 2 logarithm of the number.
269    ///
270    /// Precision is specified when the `libm` feature is enabled.
271    #[inline(always)]
272    pub fn log2(x: f32) -> f32 {
273        libm::log2f(x)
274    }
275
276    /// Returns the base 10 logarithm of the number.
277    ///
278    /// Precision is specified when the `libm` feature is enabled.
279    #[inline(always)]
280    pub fn log10(x: f32) -> f32 {
281        libm::log10f(x)
282    }
283
284    /// Returns the cube root of a number.
285    ///
286    /// Precision is specified when the `libm` feature is enabled.
287    #[inline(always)]
288    pub fn cbrt(x: f32) -> f32 {
289        libm::cbrtf(x)
290    }
291
292    /// Compute the distance between the origin and a point `(x, y)` on the Euclidean plane.
293    ///
294    /// Equivalently, compute the length of the hypotenuse of a right-angle triangle with other sides having length `x.abs()` and `y.abs()`.
295    ///
296    /// Precision is specified when the `libm` feature is enabled.
297    #[inline(always)]
298    pub fn hypot(x: f32, y: f32) -> f32 {
299        libm::hypotf(x, y)
300    }
301
302    /// Computes the sine of a number (in radians).
303    ///
304    /// Precision is specified when the `libm` feature is enabled.
305    #[inline(always)]
306    pub fn sin(x: f32) -> f32 {
307        libm::sinf(x)
308    }
309
310    /// Computes the cosine of a number (in radians).
311    ///
312    /// Precision is specified when the `libm` feature is enabled.
313    #[inline(always)]
314    pub fn cos(x: f32) -> f32 {
315        libm::cosf(x)
316    }
317
318    /// Computes the tangent of a number (in radians).
319    ///
320    /// Precision is specified when the `libm` feature is enabled.
321    #[inline(always)]
322    pub fn tan(x: f32) -> f32 {
323        libm::tanf(x)
324    }
325
326    /// Computes the arcsine of a number. Return value is in radians in
327    /// the range [-pi/2, pi/2] or NaN if the number is outside the range
328    /// [-1, 1].
329    ///
330    /// Precision is specified when the `libm` feature is enabled.
331    #[inline(always)]
332    pub fn asin(x: f32) -> f32 {
333        libm::asinf(x)
334    }
335
336    /// Computes the arccosine of a number. Return value is in radians in
337    /// Hyperbolic tangent function.
338    ///
339    /// Precision is specified when the `libm` feature is enabled.
340    /// the range [0, pi] or NaN if the number is outside the range
341    /// [-1, 1].
342    ///
343    /// Precision is specified when the `libm` feature is enabled.
344    #[inline(always)]
345    pub fn acos(x: f32) -> f32 {
346        libm::acosf(x)
347    }
348
349    /// Computes the arctangent of a number. Return value is in radians in the
350    /// range [-pi/2, pi/2];
351    ///
352    /// Precision is specified when the `libm` feature is enabled.
353    #[inline(always)]
354    pub fn atan(x: f32) -> f32 {
355        libm::atanf(x)
356    }
357
358    /// Computes the four-quadrant arctangent of `y` and `x` in radians.
359    ///
360    /// * `x = 0`, `y = 0`: `0`
361    /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
362    /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
363    /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
364    ///
365    /// Precision is specified when the `libm` feature is enabled.
366    #[inline(always)]
367    pub fn atan2(y: f32, x: f32) -> f32 {
368        libm::atan2f(y, x)
369    }
370
371    /// Simultaneously computes the sine and cosine of the number, `x`. Returns
372    /// `(sin(x), cos(x))`.
373    ///
374    /// Precision is specified when the `libm` feature is enabled.
375    #[inline(always)]
376    pub fn sin_cos(x: f32) -> (f32, f32) {
377        libm::sincosf(x)
378    }
379
380    /// Returns `e^(self) - 1` in a way that is accurate even if the
381    /// number is close to zero.
382    ///
383    /// Precision is specified when the `libm` feature is enabled.
384    #[inline(always)]
385    pub fn exp_m1(x: f32) -> f32 {
386        libm::expm1f(x)
387    }
388
389    /// Returns `ln(1+n)` (natural logarithm) more accurately than if
390    /// the operations were performed separately.
391    ///
392    /// Precision is specified when the `libm` feature is enabled.
393    #[inline(always)]
394    pub fn ln_1p(x: f32) -> f32 {
395        libm::log1pf(x)
396    }
397
398    /// Hyperbolic sine function.
399    ///
400    /// Precision is specified when the `libm` feature is enabled.
401    #[inline(always)]
402    pub fn sinh(x: f32) -> f32 {
403        libm::sinhf(x)
404    }
405
406    /// Hyperbolic cosine function.
407    ///
408    /// Precision is specified when the `libm` feature is enabled.
409    #[inline(always)]
410    pub fn cosh(x: f32) -> f32 {
411        libm::coshf(x)
412    }
413
414    /// Hyperbolic tangent function.
415    ///
416    /// Precision is specified when the `libm` feature is enabled.
417    #[inline(always)]
418    pub fn tanh(x: f32) -> f32 {
419        libm::tanhf(x)
420    }
421
422    /// Inverse hyperbolic sine function.
423    ///
424    /// Precision is specified when the `libm` feature is enabled.
425    #[inline(always)]
426    pub fn asinh(x: f32) -> f32 {
427        libm::asinhf(x)
428    }
429
430    /// Inverse hyperbolic cosine function.
431    ///
432    /// Precision is specified when the `libm` feature is enabled.
433    #[inline(always)]
434    pub fn acosh(x: f32) -> f32 {
435        libm::acoshf(x)
436    }
437
438    /// Inverse hyperbolic tangent function.
439    ///
440    /// Precision is specified when the `libm` feature is enabled.
441    #[inline(always)]
442    pub fn atanh(x: f32) -> f32 {
443        libm::atanhf(x)
444    }
445}
446
447#[cfg(feature = "libm")]
448pub use libm_ops::*;
449
450#[cfg(not(feature = "libm"))]
451pub use std_ops::*;
452
453/// This extension trait covers shortfall in determinacy from the lack of a `libm` counterpart
454/// to `f32::powi`. Use this for the common small exponents.
455pub trait FloatPow {
456    /// Squares the f32
457    fn squared(self) -> Self;
458    /// Cubes the f32
459    fn cubed(self) -> Self;
460}
461
462impl FloatPow for f32 {
463    #[inline]
464    fn squared(self) -> Self {
465        self * self
466    }
467    #[inline]
468    fn cubed(self) -> Self {
469        self * self * self
470    }
471}