Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_math/src/ops.rs
6595 views
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
//! It also provides `no_std` compatible alternatives to certain floating-point
9
//! operations which are not provided in the [`core`] library.
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(all(not(feature = "libm"), feature = "std"))]
23
#[expect(
24
clippy::disallowed_methods,
25
reason = "Many of the disallowed methods are disallowed to force code to use the feature-conditional re-exports from this module, but this module itself is exempt from that rule."
26
)]
27
mod std_ops {
28
29
/// Raises a number to a floating point power.
30
///
31
/// Precision is specified when the `libm` feature is enabled.
32
#[inline(always)]
33
pub fn powf(x: f32, y: f32) -> f32 {
34
f32::powf(x, y)
35
}
36
37
/// Returns `e^(self)`, (the exponential function).
38
///
39
/// Precision is specified when the `libm` feature is enabled.
40
#[inline(always)]
41
pub fn exp(x: f32) -> f32 {
42
f32::exp(x)
43
}
44
45
/// Returns `2^(self)`.
46
///
47
/// Precision is specified when the `libm` feature is enabled.
48
#[inline(always)]
49
pub fn exp2(x: f32) -> f32 {
50
f32::exp2(x)
51
}
52
53
/// Returns the natural logarithm of the number.
54
///
55
/// Precision is specified when the `libm` feature is enabled.
56
#[inline(always)]
57
pub fn ln(x: f32) -> f32 {
58
f32::ln(x)
59
}
60
61
/// Returns the base 2 logarithm of the number.
62
///
63
/// Precision is specified when the `libm` feature is enabled.
64
#[inline(always)]
65
pub fn log2(x: f32) -> f32 {
66
f32::log2(x)
67
}
68
69
/// Returns the base 10 logarithm of the number.
70
///
71
/// Precision is specified when the `libm` feature is enabled.
72
#[inline(always)]
73
pub fn log10(x: f32) -> f32 {
74
f32::log10(x)
75
}
76
77
/// Returns the cube root of a number.
78
///
79
/// Precision is specified when the `libm` feature is enabled.
80
#[inline(always)]
81
pub fn cbrt(x: f32) -> f32 {
82
f32::cbrt(x)
83
}
84
85
/// Compute the distance between the origin and a point `(x, y)` on the Euclidean plane.
86
/// Equivalently, compute the length of the hypotenuse of a right-angle triangle with other sides having length `x.abs()` and `y.abs()`.
87
///
88
/// Precision is specified when the `libm` feature is enabled.
89
#[inline(always)]
90
pub fn hypot(x: f32, y: f32) -> f32 {
91
f32::hypot(x, y)
92
}
93
94
/// Computes the sine of a number (in radians).
95
///
96
/// Precision is specified when the `libm` feature is enabled.
97
#[inline(always)]
98
pub fn sin(x: f32) -> f32 {
99
f32::sin(x)
100
}
101
102
/// Computes the cosine of a number (in radians).
103
///
104
/// Precision is specified when the `libm` feature is enabled.
105
#[inline(always)]
106
pub fn cos(x: f32) -> f32 {
107
f32::cos(x)
108
}
109
110
/// Computes the tangent of a number (in radians).
111
///
112
/// Precision is specified when the `libm` feature is enabled.
113
#[inline(always)]
114
pub fn tan(x: f32) -> f32 {
115
f32::tan(x)
116
}
117
118
/// Computes the arcsine of a number. Return value is in radians in
119
/// the range [-pi/2, pi/2] or NaN if the number is outside the range
120
/// [-1, 1].
121
///
122
/// Precision is specified when the `libm` feature is enabled.
123
#[inline(always)]
124
pub fn asin(x: f32) -> f32 {
125
f32::asin(x)
126
}
127
128
/// Computes the arccosine of a number. Return value is in radians in
129
/// the range [0, pi] or NaN if the number is outside the range
130
/// [-1, 1].
131
///
132
/// Precision is specified when the `libm` feature is enabled.
133
#[inline(always)]
134
pub fn acos(x: f32) -> f32 {
135
f32::acos(x)
136
}
137
138
/// Computes the arctangent of a number. Return value is in radians in the
139
/// range [-pi/2, pi/2];
140
///
141
/// Precision is specified when the `libm` feature is enabled.
142
#[inline(always)]
143
pub fn atan(x: f32) -> f32 {
144
f32::atan(x)
145
}
146
147
/// Computes the four-quadrant arctangent of `y` and `x` in radians.
148
///
149
/// * `x = 0`, `y = 0`: `0`
150
/// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
151
/// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
152
/// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
153
///
154
/// Precision is specified when the `libm` feature is enabled.
155
#[inline(always)]
156
pub fn atan2(y: f32, x: f32) -> f32 {
157
f32::atan2(y, x)
158
}
159
160
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
161
/// `(sin(x), cos(x))`.
162
///
163
/// Precision is specified when the `libm` feature is enabled.
164
#[inline(always)]
165
pub fn sin_cos(x: f32) -> (f32, f32) {
166
f32::sin_cos(x)
167
}
168
169
/// Returns `e^(self) - 1` in a way that is accurate even if the
170
/// number is close to zero.
171
///
172
/// Precision is specified when the `libm` feature is enabled.
173
#[inline(always)]
174
pub fn exp_m1(x: f32) -> f32 {
175
f32::exp_m1(x)
176
}
177
178
/// Returns `ln(1+n)` (natural logarithm) more accurately than if
179
/// the operations were performed separately.
180
///
181
/// Precision is specified when the `libm` feature is enabled.
182
#[inline(always)]
183
pub fn ln_1p(x: f32) -> f32 {
184
f32::ln_1p(x)
185
}
186
187
/// Hyperbolic sine function.
188
///
189
/// Precision is specified when the `libm` feature is enabled.
190
#[inline(always)]
191
pub fn sinh(x: f32) -> f32 {
192
f32::sinh(x)
193
}
194
195
/// Hyperbolic cosine function.
196
///
197
/// Precision is specified when the `libm` feature is enabled.
198
#[inline(always)]
199
pub fn cosh(x: f32) -> f32 {
200
f32::cosh(x)
201
}
202
203
/// Hyperbolic tangent function.
204
///
205
/// Precision is specified when the `libm` feature is enabled.
206
#[inline(always)]
207
pub fn tanh(x: f32) -> f32 {
208
f32::tanh(x)
209
}
210
211
/// Inverse hyperbolic sine function.
212
///
213
/// Precision is specified when the `libm` feature is enabled.
214
#[inline(always)]
215
pub fn asinh(x: f32) -> f32 {
216
f32::asinh(x)
217
}
218
219
/// Inverse hyperbolic cosine function.
220
///
221
/// Precision is specified when the `libm` feature is enabled.
222
#[inline(always)]
223
pub fn acosh(x: f32) -> f32 {
224
f32::acosh(x)
225
}
226
227
/// Inverse hyperbolic tangent function.
228
///
229
/// Precision is specified when the `libm` feature is enabled.
230
#[inline(always)]
231
pub fn atanh(x: f32) -> f32 {
232
f32::atanh(x)
233
}
234
}
235
236
#[cfg(any(feature = "libm", all(feature = "nostd-libm", not(feature = "std"))))]
237
mod libm_ops {
238
239
/// Raises a number to a floating point power.
240
///
241
/// Precision is specified when the `libm` feature is enabled.
242
#[inline(always)]
243
pub fn powf(x: f32, y: f32) -> f32 {
244
libm::powf(x, y)
245
}
246
247
/// Returns `e^(self)`, (the exponential function).
248
///
249
/// Precision is specified when the `libm` feature is enabled.
250
#[inline(always)]
251
pub fn exp(x: f32) -> f32 {
252
libm::expf(x)
253
}
254
255
/// Returns `2^(self)`.
256
///
257
/// Precision is specified when the `libm` feature is enabled.
258
#[inline(always)]
259
pub fn exp2(x: f32) -> f32 {
260
libm::exp2f(x)
261
}
262
263
/// Returns the natural logarithm of the number.
264
///
265
/// Precision is specified when the `libm` feature is enabled.
266
#[inline(always)]
267
pub fn ln(x: f32) -> f32 {
268
// This isn't documented in `libm` but this is actually the base e logarithm.
269
libm::logf(x)
270
}
271
272
/// Returns the base 2 logarithm of the number.
273
///
274
/// Precision is specified when the `libm` feature is enabled.
275
#[inline(always)]
276
pub fn log2(x: f32) -> f32 {
277
libm::log2f(x)
278
}
279
280
/// Returns the base 10 logarithm of the number.
281
///
282
/// Precision is specified when the `libm` feature is enabled.
283
#[inline(always)]
284
pub fn log10(x: f32) -> f32 {
285
libm::log10f(x)
286
}
287
288
/// Returns the cube root of a number.
289
///
290
/// Precision is specified when the `libm` feature is enabled.
291
#[inline(always)]
292
pub fn cbrt(x: f32) -> f32 {
293
libm::cbrtf(x)
294
}
295
296
/// Compute the distance between the origin and a point `(x, y)` on the Euclidean plane.
297
///
298
/// Equivalently, compute the length of the hypotenuse of a right-angle triangle with other sides having length `x.abs()` and `y.abs()`.
299
///
300
/// Precision is specified when the `libm` feature is enabled.
301
#[inline(always)]
302
pub fn hypot(x: f32, y: f32) -> f32 {
303
libm::hypotf(x, y)
304
}
305
306
/// Computes the sine of a number (in radians).
307
///
308
/// Precision is specified when the `libm` feature is enabled.
309
#[inline(always)]
310
pub fn sin(x: f32) -> f32 {
311
libm::sinf(x)
312
}
313
314
/// Computes the cosine of a number (in radians).
315
///
316
/// Precision is specified when the `libm` feature is enabled.
317
#[inline(always)]
318
pub fn cos(x: f32) -> f32 {
319
libm::cosf(x)
320
}
321
322
/// Computes the tangent of a number (in radians).
323
///
324
/// Precision is specified when the `libm` feature is enabled.
325
#[inline(always)]
326
pub fn tan(x: f32) -> f32 {
327
libm::tanf(x)
328
}
329
330
/// Computes the arcsine of a number. Return value is in radians in
331
/// the range [-pi/2, pi/2] or NaN if the number is outside the range
332
/// [-1, 1].
333
///
334
/// Precision is specified when the `libm` feature is enabled.
335
#[inline(always)]
336
pub fn asin(x: f32) -> f32 {
337
libm::asinf(x)
338
}
339
340
/// Computes the arccosine of a number. Return value is in radians in
341
/// Hyperbolic tangent function.
342
///
343
/// Precision is specified when the `libm` feature is enabled.
344
/// the range [0, pi] or NaN if the number is outside the range
345
/// [-1, 1].
346
///
347
/// Precision is specified when the `libm` feature is enabled.
348
#[inline(always)]
349
pub fn acos(x: f32) -> f32 {
350
libm::acosf(x)
351
}
352
353
/// Computes the arctangent of a number. Return value is in radians in the
354
/// range [-pi/2, pi/2];
355
///
356
/// Precision is specified when the `libm` feature is enabled.
357
#[inline(always)]
358
pub fn atan(x: f32) -> f32 {
359
libm::atanf(x)
360
}
361
362
/// Computes the four-quadrant arctangent of `y` and `x` in radians.
363
///
364
/// * `x = 0`, `y = 0`: `0`
365
/// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
366
/// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
367
/// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
368
///
369
/// Precision is specified when the `libm` feature is enabled.
370
#[inline(always)]
371
pub fn atan2(y: f32, x: f32) -> f32 {
372
libm::atan2f(y, x)
373
}
374
375
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
376
/// `(sin(x), cos(x))`.
377
///
378
/// Precision is specified when the `libm` feature is enabled.
379
#[inline(always)]
380
pub fn sin_cos(x: f32) -> (f32, f32) {
381
libm::sincosf(x)
382
}
383
384
/// Returns `e^(self) - 1` in a way that is accurate even if the
385
/// number is close to zero.
386
///
387
/// Precision is specified when the `libm` feature is enabled.
388
#[inline(always)]
389
pub fn exp_m1(x: f32) -> f32 {
390
libm::expm1f(x)
391
}
392
393
/// Returns `ln(1+n)` (natural logarithm) more accurately than if
394
/// the operations were performed separately.
395
///
396
/// Precision is specified when the `libm` feature is enabled.
397
#[inline(always)]
398
pub fn ln_1p(x: f32) -> f32 {
399
libm::log1pf(x)
400
}
401
402
/// Hyperbolic sine function.
403
///
404
/// Precision is specified when the `libm` feature is enabled.
405
#[inline(always)]
406
pub fn sinh(x: f32) -> f32 {
407
libm::sinhf(x)
408
}
409
410
/// Hyperbolic cosine function.
411
///
412
/// Precision is specified when the `libm` feature is enabled.
413
#[inline(always)]
414
pub fn cosh(x: f32) -> f32 {
415
libm::coshf(x)
416
}
417
418
/// Hyperbolic tangent function.
419
///
420
/// Precision is specified when the `libm` feature is enabled.
421
#[inline(always)]
422
pub fn tanh(x: f32) -> f32 {
423
libm::tanhf(x)
424
}
425
426
/// Inverse hyperbolic sine function.
427
///
428
/// Precision is specified when the `libm` feature is enabled.
429
#[inline(always)]
430
pub fn asinh(x: f32) -> f32 {
431
libm::asinhf(x)
432
}
433
434
/// Inverse hyperbolic cosine function.
435
///
436
/// Precision is specified when the `libm` feature is enabled.
437
#[inline(always)]
438
pub fn acosh(x: f32) -> f32 {
439
libm::acoshf(x)
440
}
441
442
/// Inverse hyperbolic tangent function.
443
///
444
/// Precision is specified when the `libm` feature is enabled.
445
#[inline(always)]
446
pub fn atanh(x: f32) -> f32 {
447
libm::atanhf(x)
448
}
449
}
450
451
#[cfg(all(any(feature = "libm", feature = "nostd-libm"), not(feature = "std")))]
452
mod libm_ops_for_no_std {
453
//! Provides standardized names for [`f32`] operations which may not be
454
//! supported on `no_std` platforms.
455
//! On `no_std` platforms, this forwards to the implementations provided
456
//! by [`libm`].
457
458
/// Calculates the least nonnegative remainder of `self (mod rhs)`.
459
///
460
/// Precision is specified when the `libm` feature is enabled.
461
#[inline(always)]
462
pub fn rem_euclid(x: f32, y: f32) -> f32 {
463
let result = libm::remainderf(x, y);
464
465
// libm::remainderf has a range of -y/2 to +y/2
466
if result < 0. {
467
result + y
468
} else {
469
result
470
}
471
}
472
473
/// Computes the absolute value of x.
474
///
475
/// Precision is specified when the `libm` feature is enabled.
476
#[inline(always)]
477
pub fn abs(x: f32) -> f32 {
478
libm::fabsf(x)
479
}
480
481
/// Returns the square root of a number.
482
///
483
/// Precision is specified when the `libm` feature is enabled.
484
#[inline(always)]
485
pub fn sqrt(x: f32) -> f32 {
486
libm::sqrtf(x)
487
}
488
489
/// Returns a number composed of the magnitude of `x` and the sign of `y`.
490
///
491
/// Precision is specified when the `libm` feature is enabled.
492
#[inline(always)]
493
pub fn copysign(x: f32, y: f32) -> f32 {
494
libm::copysignf(x, y)
495
}
496
497
/// Returns the nearest integer to `x`. If a value is half-way between two integers, round away from `0.0`.
498
///
499
/// Precision is specified when the `libm` feature is enabled.
500
#[inline(always)]
501
pub fn round(x: f32) -> f32 {
502
libm::roundf(x)
503
}
504
505
/// Returns the largest integer less than or equal to `x`.
506
///
507
/// Precision is specified when the `libm` feature is enabled.
508
#[inline(always)]
509
pub fn floor(x: f32) -> f32 {
510
libm::floorf(x)
511
}
512
513
/// Returns the smallest integer greater than or equal to `x`.
514
///
515
/// Precision is specified when the `libm` feature is enabled.
516
#[inline(always)]
517
pub fn ceil(x: f32) -> f32 {
518
libm::ceilf(x)
519
}
520
521
/// Returns the fractional part of `x`.
522
///
523
/// This function always returns the precise result.
524
#[inline(always)]
525
pub fn fract(x: f32) -> f32 {
526
libm::modff(x).0
527
}
528
}
529
530
#[cfg(feature = "std")]
531
#[expect(
532
clippy::disallowed_methods,
533
reason = "Many of the disallowed methods are disallowed to force code to use the feature-conditional re-exports from this module, but this module itself is exempt from that rule."
534
)]
535
mod std_ops_for_no_std {
536
//! Provides standardized names for [`f32`] operations which may not be
537
//! supported on `no_std` platforms.
538
//! On `std` platforms, this forwards directly to the implementations provided
539
//! by [`std`].
540
541
/// Calculates the least nonnegative remainder of `x (mod y)`.
542
///
543
/// The result of this operation is guaranteed to be the rounded infinite-precision result.
544
#[inline(always)]
545
pub fn rem_euclid(x: f32, y: f32) -> f32 {
546
f32::rem_euclid(x, y)
547
}
548
549
/// Computes the absolute value of x.
550
///
551
/// This function always returns the precise result.
552
#[inline(always)]
553
pub fn abs(x: f32) -> f32 {
554
f32::abs(x)
555
}
556
557
/// Returns the square root of a number.
558
///
559
/// The result of this operation is guaranteed to be the rounded infinite-precision result.
560
/// It is specified by IEEE 754 as `squareRoot` and guaranteed not to change.
561
#[inline(always)]
562
pub fn sqrt(x: f32) -> f32 {
563
f32::sqrt(x)
564
}
565
566
/// Returns a number composed of the magnitude of `x` and the sign of `y`.
567
///
568
/// Equal to `x` if the sign of `x` and `y` are the same, otherwise equal to `-x`. If `x` is a
569
/// `NaN`, then a `NaN` with the sign bit of `y` is returned. Note, however, that conserving the
570
/// sign bit on `NaN` across arithmetical operations is not generally guaranteed.
571
#[inline(always)]
572
pub fn copysign(x: f32, y: f32) -> f32 {
573
f32::copysign(x, y)
574
}
575
576
/// Returns the nearest integer to `x`. If a value is half-way between two integers, round away from `0.0`.
577
///
578
/// This function always returns the precise result.
579
#[inline(always)]
580
pub fn round(x: f32) -> f32 {
581
f32::round(x)
582
}
583
584
/// Returns the largest integer less than or equal to `x`.
585
///
586
/// This function always returns the precise result.
587
#[inline(always)]
588
pub fn floor(x: f32) -> f32 {
589
f32::floor(x)
590
}
591
592
/// Returns the smallest integer greater than or equal to `x`.
593
///
594
/// This function always returns the precise result.
595
#[inline(always)]
596
pub fn ceil(x: f32) -> f32 {
597
f32::ceil(x)
598
}
599
600
/// Returns the fractional part of `x`.
601
///
602
/// This function always returns the precise result.
603
#[inline(always)]
604
pub fn fract(x: f32) -> f32 {
605
f32::fract(x)
606
}
607
}
608
609
#[cfg(any(feature = "libm", all(feature = "nostd-libm", not(feature = "std"))))]
610
pub use libm_ops::*;
611
612
#[cfg(all(not(feature = "libm"), feature = "std"))]
613
pub use std_ops::*;
614
615
#[cfg(feature = "std")]
616
pub use std_ops_for_no_std::*;
617
618
#[cfg(all(any(feature = "libm", feature = "nostd-libm"), not(feature = "std")))]
619
pub use libm_ops_for_no_std::*;
620
621
#[cfg(all(
622
not(feature = "libm"),
623
not(feature = "std"),
624
not(feature = "nostd-libm")
625
))]
626
compile_error!("Either the `libm`, `std`, or `nostd-libm` feature must be enabled.");
627
628
/// This extension trait covers shortfall in determinacy from the lack of a `libm` counterpart
629
/// to `f32::powi`. Use this for the common small exponents.
630
pub trait FloatPow {
631
/// Squares the f32
632
fn squared(self) -> Self;
633
/// Cubes the f32
634
fn cubed(self) -> Self;
635
}
636
637
impl FloatPow for f32 {
638
#[inline]
639
fn squared(self) -> Self {
640
self * self
641
}
642
#[inline]
643
fn cubed(self) -> Self {
644
self * self * self
645
}
646
}
647
648