Skip to main content

irithyll_core/
math.rs

1//! Platform-agnostic f64 math operations.
2//!
3//! In `std` mode, these delegate to inherent f64 methods (zero overhead).
4//! In `no_std` mode, these use `libm` (pure Rust software implementations).
5//!
6//! This module exists because f64 inherent methods (.sqrt(), .exp(), etc.)
7//! are not available in no_std on MSRV 1.75.
8
9// NOTE: We always use libm functions regardless of std feature.
10// On std targets, LLVM will optimize these to the same native instructions.
11// This avoids conditional compilation complexity and ensures identical behavior.
12
13/// Absolute value.
14#[inline]
15pub fn abs(x: f64) -> f64 {
16    libm::fabs(x)
17}
18
19/// Square root.
20#[inline]
21pub fn sqrt(x: f64) -> f64 {
22    libm::sqrt(x)
23}
24
25/// Natural exponential (e^x).
26#[inline]
27pub fn exp(x: f64) -> f64 {
28    libm::exp(x)
29}
30
31/// Natural logarithm (ln).
32#[inline]
33pub fn ln(x: f64) -> f64 {
34    libm::log(x)
35}
36
37/// Base-2 logarithm.
38#[inline]
39pub fn log2(x: f64) -> f64 {
40    libm::log2(x)
41}
42
43/// Base-10 logarithm.
44#[inline]
45pub fn log10(x: f64) -> f64 {
46    libm::log10(x)
47}
48
49/// Power: x^n (floating point exponent).
50#[inline]
51pub fn powf(x: f64, n: f64) -> f64 {
52    libm::pow(x, n)
53}
54
55/// Power: x^n (integer exponent).
56#[inline]
57pub fn powi(x: f64, n: i32) -> f64 {
58    libm::pow(x, n as f64)
59}
60
61/// Sine.
62#[inline]
63pub fn sin(x: f64) -> f64 {
64    libm::sin(x)
65}
66
67/// Cosine.
68#[inline]
69pub fn cos(x: f64) -> f64 {
70    libm::cos(x)
71}
72
73/// Floor.
74#[inline]
75pub fn floor(x: f64) -> f64 {
76    libm::floor(x)
77}
78
79/// Ceil.
80#[inline]
81pub fn ceil(x: f64) -> f64 {
82    libm::ceil(x)
83}
84
85/// Round to nearest integer.
86#[inline]
87pub fn round(x: f64) -> f64 {
88    libm::round(x)
89}
90
91/// Hyperbolic tangent.
92#[inline]
93pub fn tanh(x: f64) -> f64 {
94    libm::tanh(x)
95}
96
97/// Minimum of two f64 values (handles NaN: returns the non-NaN value).
98#[inline]
99pub fn fmin(x: f64, y: f64) -> f64 {
100    libm::fmin(x, y)
101}
102
103/// Maximum of two f64 values (handles NaN: returns the non-NaN value).
104#[inline]
105pub fn fmax(x: f64, y: f64) -> f64 {
106    libm::fmax(x, y)
107}
108
109/// Error function.
110#[inline]
111pub fn erf(x: f64) -> f64 {
112    libm::erf(x)
113}
114
115/// f32 absolute value.
116#[inline]
117pub fn abs_f32(x: f32) -> f32 {
118    libm::fabsf(x)
119}
120
121/// f32 square root.
122#[inline]
123pub fn sqrt_f32(x: f32) -> f32 {
124    libm::sqrtf(x)
125}
126
127#[cfg(test)]
128mod tests {
129    use super::*;
130
131    #[test]
132    fn sqrt_of_4() {
133        assert!((sqrt(4.0) - 2.0).abs() < 1e-15);
134    }
135
136    #[test]
137    fn exp_of_0() {
138        assert!((exp(0.0) - 1.0).abs() < 1e-15);
139    }
140
141    #[test]
142    fn ln_of_e() {
143        assert!((ln(core::f64::consts::E) - 1.0).abs() < 1e-15);
144    }
145
146    #[test]
147    fn abs_negative() {
148        assert_eq!(abs(-5.0), 5.0);
149        assert_eq!(abs(5.0), 5.0);
150        assert_eq!(abs(0.0), 0.0);
151    }
152
153    #[test]
154    fn powf_squares() {
155        assert!((powf(3.0, 2.0) - 9.0).abs() < 1e-15);
156    }
157
158    #[test]
159    fn powi_cubes() {
160        assert!((powi(2.0, 3) - 8.0).abs() < 1e-15);
161    }
162
163    #[test]
164    fn sin_cos_identity() {
165        let x = 1.0;
166        let s = sin(x);
167        let c = cos(x);
168        assert!((s * s + c * c - 1.0).abs() < 1e-15);
169    }
170
171    #[test]
172    fn floor_ceil_round() {
173        assert_eq!(floor(2.7), 2.0);
174        assert_eq!(ceil(2.3), 3.0);
175        assert_eq!(round(2.5), 3.0);
176        assert_eq!(round(2.4), 2.0);
177    }
178
179    #[test]
180    fn log2_of_8() {
181        assert!((log2(8.0) - 3.0).abs() < 1e-15);
182    }
183
184    #[test]
185    fn tanh_of_0() {
186        assert!((tanh(0.0)).abs() < 1e-15);
187    }
188
189    #[test]
190    fn fmin_fmax() {
191        assert_eq!(fmin(1.0, 2.0), 1.0);
192        assert_eq!(fmax(1.0, 2.0), 2.0);
193    }
194}