84: Implement fmod r=japaric a=P1n3appl3

closes rust-lang/libm#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 <josephryan3.14@gmail.com>
Co-authored-by: Jorge Aparicio <jorge@japaric.io>
This commit is contained in:
bors[bot]
2018-07-14 18:51:34 +00:00
3 changed files with 83 additions and 1 deletions

View File

@@ -0,0 +1,80 @@
use core::u64;
#[inline]
pub fn fmod(x: f64, y: f64) -> f64 {
let mut uxi = x.to_bits();
let mut uyi = y.to_bits();
let mut ex = (uxi >> 52 & 0x7ff) as i64;
let mut ey = (uyi >> 52 & 0x7ff) as i64;
let sx = uxi >> 63;
let mut i;
if uyi << 1 == 0 || y.is_nan() || ex == 0x7ff {
return (x * y) / (x * y);
}
if uxi << 1 <= uyi << 1 {
if uxi << 1 == uyi << 1 {
return 0.0 * x;
}
return x;
}
/* normalize x and y */
if ex == 0 {
i = uxi << 12;
while i >> 63 == 0 {
ex -= 1;
i <<= 1;
}
uxi <<= -ex + 1;
} else {
uxi &= u64::MAX >> 12;
uxi |= 1 << 52;
}
if ey == 0 {
i = uyi << 12;
while i >> 63 == 0 {
ey -= 1;
i <<= 1;
}
uyi <<= -ey + 1;
} else {
uyi &= u64::MAX >> 12;
uyi |= 1 << 52;
}
/* x mod y */
while ex > ey {
i = uxi - uyi;
if i >> 63 == 0 {
if i == 0 {
return 0.0 * x;
}
uxi = i;
}
uxi <<= 1;
ex -= 1;
}
i = uxi - uyi;
if i >> 63 == 0 {
if i == 0 {
return 0.0 * x;
}
uxi = i;
}
while uxi >> 52 == 0 {
uxi <<= 1;
ex -= 1;
}
/* scale result */
if ex > 0 {
uxi -= 1 << 52;
uxi |= (ex as u64) << 52;
} else {
uxi >>= -ex + 1;
}
uxi |= (sx as u64) << 63;
f64::from_bits(uxi)
}

View File

@@ -19,6 +19,7 @@ mod fdim;
mod fdimf;
mod floor;
mod floorf;
mod fmod;
mod fmodf;
mod hypot;
mod hypotf;
@@ -54,6 +55,7 @@ pub use self::fdim::fdim;
pub use self::fdimf::fdimf;
pub use self::floor::floor;
pub use self::floorf::floorf;
pub use self::fmod::fmod;
pub use self::fmodf::fmodf;
pub use self::hypot::hypot;
pub use self::hypotf::hypotf;

View File

@@ -725,7 +725,7 @@ f64_f64! {
f64f64_f64! {
// atan2,
fdim,
// fmod,
fmod,
hypot,
// pow,
}