use core::f32; use core::u32; #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] 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 || y.is_nan() || 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.wrapping_sub(uyi); if i >> 31 == 0 { if i == 0 { return 0.0 * x; } uxi = i; } uxi <<= 1; ex -= 1; } i = uxi.wrapping_sub(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) }