//! This mod re-exports the correct versions of floating-point operations with1//! unspecified precision in the standard library depending on whether the `libm`2//! crate feature is enabled.3//!4//! All the functions here are named according to their versions in the standard5//! library.6//!7//! It also provides `no_std` compatible alternatives to certain floating-point8//! operations which are not provided in the [`core`] library.910// Note: There are some Rust methods with unspecified precision without a `libm`11// equivalent:12// - `f32::powi` (integer powers)13// - `f32::log` (logarithm with specified base)14// - `f32::abs_sub` (actually unsure if `libm` has this, but don't use it regardless)15//16// Additionally, the following nightly API functions are not presently integrated17// into this, but they would be candidates once standardized:18// - `f32::gamma`19// - `f32::ln_gamma`2021#[cfg(all(not(feature = "libm"), feature = "std"))]22#[expect(23clippy::disallowed_methods,24reason = "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."25)]26mod std_ops {2728/// Raises a number to a floating point power.29///30/// Precision is specified when the `libm` feature is enabled.31#[inline(always)]32pub fn powf(x: f32, y: f32) -> f32 {33f32::powf(x, y)34}3536/// Returns `e^(self)`, (the exponential function).37///38/// Precision is specified when the `libm` feature is enabled.39#[inline(always)]40pub fn exp(x: f32) -> f32 {41f32::exp(x)42}4344/// Returns `2^(self)`.45///46/// Precision is specified when the `libm` feature is enabled.47#[inline(always)]48pub fn exp2(x: f32) -> f32 {49f32::exp2(x)50}5152/// Returns the natural logarithm of the number.53///54/// Precision is specified when the `libm` feature is enabled.55#[inline(always)]56pub fn ln(x: f32) -> f32 {57f32::ln(x)58}5960/// Returns the base 2 logarithm of the number.61///62/// Precision is specified when the `libm` feature is enabled.63#[inline(always)]64pub fn log2(x: f32) -> f32 {65f32::log2(x)66}6768/// Returns the base 10 logarithm of the number.69///70/// Precision is specified when the `libm` feature is enabled.71#[inline(always)]72pub fn log10(x: f32) -> f32 {73f32::log10(x)74}7576/// Returns the cube root of a number.77///78/// Precision is specified when the `libm` feature is enabled.79#[inline(always)]80pub fn cbrt(x: f32) -> f32 {81f32::cbrt(x)82}8384/// Compute the distance between the origin and a point `(x, y)` on the Euclidean plane.85/// Equivalently, compute the length of the hypotenuse of a right-angle triangle with other sides having length `x.abs()` and `y.abs()`.86///87/// Precision is specified when the `libm` feature is enabled.88#[inline(always)]89pub fn hypot(x: f32, y: f32) -> f32 {90f32::hypot(x, y)91}9293/// Computes the sine of a number (in radians).94///95/// Precision is specified when the `libm` feature is enabled.96#[inline(always)]97pub fn sin(x: f32) -> f32 {98f32::sin(x)99}100101/// Computes the cosine of a number (in radians).102///103/// Precision is specified when the `libm` feature is enabled.104#[inline(always)]105pub fn cos(x: f32) -> f32 {106f32::cos(x)107}108109/// Computes the tangent of a number (in radians).110///111/// Precision is specified when the `libm` feature is enabled.112#[inline(always)]113pub fn tan(x: f32) -> f32 {114f32::tan(x)115}116117/// Computes the arcsine of a number. Return value is in radians in118/// the range [-pi/2, pi/2] or NaN if the number is outside the range119/// [-1, 1].120///121/// Precision is specified when the `libm` feature is enabled.122#[inline(always)]123pub fn asin(x: f32) -> f32 {124f32::asin(x)125}126127/// Computes the arccosine of a number. Return value is in radians in128/// the range [0, pi] or NaN if the number is outside the range129/// [-1, 1].130///131/// Precision is specified when the `libm` feature is enabled.132#[inline(always)]133pub fn acos(x: f32) -> f32 {134f32::acos(x)135}136137/// Computes the arctangent of a number. Return value is in radians in the138/// range [-pi/2, pi/2];139///140/// Precision is specified when the `libm` feature is enabled.141#[inline(always)]142pub fn atan(x: f32) -> f32 {143f32::atan(x)144}145146/// Computes the four-quadrant arctangent of `y` and `x` in radians.147///148/// * `x = 0`, `y = 0`: `0`149/// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`150/// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`151/// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`152///153/// Precision is specified when the `libm` feature is enabled.154#[inline(always)]155pub fn atan2(y: f32, x: f32) -> f32 {156f32::atan2(y, x)157}158159/// Simultaneously computes the sine and cosine of the number, `x`. Returns160/// `(sin(x), cos(x))`.161///162/// Precision is specified when the `libm` feature is enabled.163#[inline(always)]164pub fn sin_cos(x: f32) -> (f32, f32) {165f32::sin_cos(x)166}167168/// Returns `e^(self) - 1` in a way that is accurate even if the169/// number is close to zero.170///171/// Precision is specified when the `libm` feature is enabled.172#[inline(always)]173pub fn exp_m1(x: f32) -> f32 {174f32::exp_m1(x)175}176177/// Returns `ln(1+n)` (natural logarithm) more accurately than if178/// the operations were performed separately.179///180/// Precision is specified when the `libm` feature is enabled.181#[inline(always)]182pub fn ln_1p(x: f32) -> f32 {183f32::ln_1p(x)184}185186/// Hyperbolic sine function.187///188/// Precision is specified when the `libm` feature is enabled.189#[inline(always)]190pub fn sinh(x: f32) -> f32 {191f32::sinh(x)192}193194/// Hyperbolic cosine function.195///196/// Precision is specified when the `libm` feature is enabled.197#[inline(always)]198pub fn cosh(x: f32) -> f32 {199f32::cosh(x)200}201202/// Hyperbolic tangent function.203///204/// Precision is specified when the `libm` feature is enabled.205#[inline(always)]206pub fn tanh(x: f32) -> f32 {207f32::tanh(x)208}209210/// Inverse hyperbolic sine function.211///212/// Precision is specified when the `libm` feature is enabled.213#[inline(always)]214pub fn asinh(x: f32) -> f32 {215f32::asinh(x)216}217218/// Inverse hyperbolic cosine function.219///220/// Precision is specified when the `libm` feature is enabled.221#[inline(always)]222pub fn acosh(x: f32) -> f32 {223f32::acosh(x)224}225226/// Inverse hyperbolic tangent function.227///228/// Precision is specified when the `libm` feature is enabled.229#[inline(always)]230pub fn atanh(x: f32) -> f32 {231f32::atanh(x)232}233}234235#[cfg(any(feature = "libm", all(feature = "nostd-libm", not(feature = "std"))))]236mod libm_ops {237238/// Raises a number to a floating point power.239///240/// Precision is specified when the `libm` feature is enabled.241#[inline(always)]242pub fn powf(x: f32, y: f32) -> f32 {243libm::powf(x, y)244}245246/// Returns `e^(self)`, (the exponential function).247///248/// Precision is specified when the `libm` feature is enabled.249#[inline(always)]250pub fn exp(x: f32) -> f32 {251libm::expf(x)252}253254/// Returns `2^(self)`.255///256/// Precision is specified when the `libm` feature is enabled.257#[inline(always)]258pub fn exp2(x: f32) -> f32 {259libm::exp2f(x)260}261262/// Returns the natural logarithm of the number.263///264/// Precision is specified when the `libm` feature is enabled.265#[inline(always)]266pub fn ln(x: f32) -> f32 {267// This isn't documented in `libm` but this is actually the base e logarithm.268libm::logf(x)269}270271/// Returns the base 2 logarithm of the number.272///273/// Precision is specified when the `libm` feature is enabled.274#[inline(always)]275pub fn log2(x: f32) -> f32 {276libm::log2f(x)277}278279/// Returns the base 10 logarithm of the number.280///281/// Precision is specified when the `libm` feature is enabled.282#[inline(always)]283pub fn log10(x: f32) -> f32 {284libm::log10f(x)285}286287/// Returns the cube root of a number.288///289/// Precision is specified when the `libm` feature is enabled.290#[inline(always)]291pub fn cbrt(x: f32) -> f32 {292libm::cbrtf(x)293}294295/// Compute the distance between the origin and a point `(x, y)` on the Euclidean plane.296///297/// Equivalently, compute the length of the hypotenuse of a right-angle triangle with other sides having length `x.abs()` and `y.abs()`.298///299/// Precision is specified when the `libm` feature is enabled.300#[inline(always)]301pub fn hypot(x: f32, y: f32) -> f32 {302libm::hypotf(x, y)303}304305/// Computes the sine of a number (in radians).306///307/// Precision is specified when the `libm` feature is enabled.308#[inline(always)]309pub fn sin(x: f32) -> f32 {310libm::sinf(x)311}312313/// Computes the cosine of a number (in radians).314///315/// Precision is specified when the `libm` feature is enabled.316#[inline(always)]317pub fn cos(x: f32) -> f32 {318libm::cosf(x)319}320321/// Computes the tangent of a number (in radians).322///323/// Precision is specified when the `libm` feature is enabled.324#[inline(always)]325pub fn tan(x: f32) -> f32 {326libm::tanf(x)327}328329/// Computes the arcsine of a number. Return value is in radians in330/// the range [-pi/2, pi/2] or NaN if the number is outside the range331/// [-1, 1].332///333/// Precision is specified when the `libm` feature is enabled.334#[inline(always)]335pub fn asin(x: f32) -> f32 {336libm::asinf(x)337}338339/// Computes the arccosine of a number. Return value is in radians in340/// Hyperbolic tangent function.341///342/// Precision is specified when the `libm` feature is enabled.343/// the range [0, pi] or NaN if the number is outside the range344/// [-1, 1].345///346/// Precision is specified when the `libm` feature is enabled.347#[inline(always)]348pub fn acos(x: f32) -> f32 {349libm::acosf(x)350}351352/// Computes the arctangent of a number. Return value is in radians in the353/// range [-pi/2, pi/2];354///355/// Precision is specified when the `libm` feature is enabled.356#[inline(always)]357pub fn atan(x: f32) -> f32 {358libm::atanf(x)359}360361/// Computes the four-quadrant arctangent of `y` and `x` in radians.362///363/// * `x = 0`, `y = 0`: `0`364/// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`365/// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`366/// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`367///368/// Precision is specified when the `libm` feature is enabled.369#[inline(always)]370pub fn atan2(y: f32, x: f32) -> f32 {371libm::atan2f(y, x)372}373374/// Simultaneously computes the sine and cosine of the number, `x`. Returns375/// `(sin(x), cos(x))`.376///377/// Precision is specified when the `libm` feature is enabled.378#[inline(always)]379pub fn sin_cos(x: f32) -> (f32, f32) {380libm::sincosf(x)381}382383/// Returns `e^(self) - 1` in a way that is accurate even if the384/// number is close to zero.385///386/// Precision is specified when the `libm` feature is enabled.387#[inline(always)]388pub fn exp_m1(x: f32) -> f32 {389libm::expm1f(x)390}391392/// Returns `ln(1+n)` (natural logarithm) more accurately than if393/// the operations were performed separately.394///395/// Precision is specified when the `libm` feature is enabled.396#[inline(always)]397pub fn ln_1p(x: f32) -> f32 {398libm::log1pf(x)399}400401/// Hyperbolic sine function.402///403/// Precision is specified when the `libm` feature is enabled.404#[inline(always)]405pub fn sinh(x: f32) -> f32 {406libm::sinhf(x)407}408409/// Hyperbolic cosine function.410///411/// Precision is specified when the `libm` feature is enabled.412#[inline(always)]413pub fn cosh(x: f32) -> f32 {414libm::coshf(x)415}416417/// Hyperbolic tangent function.418///419/// Precision is specified when the `libm` feature is enabled.420#[inline(always)]421pub fn tanh(x: f32) -> f32 {422libm::tanhf(x)423}424425/// Inverse hyperbolic sine function.426///427/// Precision is specified when the `libm` feature is enabled.428#[inline(always)]429pub fn asinh(x: f32) -> f32 {430libm::asinhf(x)431}432433/// Inverse hyperbolic cosine function.434///435/// Precision is specified when the `libm` feature is enabled.436#[inline(always)]437pub fn acosh(x: f32) -> f32 {438libm::acoshf(x)439}440441/// Inverse hyperbolic tangent function.442///443/// Precision is specified when the `libm` feature is enabled.444#[inline(always)]445pub fn atanh(x: f32) -> f32 {446libm::atanhf(x)447}448}449450#[cfg(all(any(feature = "libm", feature = "nostd-libm"), not(feature = "std")))]451mod libm_ops_for_no_std {452//! Provides standardized names for [`f32`] operations which may not be453//! supported on `no_std` platforms.454//! On `no_std` platforms, this forwards to the implementations provided455//! by [`libm`].456457/// Calculates the least nonnegative remainder of `self (mod rhs)`.458///459/// Precision is specified when the `libm` feature is enabled.460#[inline(always)]461pub fn rem_euclid(x: f32, y: f32) -> f32 {462let result = libm::remainderf(x, y);463464// libm::remainderf has a range of -y/2 to +y/2465if result < 0. {466result + y467} else {468result469}470}471472/// Computes the absolute value of x.473///474/// Precision is specified when the `libm` feature is enabled.475#[inline(always)]476pub fn abs(x: f32) -> f32 {477libm::fabsf(x)478}479480/// Returns the square root of a number.481///482/// Precision is specified when the `libm` feature is enabled.483#[inline(always)]484pub fn sqrt(x: f32) -> f32 {485libm::sqrtf(x)486}487488/// Returns a number composed of the magnitude of `x` and the sign of `y`.489///490/// Precision is specified when the `libm` feature is enabled.491#[inline(always)]492pub fn copysign(x: f32, y: f32) -> f32 {493libm::copysignf(x, y)494}495496/// Returns the nearest integer to `x`. If a value is half-way between two integers, round away from `0.0`.497///498/// Precision is specified when the `libm` feature is enabled.499#[inline(always)]500pub fn round(x: f32) -> f32 {501libm::roundf(x)502}503504/// Returns the largest integer less than or equal to `x`.505///506/// Precision is specified when the `libm` feature is enabled.507#[inline(always)]508pub fn floor(x: f32) -> f32 {509libm::floorf(x)510}511512/// Returns the smallest integer greater than or equal to `x`.513///514/// Precision is specified when the `libm` feature is enabled.515#[inline(always)]516pub fn ceil(x: f32) -> f32 {517libm::ceilf(x)518}519520/// Returns the fractional part of `x`.521///522/// This function always returns the precise result.523#[inline(always)]524pub fn fract(x: f32) -> f32 {525libm::modff(x).0526}527}528529#[cfg(feature = "std")]530#[expect(531clippy::disallowed_methods,532reason = "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."533)]534mod std_ops_for_no_std {535//! Provides standardized names for [`f32`] operations which may not be536//! supported on `no_std` platforms.537//! On `std` platforms, this forwards directly to the implementations provided538//! by [`std`].539540/// Calculates the least nonnegative remainder of `x (mod y)`.541///542/// The result of this operation is guaranteed to be the rounded infinite-precision result.543#[inline(always)]544pub fn rem_euclid(x: f32, y: f32) -> f32 {545f32::rem_euclid(x, y)546}547548/// Computes the absolute value of x.549///550/// This function always returns the precise result.551#[inline(always)]552pub fn abs(x: f32) -> f32 {553f32::abs(x)554}555556/// Returns the square root of a number.557///558/// The result of this operation is guaranteed to be the rounded infinite-precision result.559/// It is specified by IEEE 754 as `squareRoot` and guaranteed not to change.560#[inline(always)]561pub fn sqrt(x: f32) -> f32 {562f32::sqrt(x)563}564565/// Returns a number composed of the magnitude of `x` and the sign of `y`.566///567/// Equal to `x` if the sign of `x` and `y` are the same, otherwise equal to `-x`. If `x` is a568/// `NaN`, then a `NaN` with the sign bit of `y` is returned. Note, however, that conserving the569/// sign bit on `NaN` across arithmetical operations is not generally guaranteed.570#[inline(always)]571pub fn copysign(x: f32, y: f32) -> f32 {572f32::copysign(x, y)573}574575/// Returns the nearest integer to `x`. If a value is half-way between two integers, round away from `0.0`.576///577/// This function always returns the precise result.578#[inline(always)]579pub fn round(x: f32) -> f32 {580f32::round(x)581}582583/// Returns the largest integer less than or equal to `x`.584///585/// This function always returns the precise result.586#[inline(always)]587pub fn floor(x: f32) -> f32 {588f32::floor(x)589}590591/// Returns the smallest integer greater than or equal to `x`.592///593/// This function always returns the precise result.594#[inline(always)]595pub fn ceil(x: f32) -> f32 {596f32::ceil(x)597}598599/// Returns the fractional part of `x`.600///601/// This function always returns the precise result.602#[inline(always)]603pub fn fract(x: f32) -> f32 {604f32::fract(x)605}606}607608#[cfg(any(feature = "libm", all(feature = "nostd-libm", not(feature = "std"))))]609pub use libm_ops::*;610611#[cfg(all(not(feature = "libm"), feature = "std"))]612pub use std_ops::*;613614#[cfg(feature = "std")]615pub use std_ops_for_no_std::*;616617#[cfg(all(any(feature = "libm", feature = "nostd-libm"), not(feature = "std")))]618pub use libm_ops_for_no_std::*;619620#[cfg(all(621not(feature = "libm"),622not(feature = "std"),623not(feature = "nostd-libm")624))]625compile_error!("Either the `libm`, `std`, or `nostd-libm` feature must be enabled.");626627/// This extension trait covers shortfall in determinacy from the lack of a `libm` counterpart628/// to `f32::powi`. Use this for the common small exponents.629pub trait FloatPow {630/// Squares the f32631fn squared(self) -> Self;632/// Cubes the f32633fn cubed(self) -> Self;634}635636impl FloatPow for f32 {637#[inline]638fn squared(self) -> Self {639self * self640}641#[inline]642fn cubed(self) -> Self {643self * self * self644}645}646647648