From 69f61b414906005e7e1e4486781f0cf98d683821 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 12 Jul 2018 03:07:28 -0500 Subject: [PATCH] implement fmodf --- library/compiler-builtins/libm/src/fmodf.rs | 89 +++++++++++++++++++ library/compiler-builtins/libm/src/lib.rs | 6 ++ .../libm/test-generator/src/main.rs | 1 + 3 files changed, 96 insertions(+) create mode 100644 library/compiler-builtins/libm/src/fmodf.rs diff --git a/library/compiler-builtins/libm/src/fmodf.rs b/library/compiler-builtins/libm/src/fmodf.rs new file mode 100644 index 000000000000..a184411a1823 --- /dev/null +++ b/library/compiler-builtins/libm/src/fmodf.rs @@ -0,0 +1,89 @@ +use core::u32; + +use isnanf; + +pub fn fmodf(x: f32, y: f32) -> f32 { + let mut uxi = x.to_bits(); + let mut uyi = y.to_bits(); + let mut ex = (uxi >> 23 & 0xff) as i32; + let mut ey = (uyi >> 23 & 0xff) as i32; + let sx = uxi & 0x80000000; + let mut i; + + if uyi << 1 == 0 || isnanf(y) || ex == 0xff { + 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 << 9; + while i >> 31 == 0 { + ex -= 1; + i <<= 1; + } + + uxi <<= -ex + 1; + } else { + uxi &= u32::MAX >> 9; + uxi |= 1 << 23; + } + + if ey == 0 { + i = uyi << 9; + while i >> 31 == 0 { + ey -= 1; + i <<= 1; + } + + uyi <<= -ey + 1; + } else { + uyi &= u32::MAX >> 9; + uyi |= 1 << 23; + } + + /* x mod y */ + while ex > ey { + i = uxi - uyi; + if i >> 31 == 0 { + if i == 0 { + return 0.0 * x; + } + uxi = i; + } + uxi <<= 1; + + ex -= 1; + } + + i = uxi - uyi; + if i >> 31 == 0 { + if i == 0 { + return 0.0 * x; + } + uxi = i; + } + + while uxi >> 23 == 0 { + uxi <<= 1; + ex -= 1; + } + + /* scale result up */ + if ex > 0 { + uxi -= 1 << 23; + uxi |= (ex as u32) << 23; + } else { + uxi >>= -ex + 1; + } + uxi |= sx; + + f32::from_bits(uxi) +} diff --git a/library/compiler-builtins/libm/src/lib.rs b/library/compiler-builtins/libm/src/lib.rs index cb2110f1fb74..41c20b2dae5a 100644 --- a/library/compiler-builtins/libm/src/lib.rs +++ b/library/compiler-builtins/libm/src/lib.rs @@ -2,11 +2,13 @@ #![no_std] mod fabsf; +mod fmodf; mod powf; mod scalbnf; mod sqrtf; pub use fabsf::fabsf; +pub use fmodf::fmodf; pub use powf::powf; pub use scalbnf::scalbnf; pub use sqrtf::sqrtf; @@ -16,3 +18,7 @@ pub use sqrtf::sqrtf; pub fn _eqf(a: u32, b: u32) -> bool { (a as i32).wrapping_sub(b as i32).abs() <= 1 } + +fn isnanf(x: f32) -> bool { + x.to_bits() & 0x7fffffff > 0x7f800000 +} diff --git a/library/compiler-builtins/libm/test-generator/src/main.rs b/library/compiler-builtins/libm/test-generator/src/main.rs index c406cf340ed1..3e58f7e1a081 100644 --- a/library/compiler-builtins/libm/test-generator/src/main.rs +++ b/library/compiler-builtins/libm/test-generator/src/main.rs @@ -225,6 +225,7 @@ f32_f32! { // With signature `fn(f32, f32) -> f32` f32f32_f32! { + fmodf, powf, }