From 4b304db80d41cfee481955b55e2b95834b6e3bac Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 16 May 2024 02:59:50 -0500 Subject: [PATCH] Make float to signed int generic --- src/float/conv.rs | 135 +++++++++++++++++++--------------------------- src/float/mod.rs | 10 ++-- 2 files changed, 61 insertions(+), 84 deletions(-) diff --git a/src/float/conv.rs b/src/float/conv.rs index f57d5a83..0179a317 100644 --- a/src/float/conv.rs +++ b/src/float/conv.rs @@ -1,3 +1,5 @@ +use core::ops::Neg; + use crate::int::{CastFrom, CastInto, Int, MinInt}; use super::Float; @@ -150,12 +152,11 @@ fn float_to_unsigned_int(f: F) -> U where F: Float, U: Int, - u32: CastInto, u32: CastFrom, F::Int: CastInto, F::Int: CastFrom, { - let uint_max_exp: u32 = F::EXPONENT_BIAS + U::BITS; + let uint_max_exp: u32 = F::EXPONENT_BIAS + U::MAX.ilog2() + 1; let fbits = f.repr(); if fbits < F::ONE.repr() { @@ -166,6 +167,7 @@ where let mantissa = if U::BITS >= F::Int::BITS { U::cast_from(fbits) << (U::BITS - F::SIGNIFICAND_BITS - 1) } else { + // FIXME magic number for when we go smaller U::cast_from(fbits >> 21) }; @@ -183,6 +185,51 @@ where } } +fn float_to_signed_int(f: F) -> I +where + F: Float, + I: Int + Neg, + I::UnsignedInt: Int, + u32: CastFrom, + F::Int: CastInto, + F::Int: CastFrom, +{ + let int_max_exp: u32 = F::EXPONENT_BIAS + I::MAX.ilog2() + 1; + let fbits = f.repr() & !F::SIGN_MASK; + + if fbits < F::ONE.repr() { + // >= 0.0, < 1.0 (< 0.0 are > 1.0 in int repr) + I::ZERO + } else if fbits < F::Int::cast_from(int_max_exp) << F::SIGNIFICAND_BITS { + // >= 1, < U::max + let mantissa = if I::BITS >= F::Int::BITS { + I::UnsignedInt::cast_from(fbits) << (I::BITS - F::SIGNIFICAND_BITS - 1) + } else { + I::UnsignedInt::cast_from(fbits >> 21) + }; + + // Set the implicit 1-bit. + let m: I::UnsignedInt = I::UnsignedInt::ONE << (I::BITS - 1) | mantissa; + // Shift based on the exponent and bias. + let s: u32 = int_max_exp - u32::cast_from(fbits >> F::SIGNIFICAND_BITS); + let u: I = I::from_unsigned(m >> s); + if f.is_sign_negative() { + -u + } else { + u + } + } else if fbits <= F::EXPONENT_MASK { + // >= max (incl. inf) + if f.is_sign_negative() { + I::MIN + } else { + I::MAX + } + } else { + I::ZERO + } +} + // Conversions from floats to unsigned integers. intrinsics! { #[arm_aeabi_alias = __aeabi_f2uiz] @@ -220,103 +267,31 @@ intrinsics! { intrinsics! { #[arm_aeabi_alias = __aeabi_f2iz] pub extern "C" fn __fixsfsi(f: f32) -> i32 { - let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. - if fbits < 127 << 23 { // >= 0, < 1 - 0 - } else if fbits < 158 << 23 { // >= 1, < max - let m = 1 << 31 | fbits << 8; // Mantissa and the implicit 1-bit. - let s = 158 - (fbits >> 23); // Shift based on the exponent and bias. - let u = (m >> s) as i32; // Unsigned result. - if f.is_sign_negative() { -u } else { u } - } else if fbits <= 255 << 23 { // >= max (incl. inf) - if f.is_sign_negative() { i32::MIN } else { i32::MAX } - } else { // NaN - 0 - } + float_to_signed_int(f) } #[arm_aeabi_alias = __aeabi_f2lz] pub extern "C" fn __fixsfdi(f: f32) -> i64 { - let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. - if fbits < 127 << 23 { // >= 0, < 1 - 0 - } else if fbits < 190 << 23 { // >= 1, < max - let m = 1 << 63 | (fbits as u64) << 40; // Mantissa and the implicit 1-bit. - let s = 190 - (fbits >> 23); // Shift based on the exponent and bias. - let u = (m >> s) as i64; // Unsigned result. - if f.is_sign_negative() { -u } else { u } - } else if fbits <= 255 << 23 { // >= max (incl. inf) - if f.is_sign_negative() { i64::MIN } else { i64::MAX } - } else { // NaN - 0 - } + float_to_signed_int(f) } #[win64_128bit_abi_hack] pub extern "C" fn __fixsfti(f: f32) -> i128 { - let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. - if fbits < 127 << 23 { // >= 0, < 1 - 0 - } else if fbits < 254 << 23 { // >= 1, < max - let m = 1 << 127 | (fbits as u128) << 104; // Mantissa and the implicit 1-bit. - let s = 254 - (fbits >> 23); // Shift based on the exponent and bias. - let u = (m >> s) as i128; // Unsigned result. - if f.is_sign_negative() { -u } else { u } - } else if fbits <= 255 << 23 { // >= max (incl. inf) - if f.is_sign_negative() { i128::MIN } else { i128::MAX } - } else { // NaN - 0 - } + float_to_signed_int(f) } #[arm_aeabi_alias = __aeabi_d2iz] pub extern "C" fn __fixdfsi(f: f64) -> i32 { - let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. - if fbits < 1023 << 52 { // >= 0, < 1 - 0 - } else if fbits < 1054 << 52 { // >= 1, < max - let m = 1 << 31 | (fbits >> 21) as u32; // Mantissa and the implicit 1-bit. - let s = 1054 - (fbits >> 52); // Shift based on the exponent and bias. - let u = (m >> s) as i32; // Unsigned result. - if f.is_sign_negative() { -u } else { u } - } else if fbits <= 2047 << 52 { // >= max (incl. inf) - if f.is_sign_negative() { i32::MIN } else { i32::MAX } - } else { // NaN - 0 - } + float_to_signed_int(f) } #[arm_aeabi_alias = __aeabi_d2lz] pub extern "C" fn __fixdfdi(f: f64) -> i64 { - let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. - if fbits < 1023 << 52 { // >= 0, < 1 - 0 - } else if fbits < 1086 << 52 { // >= 1, < max - let m = 1 << 63 | fbits << 11; // Mantissa and the implicit 1-bit. - let s = 1086 - (fbits >> 52); // Shift based on the exponent and bias. - let u = (m >> s) as i64; // Unsigned result. - if f.is_sign_negative() { -u } else { u } - } else if fbits <= 2047 << 52 { // >= max (incl. inf) - if f.is_sign_negative() { i64::MIN } else { i64::MAX } - } else { // NaN - 0 - } + float_to_signed_int(f) } #[win64_128bit_abi_hack] pub extern "C" fn __fixdfti(f: f64) -> i128 { - let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. - if fbits < 1023 << 52 { // >= 0, < 1 - 0 - } else if fbits < 1150 << 52 { // >= 1, < max - let m = 1 << 127 | (fbits as u128) << 75; // Mantissa and the implicit 1-bit. - let s = 1150 - (fbits >> 52); // Shift based on the exponent and bias. - let u = (m >> s) as i128; // Unsigned result. - if f.is_sign_negative() { -u } else { u } - } else if fbits <= 2047 << 52 { // >= max (incl. inf) - if f.is_sign_negative() { i128::MIN } else { i128::MAX } - } else { // NaN - 0 - } + float_to_signed_int(f) } } diff --git a/src/float/mod.rs b/src/float/mod.rs index e62a3fe0..de32c31a 100644 --- a/src/float/mod.rs +++ b/src/float/mod.rs @@ -80,8 +80,8 @@ pub(crate) trait Float: /// compared. fn eq_repr(self, rhs: Self) -> bool; - /// Returns the sign bit - fn sign(self) -> bool; + /// Returns true if the sign is negative + fn is_sign_negative(self) -> bool; /// Returns the exponent with bias fn exp(self) -> Self::ExpInt; @@ -103,6 +103,8 @@ pub(crate) trait Float: /// Returns if `self` is subnormal fn is_subnormal(self) -> bool; + + } } @@ -150,8 +152,8 @@ macro_rules! float_impl { self.repr() == rhs.repr() } } - fn sign(self) -> bool { - self.signed_repr() < Self::SignedInt::ZERO + fn is_sign_negative(self) -> bool { + self.is_sign_negative() } fn exp(self) -> Self::ExpInt { ((self.to_bits() & Self::EXPONENT_MASK) >> Self::SIGNIFICAND_BITS) as Self::ExpInt