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}
90