Skip to content

Commit 4b304db

Browse files
committed
Make float to signed int generic
1 parent 6a33a1c commit 4b304db

File tree

2 files changed

+61
-84
lines changed

2 files changed

+61
-84
lines changed

src/float/conv.rs

+55-80
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use core::ops::Neg;
2+
13
use crate::int::{CastFrom, CastInto, Int, MinInt};
24

35
use super::Float;
@@ -150,12 +152,11 @@ fn float_to_unsigned_int<F, U>(f: F) -> U
150152
where
151153
F: Float,
152154
U: Int,
153-
u32: CastInto<F::Int>,
154155
u32: CastFrom<F::Int>,
155156
F::Int: CastInto<U>,
156157
F::Int: CastFrom<u32>,
157158
{
158-
let uint_max_exp: u32 = F::EXPONENT_BIAS + U::BITS;
159+
let uint_max_exp: u32 = F::EXPONENT_BIAS + U::MAX.ilog2() + 1;
159160
let fbits = f.repr();
160161

161162
if fbits < F::ONE.repr() {
@@ -166,6 +167,7 @@ where
166167
let mantissa = if U::BITS >= F::Int::BITS {
167168
U::cast_from(fbits) << (U::BITS - F::SIGNIFICAND_BITS - 1)
168169
} else {
170+
// FIXME magic number for when we go smaller
169171
U::cast_from(fbits >> 21)
170172
};
171173

@@ -183,6 +185,51 @@ where
183185
}
184186
}
185187

