Skip to content

Commit c8aabbd

Browse files
committed
m_rust for wasm
1 parent 1434545 commit c8aabbd

File tree

5 files changed

+234
-36
lines changed

5 files changed

+234
-36
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ _bigint = ["dep:num-traits", "dep:num-integer"] # Internal feature. User must u
2222
# See also: https://github.com/python/cpython/issues/132763
2323
mul_add = []
2424

25+
# For WASM and other targets without native libm
26+
[target.'cfg(not(any(unix, windows)))'.dependencies]
27+
libm = "0.2"
28+
2529
[dependencies]
2630
libc = "0.2"
2731
num-complex = { version = "0.4", optional = true }

src/err.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ pub(crate) fn set_errno(value: i32) {
4444
unsafe {
4545
*_errno() = value;
4646
}
47-
#[cfg(all(unix, not(any(target_os = "linux", target_os = "android", target_os = "macos"))))]
47+
#[cfg(all(
48+
unix,
49+
not(any(target_os = "linux", target_os = "android", target_os = "macos"))
50+
))]
4851
unsafe {
4952
// FreeBSD, NetBSD, OpenBSD, etc. use __error()
5053
*libc::__error() = value;
@@ -73,7 +76,10 @@ pub(crate) fn get_errno() -> i32 {
7376
unsafe {
7477
*_errno()
7578
}
76-
#[cfg(all(unix, not(any(target_os = "linux", target_os = "android", target_os = "macos"))))]
79+
#[cfg(all(
80+
unix,
81+
not(any(target_os = "linux", target_os = "android", target_os = "macos"))
82+
))]
7783
unsafe {
7884
// FreeBSD, NetBSD, OpenBSD, etc. use __error()
7985
*libc::__error()

src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@ pub mod math;
55

66
// Internal modules
77
mod err;
8+
// Native libm via FFI (unix/windows)
9+
#[cfg(any(unix, windows))]
810
pub(crate) mod m;
11+
// Pure Rust libm for WASM and other targets
12+
#[cfg(not(any(unix, windows)))]
13+
#[path = "m_rust.rs"]
14+
pub(crate) mod m;
15+
#[cfg(any(unix, windows))]
916
mod m_sys;
1017
#[cfg(test)]
1118
mod test;

src/m_rust.rs

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
//! Pure Rust implementations of libm functions using the libm crate.
2+
//! Used on targets without native libm (e.g., WASM).
3+
4+
// Trigonometric functions
5+
6+
#[inline(always)]
7+
pub fn acos(n: f64) -> f64 {
8+
libm::acos(n)
9+
}
10+
11+
#[inline(always)]
12+
pub fn asin(n: f64) -> f64 {
13+
libm::asin(n)
14+
}
15+
16+
#[inline(always)]
17+
pub fn atan(n: f64) -> f64 {
18+
libm::atan(n)
19+
}
20+
21+
#[inline(always)]
22+
pub fn atan2(y: f64, x: f64) -> f64 {
23+
libm::atan2(y, x)
24+
}
25+
26+
#[inline(always)]
27+
pub fn cos(n: f64) -> f64 {
28+
libm::cos(n)
29+
}
30+
31+
#[inline(always)]
32+
pub fn sin(n: f64) -> f64 {
33+
libm::sin(n)
34+
}
35+
36+
#[inline(always)]
37+
pub fn tan(n: f64) -> f64 {
38+
libm::tan(n)
39+
}
40+
41+
// Hyperbolic functions
42+
43+
#[inline(always)]
44+
pub fn acosh(n: f64) -> f64 {
45+
libm::acosh(n)
46+
}
47+
48+
#[inline(always)]
49+
pub fn asinh(n: f64) -> f64 {
50+
libm::asinh(n)
51+
}
52+
53+
#[inline(always)]
54+
pub fn atanh(n: f64) -> f64 {
55+
libm::atanh(n)
56+
}
57+
58+
#[inline(always)]
59+
pub fn cosh(n: f64) -> f64 {
60+
libm::cosh(n)
61+
}
62+
63+
#[inline(always)]
64+
pub fn sinh(n: f64) -> f64 {
65+
libm::sinh(n)
66+
}
67+
68+
#[inline(always)]
69+
pub fn tanh(n: f64) -> f64 {
70+
libm::tanh(n)
71+
}
72+
73+
// Exponential and logarithmic functions
74+
75+
#[inline(always)]
76+
pub fn exp(n: f64) -> f64 {
77+
libm::exp(n)
78+
}
79+
80+
#[inline(always)]
81+
pub fn exp2(n: f64) -> f64 {
82+
libm::exp2(n)
83+
}
84+
85+
#[inline(always)]
86+
pub fn expm1(n: f64) -> f64 {
87+
libm::expm1(n)
88+
}
89+
90+
#[inline(always)]
91+
pub fn log(n: f64) -> f64 {
92+
libm::log(n)
93+
}
94+
95+
#[inline(always)]
96+
pub fn log10(n: f64) -> f64 {
97+
libm::log10(n)
98+
}
99+
100+
#[inline(always)]
101+
pub fn log1p(n: f64) -> f64 {
102+
libm::log1p(n)
103+
}
104+
105+
#[inline(always)]
106+
pub fn log2(n: f64) -> f64 {
107+
libm::log2(n)
108+
}
109+
110+
// Power functions
111+
112+
#[inline(always)]
113+
pub fn cbrt(n: f64) -> f64 {
114+
libm::cbrt(n)
115+
}
116+
117+
#[inline(always)]
118+
pub fn hypot(x: f64, y: f64) -> f64 {
119+
libm::hypot(x, y)
120+
}
121+
122+
#[inline(always)]
123+
pub fn pow(x: f64, y: f64) -> f64 {
124+
libm::pow(x, y)
125+
}
126+
127+
#[inline(always)]
128+
pub fn sqrt(n: f64) -> f64 {
129+
libm::sqrt(n)
130+
}
131+
132+
// Floating-point manipulation functions
133+
134+
#[inline(always)]
135+
pub fn ceil(n: f64) -> f64 {
136+
libm::ceil(n)
137+
}
138+
139+
#[inline(always)]
140+
pub fn copysign(x: f64, y: f64) -> f64 {
141+
libm::copysign(x, y)
142+
}
143+
144+
#[inline(always)]
145+
pub fn fabs(n: f64) -> f64 {
146+
libm::fabs(n)
147+
}
148+
149+
#[inline(always)]
150+
pub fn floor(n: f64) -> f64 {
151+
libm::floor(n)
152+
}
153+
154+
#[inline(always)]
155+
pub fn fmod(x: f64, y: f64) -> f64 {
156+
libm::fmod(x, y)
157+
}
158+
159+
#[inline(always)]
160+
pub fn frexp(n: f64, exp: &mut i32) -> f64 {
161+
let (mantissa, exponent) = libm::frexp(n);
162+
*exp = exponent;
163+
mantissa
164+
}
165+
166+
#[inline(always)]
167+
pub fn ldexp(x: f64, n: i32) -> f64 {
168+
libm::ldexp(x, n)
169+
}
170+
171+
#[inline(always)]
172+
pub fn modf(n: f64, iptr: &mut f64) -> f64 {
173+
let (frac, int) = libm::modf(n);
174+
*iptr = int;
175+
frac
176+
}
177+
178+
#[inline(always)]
179+
pub fn nextafter(x: f64, y: f64) -> f64 {
180+
libm::nextafter(x, y)
181+
}
182+
183+
#[inline(always)]
184+
pub fn remainder(x: f64, y: f64) -> f64 {
185+
libm::remainder(x, y)
186+
}
187+
188+
#[inline(always)]
189+
pub fn trunc(n: f64) -> f64 {
190+
libm::trunc(n)
191+
}
192+
193+
// Special functions
194+
195+
#[inline(always)]
196+
pub fn erf(n: f64) -> f64 {
197+
libm::erf(n)
198+
}
199+
200+
#[inline(always)]
201+
pub fn erfc(n: f64) -> f64 {
202+
libm::erfc(n)
203+
}
204+
205+
// Platform-specific sincos (fallback: call sin and cos separately)
206+
207+
#[cfg(feature = "complex")]
208+
#[inline(always)]
209+
pub fn sincos(x: f64) -> (f64, f64) {
210+
(libm::sin(x), libm::cos(x))
211+
}

src/m_sys.rs

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
// These symbols are all defined by `libm`,
2-
// or by `compiler-builtins` on unsupported platforms.
1+
// Raw FFI declarations for system libm.
2+
// Only available on unix/windows where native libm exists.
3+
4+
#[cfg(any(unix, windows))]
35
#[cfg_attr(unix, link(name = "m"))]
46
#[allow(dead_code)]
57
unsafe extern "C" {
@@ -45,7 +47,6 @@ unsafe extern "C" {
4547
pub fn ceil(n: f64) -> f64;
4648
pub fn copysign(x: f64, y: f64) -> f64;
4749
pub fn fabs(n: f64) -> f64;
48-
// pub fn fdim(a: f64, b: f64) -> f64;
4950
pub fn fdimf(a: f32, b: f32) -> f32;
5051
pub fn floor(n: f64) -> f64;
5152
pub fn fmod(x: f64, y: f64) -> f64;
@@ -61,38 +62,7 @@ unsafe extern "C" {
6162
pub fn erfc(n: f64) -> f64;
6263
pub fn erff(n: f32) -> f32;
6364
pub fn erfcf(n: f32) -> f32;
64-
// pub fn lgamma_r(n: f64, s: &mut i32) -> f64;
6565
#[cfg(not(target_os = "aix"))]
6666
pub fn lgammaf_r(n: f32, s: &mut i32) -> f32;
67-
// pub fn tgamma(n: f64) -> f64;
6867
pub fn tgammaf(n: f32) -> f32;
69-
70-
// pub fn acosf128(n: f128) -> f128;
71-
// pub fn asinf128(n: f128) -> f128;
72-
// pub fn atanf128(n: f128) -> f128;
73-
// pub fn atan2f128(a: f128, b: f128) -> f128;
74-
// pub fn cbrtf128(n: f128) -> f128;
75-
// pub fn coshf128(n: f128) -> f128;
76-
// pub fn expm1f128(n: f128) -> f128;
77-
// pub fn hypotf128(x: f128, y: f128) -> f128;
78-
// pub fn log1pf128(n: f128) -> f128;
79-
// pub fn sinhf128(n: f128) -> f128;
80-
// pub fn tanf128(n: f128) -> f128;
81-
// pub fn tanhf128(n: f128) -> f128;
82-
// pub fn tgammaf128(n: f128) -> f128;
83-
// pub fn lgammaf128_r(n: f128, s: &mut i32) -> f128;
84-
// pub fn erff128(n: f128) -> f128;
85-
// pub fn erfcf128(n: f128) -> f128;
86-
87-
// cfg_if::cfg_if! {
88-
// if #[cfg(not(all(target_os = "windows", target_env = "msvc", target_arch = "x86")))] {
89-
// pub fn acosf(n: f32) -> f32;
90-
// pub fn asinf(n: f32) -> f32;
91-
// pub fn atan2f(a: f32, b: f32) -> f32;
92-
// pub fn atanf(n: f32) -> f32;
93-
// pub fn coshf(n: f32) -> f32;
94-
// pub fn sinhf(n: f32) -> f32;
95-
// pub fn tanf(n: f32) -> f32;
96-
// pub fn tanhf(n: f32) -> f32;
97-
// }}
9868
}

0 commit comments

Comments
 (0)