Skip to content

Commit ff63f7b

Browse files
committed
Convert float_to_int! into a function
1 parent a272d75 commit ff63f7b

File tree

2 files changed

+88
-62
lines changed

2 files changed

+88
-62
lines changed

src/float/conv.rs

+63-62
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use float::Float;
2-
use int::Int;
2+
use int::{Int, CastInto};
33

44
macro_rules! int_to_float {
55
($i:expr, $ity:ty, $fty:ty) => ({
@@ -137,115 +137,116 @@ enum Sign {
137137
Negative
138138
}
139139

140-
macro_rules! float_to_int {
141-
($f:expr, $fty:ty, $ity:ty) => ({
142-
let f = $f;
143-
let fixint_min = <$ity>::min_value();
144-
let fixint_max = <$ity>::max_value();
145-
let fixint_bits = <$ity>::BITS as usize;
146-
let fixint_unsigned = fixint_min == 0;
147-
148-
let sign_bit = <$fty>::SIGN_MASK;
149-
let significand_bits = <$fty>::SIGNIFICAND_BITS as usize;
150-
let exponent_bias = <$fty>::EXPONENT_BIAS as usize;
151-
//let exponent_max = <$fty>::exponent_max() as usize;
152-
153-
// Break a into sign, exponent, significand
154-
let a_rep = <$fty>::repr(f);
155-
let a_abs = a_rep & !sign_bit;
156-
157-
// this is used to work around -1 not being available for unsigned
158-
let sign = if (a_rep & sign_bit) == 0 { Sign::Positive } else { Sign::Negative };
159-
let mut exponent = (a_abs >> significand_bits) as usize;
160-
let significand = (a_abs & <$fty>::SIGNIFICAND_MASK) | <$fty>::IMPLICIT_BIT;
161-
162-
// if < 1 or unsigned & negative
163-
if exponent < exponent_bias ||
164-
fixint_unsigned && sign == Sign::Negative {
165-
return 0
166-
}
167-
exponent -= exponent_bias;
168-
169-
// If the value is infinity, saturate.
170-
// If the value is too large for the integer type, 0.
171-
if exponent >= (if fixint_unsigned {fixint_bits} else {fixint_bits -1}) {
172-
return if sign == Sign::Positive {fixint_max} else {fixint_min}
173-
}
174-
// If 0 <= exponent < significand_bits, right shift to get the result.
175-
// Otherwise, shift left.
176-
// (sign - 1) will never overflow as negative signs are already returned as 0 for unsigned
177-
let r = if exponent < significand_bits {
178-
(significand >> (significand_bits - exponent)) as $ity
179-
} else {
180-
(significand as $ity) << (exponent - significand_bits)
181-
};
182-
183-
if sign == Sign::Negative {
184-
(!r).wrapping_add(1)
185-
} else {
186-
r
187-
}
188-
})
140+
fn float_to_int<F: Float, I: Int>(f: F) -> I where
141+
F::Int: CastInto<u32>,
142+
F::Int: CastInto<I>,
143+
{
144+
let f = f;
145+
let fixint_min = I::min_value();
146+
let fixint_max = I::max_value();
147+
let fixint_bits = I::BITS;
148+
let fixint_unsigned = fixint_min == I::ZERO;
149+
150+
let sign_bit = F::SIGN_MASK;
151+
let significand_bits = F::SIGNIFICAND_BITS;
152+
let exponent_bias = F::EXPONENT_BIAS;
153+
//let exponent_max = F::exponent_max() as usize;
154+
155+
// Break a into sign, exponent, significand
156+
let a_rep = F::repr(f);
157+
let a_abs = a_rep & !sign_bit;
158+
159+
// this is used to work around -1 not being available for unsigned
160+
let sign = if (a_rep & sign_bit) == F::Int::ZERO { Sign::Positive } else { Sign::Negative };
161+
let mut exponent: u32 = (a_abs >> significand_bits).cast();
162+
let significand = (a_abs & F::SIGNIFICAND_MASK) | F::IMPLICIT_BIT;
163+
164+
// if < 1 or unsigned & negative
165+
if exponent < exponent_bias ||
166+
fixint_unsigned && sign == Sign::Negative {
167+
return I::ZERO;
168+
}
169+
exponent -= exponent_bias;
170+
171+
// If the value is infinity, saturate.
172+
// If the value is too large for the integer type, 0.
173+
if exponent >= (if fixint_unsigned {fixint_bits} else {fixint_bits -1}) {
174+
return if sign == Sign::Positive {fixint_max} else {fixint_min}
175+
}
176+
// If 0 <= exponent < significand_bits, right shift to get the result.
177+
// Otherwise, shift left.
178+
// (sign - 1) will never overflow as negative signs are already returned as 0 for unsigned
179+
let r: I = if exponent < significand_bits {
180+
(significand >> (significand_bits - exponent)).cast()
181+
} else {
182+
(significand << (exponent - significand_bits)).cast()
183+
};
184+
185+
if sign == Sign::Negative {
186+
(!r).wrapping_add(I::ONE)
187+
} else {
188+
r
189+
}
189190
}
190191

191192
intrinsics! {
192193
#[arm_aeabi_alias = __aeabi_f2iz]
193194
pub extern "C" fn __fixsfsi(f: f32) -> i32 {
194-
float_to_int!(f, f32, i32)
195+
float_to_int(f)
195196
}
196197

197198
#[arm_aeabi_alias = __aeabi_f2lz]
198199
pub extern "C" fn __fixsfdi(f: f32) -> i64 {
199-
float_to_int!(f, f32, i64)
200+
float_to_int(f)
200201
}
201202

202203
#[unadjusted_on_win64]
203204
pub extern "C" fn __fixsfti(f: f32) -> i128 {
204-
float_to_int!(f, f32, i128)
205+
float_to_int(f)
205206
}
206207

207208
#[arm_aeabi_alias = __aeabi_d2iz]
208209
pub extern "C" fn __fixdfsi(f: f64) -> i32 {
209-
float_to_int!(f, f64, i32)
210+
float_to_int(f)
210211
}
211212

212213
#[arm_aeabi_alias = __aeabi_d2lz]
213214
pub extern "C" fn __fixdfdi(f: f64) -> i64 {
214-
float_to_int!(f, f64, i64)
215+
float_to_int(f)
215216
}
216217

217218
#[unadjusted_on_win64]
218219
pub extern "C" fn __fixdfti(f: f64) -> i128 {
219-
float_to_int!(f, f64, i128)
220+
float_to_int(f)
220221
}
221222

222223
#[arm_aeabi_alias = __aeabi_f2uiz]
223224
pub extern "C" fn __fixunssfsi(f: f32) -> u32 {
224-
float_to_int!(f, f32, u32)
225+
float_to_int(f)
225226
}
226227

227228
#[arm_aeabi_alias = __aeabi_f2ulz]
228229
pub extern "C" fn __fixunssfdi(f: f32) -> u64 {
229-
float_to_int!(f, f32, u64)
230+
float_to_int(f)
230231
}
231232

232233
#[unadjusted_on_win64]
233234
pub extern "C" fn __fixunssfti(f: f32) -> u128 {
234-
float_to_int!(f, f32, u128)
235+
float_to_int(f)
235236
}
236237

237238
#[arm_aeabi_alias = __aeabi_d2uiz]
238239
pub extern "C" fn __fixunsdfsi(f: f64) -> u32 {
239-
float_to_int!(f, f64, u32)
240+
float_to_int(f)
240241
}
241242

242243
#[arm_aeabi_alias = __aeabi_d2ulz]
243244
pub extern "C" fn __fixunsdfdi(f: f64) -> u64 {
244-
float_to_int!(f, f64, u64)
245+
float_to_int(f)
245246
}
246247

247248
#[unadjusted_on_win64]
248249
pub extern "C" fn __fixunsdfti(f: f64) -> u128 {
249-
float_to_int!(f, f64, u128)
250+
float_to_int(f)
250251
}
251252
}

src/int/mod.rs

+25
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,28 @@ large_int!(u64, u32, u32, 32);
230230
large_int!(i64, u32, i32, 32);
231231
large_int!(u128, u64, u64, 64);
232232
large_int!(i128, u64, i64, 64);
233+
234+
/// Trait to express (possibly lossy) casting of integers
235+
pub trait CastInto<T: Copy>: Copy {
236+
fn cast(self) -> T;
237+
}
238+
239+
macro_rules! cast_into {
240+
($ty:ty) => {
241+
cast_into!($ty; usize, isize, u32, i32, u64, i64, u128, i128);
242+
};
243+
($ty:ty; $($into:ty),*) => {$(
244+
impl CastInto<$into> for $ty {
245+
fn cast(self) -> $into {
246+
self as $into
247+
}
248+
}
249+
)*};
250+
}
251+
252+
cast_into!(u32);
253+
cast_into!(i32);
254+
cast_into!(u64);
255+
cast_into!(i64);
256+
cast_into!(u128);
257+
cast_into!(i128);

0 commit comments

Comments
 (0)