libm/math/
fmodf.rs

1use core::f32;
2use core::u32;
3
4#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
5pub fn fmodf(x: f32, y: f32) -> f32 {
6    let mut uxi = x.to_bits();
7    let mut uyi = y.to_bits();
8    let mut ex = (uxi >> 23 & 0xff) as i32;
9    let mut ey = (uyi >> 23 & 0xff) as i32;
10    let sx = uxi & 0x80000000;
11    let mut i;
12
13    if uyi << 1 == 0 || y.is_nan() || ex == 0xff {
14        return (x * y) / (x * y);
15    }
16
17    if uxi << 1 <= uyi << 1 {
18        if uxi << 1 == uyi << 1 {
19            return 0.0 * x;
20        }
21
22        return x;
23    }
24
25    /* normalize x and y */
26    if ex == 0 {
27        i = uxi << 9;
28        while i >> 31 == 0 {
29            ex -= 1;
30            i <<= 1;
31        }
32
33        uxi <<= -ex + 1;
34    } else {
35        uxi &= u32::MAX >> 9;
36        uxi |= 1 << 23;
37    }
38
39    if ey == 0 {
40        i = uyi << 9;
41        while i >> 31 == 0 {
42            ey -= 1;
43            i <<= 1;
44        }
45
46        uyi <<= -ey + 1;
47    } else {
48        uyi &= u32::MAX >> 9;
49        uyi |= 1 << 23;
50    }
51
52    /* x mod y */
53    while ex > ey {
54        i = uxi.wrapping_sub(uyi);
55        if i >> 31 == 0 {
56            if i == 0 {
57                return 0.0 * x;
58            }
59            uxi = i;
60        }
61        uxi <<= 1;
62
63        ex -= 1;
64    }
65
66    i = uxi.wrapping_sub(uyi);
67    if i >> 31 == 0 {
68        if i == 0 {
69            return 0.0 * x;
70        }
71        uxi = i;
72    }
73
74    while uxi >> 23 == 0 {
75        uxi <<= 1;
76        ex -= 1;
77    }
78
79    /* scale result up */
80    if ex > 0 {
81        uxi -= 1 << 23;
82        uxi |= (ex as u32) << 23;
83    } else {
84        uxi >>= -ex + 1;
85    }
86    uxi |= sx;
87
88    f32::from_bits(uxi)
89}