Skip to main content

c/
math_helpers.rs

1
2
3#[inline]
4const fn asuint(f: f32) -> u32 {
5    f.to_bits()
6}
7
8#[inline]
9const fn asfloat(i: u32) -> f32 {
10    f32::from_bits(i)
11}
12
13#[inline]
14const fn asuint64(f: f64) -> u64 {
15    f.to_bits()
16}
17
18#[inline]
19const fn asdouble(i: u64) -> f64 {
20    f64::from_bits(i)
21}
22
23#[inline]
24unsafe fn extract_words(hi: *mut u32, lo: *mut u32, d: f64) {
25    let u = asuint64(d);
26    *hi = (u >> 32) as u32;
27    *lo = u as u32;
28}
29
30#[inline]
31unsafe fn get_high_word(d: f64) -> u32 {
32    (asuint64(d) >> 32) as u32
33}
34
35#[inline]
36unsafe fn get_low_word(d: f64) -> u32 {
37    asuint64(d) as u32
38}
39
40#[inline]
41unsafe fn insert_words(d: *mut f64, hi: u32, lo: u32) {
42    *d = asdouble(((hi as u64) << 32) | (lo as u64));
43}
44
45#[inline]
46unsafe fn set_high_word(d: *mut f64, hi: u32) {
47    let lo = asuint64(*d) as u32;
48    *d = asdouble(((hi as u64) << 32) | (lo as u64));
49}
50
51#[inline]
52unsafe fn set_low_word(d: *mut f64, lo: u32) {
53    let hi = asuint64(*d) >> 32;
54    *d = asdouble((hi << 32) | (lo as u64));
55}
56
57#[inline]
58unsafe fn get_float_word(f: f32) -> u32 {
59    asuint(f)
60}
61
62#[inline]
63unsafe fn set_float_word(f: *mut f32, w: u32) {
64    *f = asfloat(w);
65}
66
67#[inline]
68fn eval_as_float(x: f32) -> f32 {
69    x
70}
71
72#[inline]
73fn eval_as_double(x: f64) -> f64 {
74    x
75}
76
77#[inline]
78fn fp_barrierf(x: f32) -> f32 {
79    unsafe { core::ptr::read_volatile(&x) }
80}
81
82#[inline]
83fn fp_barrier(x: f64) -> f64 {
84    unsafe { core::ptr::read_volatile(&x) }
85}
86
87#[inline]
88fn fp_force_evalf(x: f32) {
89    unsafe {
90        core::ptr::read_volatile(&x);
91    }
92}
93
94#[inline]
95fn fp_force_eval(x: f64) {
96    unsafe {
97        core::ptr::read_volatile(&x);
98    }
99}
100
101#[inline]
102fn fp_force_evall(x: f64) {
103    unsafe {
104        core::ptr::read_volatile(&x);
105    }
106}
107
108#[inline]
109fn force_eval<T: Copy>(x: T) {
110    unsafe {
111        core::ptr::read_volatile(&x);
112    }
113}
114
115#[inline]
116fn predict_true(x: bool) -> bool {
117    x
118}
119
120#[inline]
121fn predict_false(x: bool) -> bool {
122    x
123}
124
125
126#[inline]
127pub fn __math_invalid(x: f64) -> f64 {
128    if x.is_nan() { return x; }
129    unsafe { feraiseexcept(FE_INVALID); }
130    (x - x) / (x - x)
131}
132
133#[inline]
134pub fn __math_invalidf(x: f32) -> f32 {
135    if x.is_nan() { return x; }
136    unsafe { feraiseexcept(FE_INVALID); }
137    (x - x) / (x - x)
138}
139
140#[inline]
141pub fn __math_divzero(sign: u32) -> f64 {
142    unsafe { feraiseexcept(FE_DIVBYZERO); }
143    let x = if sign != 0 { -1.0f64 } else { 1.0f64 };
144    x / 0.0
145}
146
147#[inline]
148pub fn __math_divzerof(sign: u32) -> f32 {
149    unsafe { feraiseexcept(FE_DIVBYZERO); }
150    let x = if sign != 0 { -1.0f32 } else { 1.0f32 };
151    x / 0.0
152}
153
154#[inline]
155pub fn __math_xflow(sign: u32, y: f64) -> f64 {
156    // musl: (sign ? -y : y) * y  (preserves sign of infinity/zero)
157    if sign != 0 {
158        -y * y
159    } else {
160        y * y
161    }
162}
163
164#[inline]
165pub fn __math_xflowf(sign: u32, y: f32) -> f32 {
166    if sign != 0 {
167        -y * y
168    } else {
169        y * y
170    }
171}
172
173#[inline]
174pub fn __math_oflow(sign: u32) -> f64 {
175    unsafe { feraiseexcept(FE_OVERFLOW | FE_INEXACT); }
176    __math_xflow(sign, 1e231f64)
177}
178
179#[inline]
180pub fn __math_oflowf(sign: u32) -> f32 {
181    unsafe { feraiseexcept(FE_OVERFLOW | FE_INEXACT); }
182    __math_xflowf(sign, 1.7e38f32)
183}
184
185#[inline]
186pub fn __math_uflow(sign: u32) -> f64 {
187    unsafe { feraiseexcept(FE_UNDERFLOW | FE_INEXACT); }
188    __math_xflow(sign, 1e-231f64)
189}
190
191#[inline]
192pub fn __math_uflowf(sign: u32) -> f32 {
193    unsafe { feraiseexcept(FE_UNDERFLOW | FE_INEXACT); }
194    __math_xflowf(sign, 1.2e-38f32)
195}
196
197#[no_mangle]
198pub static mut signgam: c_int = 0;
199
200#[no_mangle]
201pub static mut __signgam: c_int = 0;
202
203pub const FP_NAN: c_int = 0;
204pub const FP_INFINITE: c_int = 1;
205pub const FP_ZERO: c_int = 2;
206pub const FP_SUBNORMAL: c_int = 3;
207pub const FP_NORMAL: c_int = 4;
208
209pub const FP_ILOGB0: c_int = -2147483648i32;
210pub const FP_ILOGBNAN: c_int = 2147483647i32;
211
212#[no_mangle]
213pub unsafe extern "C" fn __fpclassify(x: f64) -> c_int {
214    let u = asuint64(x);
215    let e = (u >> 52) & 0x7ff;
216    if e == 0 {
217        if (u << 1) != 0 { FP_SUBNORMAL } else { FP_ZERO }
218    } else if e == 0x7ff {
219        if (u << 12) != 0 { FP_NAN } else { FP_INFINITE }
220    } else {
221        FP_NORMAL
222    }
223}
224
225#[no_mangle]
226pub unsafe extern "C" fn __fpclassifyf(x: f32) -> c_int {
227    let u = asuint(x);
228    let e = (u >> 23) & 0xff;
229    if e == 0 {
230        if (u << 1) != 0 { FP_SUBNORMAL } else { FP_ZERO }
231    } else if e == 0xff {
232        if (u << 9) != 0 { FP_NAN } else { FP_INFINITE }
233    } else {
234        FP_NORMAL
235    }
236}
237
238#[no_mangle]
239pub fn __signbit(x: f64) -> c_int {
240    ((asuint64(x) >> 63) & 1) as c_int
241}
242
243#[no_mangle]
244pub fn __signbitf(x: f32) -> c_int {
245    ((asuint(x) >> 31) & 1) as c_int
246}
247
248#[inline]
249pub fn is_nan(x: f64) -> bool {
250    let u = asuint64(x);
251    ((u >> 52) & 0x7ff) == 0x7ff && (u << 12) != 0
252}
253
254#[inline]
255pub fn is_nanf(x: f32) -> bool {
256    let u = asuint(x);
257    ((u >> 23) & 0xff) == 0xff && (u << 9) != 0
258}
259
260#[inline]
261pub fn is_inf(x: f64) -> bool {
262    let u = asuint64(x);
263    ((u >> 52) & 0x7ff) == 0x7ff && (u << 12) == 0
264}
265
266#[inline]
267pub fn is_inff(x: f32) -> bool {
268    let u = asuint(x);
269    ((u >> 23) & 0xff) == 0xff && (u << 9) == 0
270}
271
272#[inline]
273pub fn is_finite(x: f64) -> bool {
274    let u = asuint64(x);
275    ((u >> 52) & 0x7ff) != 0x7ff
276}
277
278#[inline]
279pub fn is_finitef(x: f32) -> bool {
280    let u = asuint(x);
281    ((u >> 23) & 0xff) != 0xff
282}
283
284#[inline]
285pub fn toint_value() -> f64 {
286    4503599627370496.0
287}
288
289#[inline]
290pub fn tointf_value() -> f32 {
291    8388608.0f32
292}