Skip to main content

c/
math_bitmanip.rs

1#[inline]
2fn p2d(e: i32) -> f64 {
3    f64::from_bits(((0x3ff + e) as u64) << 52)
4}
5
6#[inline]
7fn p2f(e: i32) -> f32 {
8    f32::from_bits(((0x7f + e) as u32) << 23)
9}
10
11#[no_mangle]
12pub extern "C" fn fabs(x: f64) -> f64 {
13    f64::from_bits(x.to_bits() & ((-1i64 as u64) / 2))
14}
15
16#[no_mangle]
17pub extern "C" fn fabsf(x: f32) -> f32 {
18    f32::from_bits(x.to_bits() & 0x7fffffff)
19}
20
21#[no_mangle]
22pub extern "C" fn copysign(x: f64, y: f64) -> f64 {
23    let mut ux = x.to_bits();
24    ux &= (-1i64 as u64) / 2;
25    ux |= y.to_bits() & (1u64 << 63);
26    f64::from_bits(ux)
27}
28
29#[no_mangle]
30pub extern "C" fn copysignf(x: f32, y: f32) -> f32 {
31    let mut ux = x.to_bits();
32    ux &= 0x7fffffff;
33    ux |= y.to_bits() & 0x80000000;
34    f32::from_bits(ux)
35}
36
37#[no_mangle]
38pub extern "C" fn trunc(x: f64) -> f64 {
39    let ix = x.to_bits();
40    let mut e = ((ix >> 52) & 0x7ff) as i32 - 0x3ff + 12;
41
42    if e >= 52 + 12 {
43        return x;
44    }
45    if e < 12 {
46        e = 1;
47    }
48    let m = (-1i64 as u64) >> e;
49    if (ix & m) == 0 {
50        return x;
51    }
52    force_eval(x + p2d(120));
53    f64::from_bits(ix & !m)
54}
55
56#[no_mangle]
57pub extern "C" fn truncf(x: f32) -> f32 {
58    let ix = x.to_bits();
59    let mut e = ((ix >> 23) & 0xff) as i32 - 0x7f + 9;
60
61    if e >= 23 + 9 {
62        return x;
63    }
64    if e < 9 {
65        e = 1;
66    }
67    let m = (-1i32 as u32) >> e;
68    if (ix & m) == 0 {
69        return x;
70    }
71    force_eval(x + p2f(120));
72    f32::from_bits(ix & !m)
73}
74
75#[no_mangle]
76pub extern "C" fn floor(x: f64) -> f64 {
77    let ix = x.to_bits();
78    let e = ((ix >> 52) & 0x7ff) as i32;
79
80    if e >= 0x3ff + 52 || x == 0.0 {
81        return x;
82    }
83    let y = if ix >> 63 != 0 {
84        x - p2d(52) + p2d(52) - x
85    } else {
86        x + p2d(52) - p2d(52) - x
87    };
88    if e <= 0x3ff - 1 {
89        force_eval(y);
90        return if ix >> 63 != 0 { -1.0 } else { 0.0 };
91    }
92    if y > 0.0 {
93        x + y - 1.0
94    } else {
95        x + y
96    }
97}
98
99#[no_mangle]
100pub extern "C" fn floorf(x: f32) -> f32 {
101    let mut ix = x.to_bits();
102    let e = ((ix >> 23) & 0xff) as i32 - 0x7f;
103
104    if e >= 23 {
105        return x;
106    }
107    if e >= 0 {
108        let m = 0x007fffff >> e;
109        if (ix & m) == 0 {
110            return x;
111        }
112        force_eval(x + p2f(120));
113        if ix >> 31 != 0 {
114            ix += m;
115        }
116        ix &= !m;
117    } else {
118        force_eval(x + p2f(120));
119        if ix >> 31 == 0 {
120            ix = 0;
121        } else if ix << 1 != 0 {
122            return -1.0f32;
123        }
124    }
125    f32::from_bits(ix)
126}
127
128#[no_mangle]
129pub extern "C" fn ceil(x: f64) -> f64 {
130    let ix = x.to_bits();
131    let e = ((ix >> 52) & 0x7ff) as i32;
132
133    if e >= 0x3ff + 52 || x == 0.0 {
134        return x;
135    }
136    let y = if ix >> 63 != 0 {
137        x - p2d(52) + p2d(52) - x
138    } else {
139        x + p2d(52) - p2d(52) - x
140    };
141    if e <= 0x3ff - 1 {
142        force_eval(y);
143        return if ix >> 63 != 0 { -0.0 } else { 1.0 };
144    }
145    if y < 0.0 {
146        x + y + 1.0
147    } else {
148        x + y
149    }
150}
151
152#[no_mangle]
153pub extern "C" fn ceilf(x: f32) -> f32 {
154    let mut ix = x.to_bits();
155    let e = ((ix >> 23) & 0xff) as i32 - 0x7f;
156
157    if e >= 23 {
158        return x;
159    }
160    if e >= 0 {
161        let m = 0x007fffff >> e;
162        if (ix & m) == 0 {
163            return x;
164        }
165        force_eval(x + p2f(120));
166        if ix >> 31 == 0 {
167            ix += m;
168        }
169        ix &= !m;
170    } else {
171        force_eval(x + p2f(120));
172        if ix >> 31 != 0 {
173            return -0.0f32;
174        } else if ix << 1 != 0 {
175            return 1.0f32;
176        }
177    }
178    f32::from_bits(ix)
179}
180
181#[no_mangle]
182pub extern "C" fn round(x: f64) -> f64 {
183    let ix = x.to_bits();
184    let e = ((ix >> 52) & 0x7ff) as i32;
185    let mut ax = x;
186
187    if e >= 0x3ff + 52 {
188        return x;
189    }
190    let neg = ix >> 63 != 0;
191    if neg {
192        ax = -ax;
193    }
194    if e < 0x3ff - 1 {
195        force_eval(ax + p2d(52));
196        return 0.0 * x;
197    }
198    let y = ax + p2d(52) - p2d(52) - ax;
199    let y = if y > 0.5 {
200        y + ax - 1.0
201    } else if y <= -0.5 {
202        y + ax + 1.0
203    } else {
204        y + ax
205    };
206    if neg { -y } else { y }
207}
208
209#[no_mangle]
210pub extern "C" fn roundf(x: f32) -> f32 {
211    let ix = x.to_bits();
212    let e = ((ix >> 23) & 0xff) as i32;
213    let mut ax = x;
214
215    if e >= 0x7f + 23 {
216        return x;
217    }
218    let neg = ix >> 31 != 0;
219    if neg {
220        ax = -ax;
221    }
222    if e < 0x7f - 1 {
223        force_eval(ax + p2f(23));
224        return 0.0f32 * x;
225    }
226    let y = ax + p2f(23) - p2f(23) - ax;
227    let y = if y > 0.5f32 {
228        y + ax - 1.0f32
229    } else if y <= -0.5f32 {
230        y + ax + 1.0f32
231    } else {
232        y + ax
233    };
234    if neg { -y } else { y }
235}
236
237#[no_mangle]
238pub extern "C" fn scalbn(x: f64, n: c_int) -> f64 {
239    let mut y = x;
240    let mut n = n;
241
242    if n > 1023 {
243        y *= p2d(1023);
244        n -= 1023;
245        if n > 1023 {
246            y *= p2d(1023);
247            n -= 1023;
248            if n > 1023 {
249                n = 1023;
250            }
251        }
252    } else if n < -1022 {
253        y *= p2d(-1022) * p2d(53);
254        n += 1022 - 53;
255        if n < -1022 {
256            y *= p2d(-1022) * p2d(53);
257            n += 1022 - 53;
258            if n < -1022 {
259                n = -1022;
260            }
261        }
262    }
263    f64::from_bits(((0x3ff + n) as u64) << 52) * y
264}
265
266#[no_mangle]
267pub extern "C" fn scalbnf(x: f32, n: c_int) -> f32 {
268    let mut y = x;
269    let mut n = n;
270
271    if n > 127 {
272        y *= p2f(127);
273        n -= 127;
274        if n > 127 {
275            y *= p2f(127);
276            n -= 127;
277            if n > 127 {
278                n = 127;
279            }
280        }
281    } else if n < -126 {
282        y *= p2f(-126) * p2f(24);
283        n += 126 - 24;
284        if n < -126 {
285            y *= p2f(-126) * p2f(24);
286            n += 126 - 24;
287            if n < -126 {
288                n = -126;
289            }
290        }
291    }
292    f32::from_bits(((0x7f + n) as u32) << 23) * y
293}
294
295#[no_mangle]
296pub extern "C" fn scalbln(x: f64, n: c_long) -> f64 {
297    let n = if n > c_int::MAX as c_long {
298        c_int::MAX
299    } else if n < c_int::MIN as c_long {
300        c_int::MIN
301    } else {
302        n as c_int
303    };
304    scalbn(x, n)
305}
306
307#[no_mangle]
308pub extern "C" fn scalblnf(x: f32, n: c_long) -> f32 {
309    let n = if n > c_int::MAX as c_long {
310        c_int::MAX
311    } else if n < c_int::MIN as c_long {
312        c_int::MIN
313    } else {
314        n as c_int
315    };
316    scalbnf(x, n)
317}
318
319#[no_mangle]
320pub extern "C" fn ldexp(x: f64, n: c_int) -> f64 {
321    scalbn(x, n)
322}
323
324#[no_mangle]
325pub extern "C" fn ldexpf(x: f32, n: c_int) -> f32 {
326    scalbnf(x, n)
327}
328
329#[no_mangle]
330pub unsafe extern "C" fn frexp(x: f64, e: *mut c_int) -> f64 {
331    let mut ix = x.to_bits();
332    let ee = ((ix >> 52) & 0x7ff) as i32;
333
334    if ee == 0 {
335        if x != 0.0 {
336            let r = frexp(x * p2d(64), e);
337            if !e.is_null() {
338                *e -= 64;
339            }
340            return r;
341        }
342        if !e.is_null() {
343            *e = 0;
344        }
345        return x;
346    }
347    if ee == 0x7ff {
348        if !e.is_null() {
349            *e = 0;
350        }
351        return x;
352    }
353    if !e.is_null() {
354        *e = ee - 0x3fe;
355    }
356    ix &= 0x800fffffffffffffu64;
357    ix |= 0x3fe0000000000000u64;
358    f64::from_bits(ix)
359}
360
361#[no_mangle]
362pub unsafe extern "C" fn frexpf(x: f32, e: *mut c_int) -> f32 {
363    let mut ix = x.to_bits();
364    let ee = ((ix >> 23) & 0xff) as i32;
365
366    if ee == 0 {
367        if x != 0.0f32 {
368            let r = frexpf(x * p2f(64), e);
369            if !e.is_null() {
370                *e -= 64;
371            }
372            return r;
373        }
374        if !e.is_null() {
375            *e = 0;
376        }
377        return x;
378    }
379    if ee == 0xff {
380        if !e.is_null() {
381            *e = 0;
382        }
383        return x;
384    }
385    if !e.is_null() {
386        *e = ee - 0x7e;
387    }
388    ix &= 0x807fffffu32;
389    ix |= 0x3f000000u32;
390    f32::from_bits(ix)
391}
392
393#[no_mangle]
394pub unsafe extern "C" fn modf(x: f64, iptr: *mut f64) -> f64 {
395    let mut ix = x.to_bits();
396    let e = ((ix >> 52) & 0x7ff) as i32 - 0x3ff;
397
398    if e >= 52 {
399        if !iptr.is_null() {
400            *iptr = x;
401        }
402        if e == 0x400 && (ix << 12) != 0 {
403            return x;
404        }
405        return f64::from_bits(ix & (1u64 << 63));
406    }
407    if e < 0 {
408        if !iptr.is_null() {
409            *iptr = f64::from_bits(ix & (1u64 << 63));
410        }
411        return x;
412    }
413    let mask = (-1i64 as u64) >> 12 >> e;
414    if (ix & mask) == 0 {
415        if !iptr.is_null() {
416            *iptr = x;
417        }
418        return f64::from_bits(ix & (1u64 << 63));
419    }
420    ix &= !mask;
421    let i = f64::from_bits(ix);
422    if !iptr.is_null() {
423        *iptr = i;
424    }
425    x - i
426}
427
428#[no_mangle]
429pub unsafe extern "C" fn modff(x: f32, iptr: *mut f32) -> f32 {
430    let mut ix = x.to_bits();
431    let e = ((ix >> 23) & 0xff) as i32 - 0x7f;
432
433    if e >= 23 {
434        if !iptr.is_null() {
435            *iptr = x;
436        }
437        if e == 0x80 && (ix << 9) != 0 {
438            return x;
439        }
440        return f32::from_bits(ix & 0x80000000u32);
441    }
442    if e < 0 {
443        if !iptr.is_null() {
444            *iptr = f32::from_bits(ix & 0x80000000u32);
445        }
446        return x;
447    }
448    let mask = 0x007fffffu32 >> e;
449    if (ix & mask) == 0 {
450        if !iptr.is_null() {
451            *iptr = x;
452        }
453        return f32::from_bits(ix & 0x80000000u32);
454    }
455    ix &= !mask;
456    let i = f32::from_bits(ix);
457    if !iptr.is_null() {
458        *iptr = i;
459    }
460    x - i
461}