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}