188+
fn float_to_signed_int<F, I>(f: F) -> I
189+
where
190+
F: Float,
191+
I: Int + Neg<Output = I>,
192+
I::UnsignedInt: Int,
193+
u32: CastFrom<F::Int>,
194+
F::Int: CastInto<I::UnsignedInt>,
195+
F::Int: CastFrom<u32>,
196+
{
197+
let int_max_exp: u32 = F::EXPONENT_BIAS + I::MAX.ilog2() + 1;
198+
let fbits = f.repr() & !F::SIGN_MASK;
199+
200+
if fbits < F::ONE.repr() {
201+
// >= 0.0, < 1.0 (< 0.0 are > 1.0 in int repr)
202+
I::ZERO
203+
} else if fbits < F::Int::cast_from(int_max_exp) << F::SIGNIFICAND_BITS {
204+
// >= 1, < U::max
205+
let mantissa = if I::BITS >= F::Int::BITS {
206+
I::UnsignedInt::cast_from(fbits) << (I::BITS - F::SIGNIFICAND_BITS - 1)
207+
} else {
208+
I::UnsignedInt::cast_from(fbits >> 21)
209+
};
210+
211+
// Set the implicit 1-bit.
212+
let m: I::UnsignedInt = I::UnsignedInt::ONE << (I::BITS - 1) | mantissa;
213+
// Shift based on the exponent and bias.
214+
let s: u32 = int_max_exp - u32::cast_from(fbits >> F::SIGNIFICAND_BITS);
215+
let u: I = I::from_unsigned(m >> s);
216+
if f.is_sign_negative() {
217+
-u
218+
} else {
219+
u
220+
}
221+
} else if fbits <= F::EXPONENT_MASK {
222+
// >= max (incl. inf)
223+
if f.is_sign_negative() {
224+
I::MIN
225+
} else {
226+
I::MAX
227+
}
228+
} else {
229+
I::ZERO
230+
}
231+
}
232+
186233
// Conversions from floats to unsigned integers.
187234
intrinsics! {
188235
#[arm_aeabi_alias = __aeabi_f2uiz]
@@ -220,103 +267,31 @@ intrinsics! {
220267
intrinsics! {
221268
#[arm_aeabi_alias = __aeabi_f2iz]
222269
pub extern "C" fn __fixsfsi(f: f32) -> i32 {
223-
let fbits = f.to_bits() & !0 >> 1; // Remove sign bit.
224-
if fbits < 127 << 23 { // >= 0, < 1
225-
0
226-
} else if fbits < 158 << 23 { // >= 1, < max
227-
let m = 1 << 31 | fbits << 8; // Mantissa and the implicit 1-bit.
228-
let s = 158 - (fbits >> 23); // Shift based on the exponent and bias.
229-
let u = (m >> s) as i32; // Unsigned result.
230-
if f.is_sign_negative() { -u } else { u }
231-
} else if fbits <= 255 << 23 { // >= max (incl. inf)
232-
if f.is_sign_negative() { i32::MIN } else { i32::MAX }
233-
} else { // NaN
234-
0
235-
}
270+
float_to_signed_int(f)
236271
}
237272

238273
#[arm_aeabi_alias = __aeabi_f2lz]
239274
pub extern "C" fn __fixsfdi(f: f32) -> i64 {
240-
let fbits = f.to_bits() & !0 >> 1; // Remove sign bit.
241-
if fbits < 127 << 23 { // >= 0, < 1
242-
0
243-
} else if fbits < 190 << 23 { // >= 1, < max
244-
let m = 1 << 63 | (fbits as u64) << 40; // Mantissa and the implicit 1-bit.
245-
let s = 190 - (fbits >> 23); // Shift based on the exponent and bias.
246-
let u = (m >> s) as i64; // Unsigned result.
247-
if f.is_sign_negative() { -u } else { u }
248-
} else if fbits <= 255 << 23 { // >= max (incl. inf)
249-
if f.is_sign_negative() { i64::MIN } else { i64::MAX }
250-
} else { // NaN
251-
0
252-
}
275+
float_to_signed_int(f)
253276
}
254277

255278
#[win64_128bit_abi_hack]
256279
pub extern "C" fn __fixsfti(f: f32) -> i128 {
257-
let fbits = f.to_bits() & !0 >> 1; // Remove sign bit.
258-
if fbits < 127 << 23 { // >= 0, < 1
259-
0
260-
} else if fbits < 254 << 23 { // >= 1, < max
261-
let m = 1 << 127 | (fbits as u128) << 104; // Mantissa and the implicit 1-bit.
262-
let s = 254 - (fbits >> 23); // Shift based on the exponent and bias.
263-
let u = (m >> s) as i128; // Unsigned result.
264-
if f.is_sign_negative() { -u } else { u }
265-
} else if fbits <= 255 << 23 { // >= max (incl. inf)
266-
if f.is_sign_negative() { i128::MIN } else { i128::MAX }
267-
} else { // NaN
268-
0
269-
}
280+
float_to_signed_int(f)
270281
}
271282

272283
#[arm_aeabi_alias = __aeabi_d2iz]
273284
pub extern "C" fn __fixdfsi(f: f64) -> i32 {
274-
let fbits = f.to_bits() & !0 >> 1; // Remove sign bit.
275-
if fbits < 1023 << 52 { // >= 0, < 1
276-
0
277-
} else if fbits < 1054 << 52 { // >= 1, < max
278-
let m = 1 << 31 | (fbits >> 21) as u32; // Mantissa and the implicit 1-bit.
279-
let s = 1054 - (fbits >> 52); // Shift based on the exponent and bias.
280-
let u = (m >> s) as i32; // Unsigned result.
281-
if f.is_sign_negative() { -u } else { u }
282-
} else if fbits <= 2047 << 52 { // >= max (incl. inf)
283-
if f.is_sign_negative() { i32::MIN } else { i32::MAX }
284-
} else { // NaN
285-
0
286-
}
285+
float_to_signed_int(f)
287286
}
288287

289288
#[arm_aeabi_alias = __aeabi_d2lz]
290289
pub extern "C" fn __fixdfdi(f: f64) -> i64 {
291-
let fbits = f.to_bits() & !0 >> 1; // Remove sign bit.
292-
if fbits < 1023 << 52 { // >= 0, < 1
293-
0
294-
} else if fbits < 1086 << 52 { // >= 1, < max
295-
let m = 1 << 63 | fbits << 11; // Mantissa and the implicit 1-bit.
296-
let s = 1086 - (fbits >> 52); // Shift based on the exponent and bias.
297-
let u = (m >> s) as i64; // Unsigned result.
298-
if f.is_sign_negative() { -u } else { u }
299-
} else if fbits <= 2047 << 52 { // >= max (incl. inf)
300-
if f.is_sign_negative() { i64::MIN } else { i64::MAX }
301-
} else { // NaN
302-
0
303-
}
290+
float_to_signed_int(f)
304291
}
305292

306293
#[win64_128bit_abi_hack]
307294
pub extern "C" fn __fixdfti(f: f64) -> i128 {
308-
let fbits = f.to_bits() & !0 >> 1; // Remove sign bit.
309-
if fbits < 1023 << 52 { // >= 0, < 1
310-
0
311-
} else if fbits < 1150 << 52 { // >= 1, < max
312-
let m = 1 << 127 | (fbits as u128) << 75; // Mantissa and the implicit 1-bit.
313-
let s = 1150 - (fbits >> 52); // Shift based on the exponent and bias.
314-
let u = (m >> s) as i128; // Unsigned result.
315-
if f.is_sign_negative() { -u } else { u }
316-
} else if fbits <= 2047 << 52 { // >= max (incl. inf)
317-
if f.is_sign_negative() { i128::MIN } else { i128::MAX }
318-
} else { // NaN
319-
0
320-
}
295+
float_to_signed_int(f)
321296
}
322297
}

src/float/mod.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ pub(crate) trait Float:
8080
/// compared.
8181
fn eq_repr(self, rhs: Self) -> bool;
8282

83-
/// Returns the sign bit
84-
fn sign(self) -> bool;
83+
/// Returns true if the sign is negative
84+
fn is_sign_negative(self) -> bool;
8585

8686
/// Returns the exponent with bias
8787
fn exp(self) -> Self::ExpInt;
@@ -103,6 +103,8 @@ pub(crate) trait Float:
103103

104104
/// Returns if `self` is subnormal
105105
fn is_subnormal(self) -> bool;
106+
107+
106108
}
107109
}
108110

@@ -150,8 +152,8 @@ macro_rules! float_impl {
150152
self.repr() == rhs.repr()
151153
}
152154
}
153-
fn sign(self) -> bool {
154-
self.signed_repr() < Self::SignedInt::ZERO
155+
fn is_sign_negative(self) -> bool {
156+
self.is_sign_negative()
155157
}
156158
fn exp(self) -> Self::ExpInt {
157159
((self.to_bits() & Self::EXPONENT_MASK) >> Self::SIGNIFICAND_BITS) as Self::ExpInt

0 commit comments

Comments
 (0)