Skip to content

Commit c22bd25

Browse files
bors[bot]P1n3appl3japaric
committed
84: Implement fmod r=japaric a=P1n3appl3 closes rust-lang#21 I replaced the `isnanf()` function from `fmodf()` with a call to the core function `is_nan()`. If there's a reason we needed to re-implement it then I can change that back. Also I couldn't figure out what to do in `src/lib.rs`. Is the `#[cfg(todo]` that I should be removing the one for `mod_euc()`? If so why is the equivalent one for the `f64` version still there? Co-authored-by: Joseph Ryan <[email protected]> Co-authored-by: Jorge Aparicio <[email protected]>
2 parents 857513d + 40b8b9a commit c22bd25

File tree

3 files changed

+83
-1
lines changed

3 files changed

+83
-1
lines changed

src/math/fmod.rs

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use core::u64;
2+
3+
#[inline]
4+
pub fn fmod(x: f64, y: f64) -> f64 {
5+
let mut uxi = x.to_bits();
6+
let mut uyi = y.to_bits();
7+
let mut ex = (uxi >> 52 & 0x7ff) as i64;
8+
let mut ey = (uyi >> 52 & 0x7ff) as i64;
9+
let sx = uxi >> 63;
10+
let mut i;
11+
12+
if uyi << 1 == 0 || y.is_nan() || ex == 0x7ff {
13+
return (x * y) / (x * y);
14+
}
15+
if uxi << 1 <= uyi << 1 {
16+
if uxi << 1 == uyi << 1 {
17+
return 0.0 * x;
18+
}
19+
return x;
20+
}
21+
22+
/* normalize x and y */
23+
if ex == 0 {
24+
i = uxi << 12;
25+
while i >> 63 == 0 {
26+
ex -= 1;
27+
i <<= 1;
28+
}
29+
uxi <<= -ex + 1;
30+
} else {
31+
uxi &= u64::MAX >> 12;
32+
uxi |= 1 << 52;
33+
}
34+
if ey == 0 {
35+
i = uyi << 12;
36+
while i >> 63 == 0 {
37+
ey -= 1;
38+
i <<= 1;
39+
}
40+
uyi <<= -ey + 1;
41+
} else {
42+
uyi &= u64::MAX >> 12;
43+
uyi |= 1 << 52;
44+
}
45+
46+
/* x mod y */
47+
while ex > ey {
48+
i = uxi - uyi;
49+
if i >> 63 == 0 {
50+
if i == 0 {
51+
return 0.0 * x;
52+
}
53+
uxi = i;
54+
}
55+
uxi <<= 1;
56+
ex -= 1;
57+
}
58+
i = uxi - uyi;
59+
if i >> 63 == 0 {
60+
if i == 0 {
61+
return 0.0 * x;
62+
}
63+
uxi = i;
64+
}
65+
while uxi >> 52 == 0 {
66+
uxi <<= 1;
67+
ex -= 1;
68+
}
69+
70+
/* scale result */
71+
if ex > 0 {
72+
uxi -= 1 << 52;
73+
uxi |= (ex as u64) << 52;
74+
} else {
75+
uxi >>= -ex + 1;
76+
}
77+
uxi |= (sx as u64) << 63;
78+
79+
f64::from_bits(uxi)
80+
}

src/math/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mod fdim;
1919
mod fdimf;
2020
mod floor;
2121
mod floorf;
22+
mod fmod;
2223
mod fmodf;
2324
mod hypot;
2425
mod hypotf;
@@ -54,6 +55,7 @@ pub use self::fdim::fdim;
5455
pub use self::fdimf::fdimf;
5556
pub use self::floor::floor;
5657
pub use self::floorf::floorf;
58+
pub use self::fmod::fmod;
5759
pub use self::fmodf::fmodf;
5860
pub use self::hypot::hypot;
5961
pub use self::hypotf::hypotf;

test-generator/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,7 @@ f64_f64! {
725725
f64f64_f64! {
726726
// atan2,
727727
fdim,
728-
// fmod,
728+
fmod,
729729
hypot,
730730
// pow,
731731
}

0 commit comments

Comments
 (0)