Skip to content

Commit 0b98447

Browse files
authored
Merge pull request #198 from est31/master
Partial revert of the float conversion refactor in #192
2 parents 789e8c1 + c781759 commit 0b98447

File tree

1 file changed

+128
-133
lines changed

1 file changed

+128
-133
lines changed

src/float/conv.rs

+128-133
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,83 @@
11
use float::Float;
2-
use int::{Int, CastInto};
3-
4-
fn int_to_float<I: Int, F: Float>(i: I) -> F where
5-
F::Int: CastInto<u32>,
6-
F::Int: CastInto<I>,
7-
I::UnsignedInt: CastInto<F::Int>,
8-
u32: CastInto<F::Int>,
9-
{
10-
if i == I::ZERO {
11-
return F::ZERO;
12-
}
2+
use int::Int;
133

14-
let two = I::UnsignedInt::ONE + I::UnsignedInt::ONE;
15-
let four = two + two;
16-
let mant_dig = F::SIGNIFICAND_BITS + 1;
17-
let exponent_bias = F::EXPONENT_BIAS;
4+
macro_rules! int_to_float {
5+
($i:expr, $ity:ty, $fty:ty) => ({
6+
let i = $i;
7+
if i == 0 {
8+
return 0.0
9+
}
1810

19-
let n = I::BITS;
20-
let (s, a) = i.extract_sign();
21-
let mut a = a;
11+
let mant_dig = <$fty>::SIGNIFICAND_BITS + 1;
12+
let exponent_bias = <$fty>::EXPONENT_BIAS;
2213

23-
// number of significant digits
24-
let sd = n - a.leading_zeros();
14+
let n = <$ity>::BITS;
15+
let (s, a) = i.extract_sign();
16+
let mut a = a;
2517

26-
// exponent
27-
let mut e = sd - 1;
18+
// number of significant digits
19+
let sd = n - a.leading_zeros();
2820

29-
if I::BITS < mant_dig {
30-
return F::from_parts(s,
31-
(e + exponent_bias).cast(),
32-
a.cast() << (mant_dig - e - 1));
33-
}
21+
// exponent
22+
let mut e = sd - 1;
23+
24+
if <$ity>::BITS < mant_dig {
25+
return <$fty>::from_parts(s,
26+
(e + exponent_bias) as <$fty as Float>::Int,
27+
(a as <$fty as Float>::Int) << (mant_dig - e - 1))
28+
}
3429

35-
a = if sd > mant_dig {
36-
/* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
37-
* finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
38-
* 12345678901234567890123456
39-
* 1 = msb 1 bit
40-
* P = bit MANT_DIG-1 bits to the right of 1
41-
* Q = bit MANT_DIG bits to the right of 1
42-
* R = "or" of all bits to the right of Q
43-
*/
44-
let mant_dig_plus_one = mant_dig + 1;
45-
let mant_dig_plus_two = mant_dig + 2;
46-
a = if sd == mant_dig_plus_one {
47-
a << 1
48-
} else if sd == mant_dig_plus_two {
30+
a = if sd > mant_dig {
31+
/* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
32+
* finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
33+
* 12345678901234567890123456
34+
* 1 = msb 1 bit
35+
* P = bit MANT_DIG-1 bits to the right of 1
36+
* Q = bit MANT_DIG bits to the right of 1
37+
* R = "or" of all bits to the right of Q
38+
*/
39+
let mant_dig_plus_one = mant_dig + 1;
40+
let mant_dig_plus_two = mant_dig + 2;
41+
a = if sd == mant_dig_plus_one {
42+
a << 1
43+
} else if sd == mant_dig_plus_two {
44+
a
45+
} else {
46+
(a >> (sd - mant_dig_plus_two)) as <$ity as Int>::UnsignedInt |
47+
((a & <$ity as Int>::UnsignedInt::max_value()).wrapping_shl((n + mant_dig_plus_two) - sd) != 0) as <$ity as Int>::UnsignedInt
48+
};
49+
50+
/* finish: */
51+
a |= ((a & 4) != 0) as <$ity as Int>::UnsignedInt; /* Or P into R */
52+
a += 1; /* round - this step may add a significant bit */
53+
a >>= 2; /* dump Q and R */
54+
55+
/* a is now rounded to mant_dig or mant_dig+1 bits */
56+
if (a & (1 << mant_dig)) != 0 {
57+
a >>= 1; e += 1;
58+
}
4959
a
60+
/* a is now rounded to mant_dig bits */
5061
} else {
51-
(a >> (sd - mant_dig_plus_two)) |
52-
Int::from_bool((a & I::UnsignedInt::max_value()).wrapping_shl((n + mant_dig_plus_two) - sd) != Int::ZERO)
62+
a.wrapping_shl(mant_dig - sd)
63+
/* a is now rounded to mant_dig bits */
5364
};
5465

55-
/* finish: */
56-
a |= Int::from_bool((a & four) != I::UnsignedInt::ZERO); /* Or P into R */
57-
a += Int::ONE; /* round - this step may add a significant bit */
58-
a >>= 2; /* dump Q and R */
59-
60-
/* a is now rounded to mant_dig or mant_dig+1 bits */
61-
if (a & (I::UnsignedInt::ONE << mant_dig)) != Int::ZERO {
62-
a >>= 1; e += 1;
63-
}
64-
a
65-
/* a is now rounded to mant_dig bits */
66-
} else {
67-
a.wrapping_shl(mant_dig - sd)
68-
/* a is now rounded to mant_dig bits */
69-
};
70-
71-
F::from_parts(s,
72-
(e + exponent_bias).cast(),
73-
a.cast())
66+
<$fty>::from_parts(s,
67+
(e + exponent_bias) as <$fty as Float>::Int,
68+
a as <$fty as Float>::Int)
69+
})
7470
}
7571

7672
intrinsics! {
7773
#[arm_aeabi_alias = __aeabi_i2f]
7874
pub extern "C" fn __floatsisf(i: i32) -> f32 {
79-
int_to_float(i)
75+
int_to_float!(i, i32, f32)
8076
}
8177

8278
#[arm_aeabi_alias = __aeabi_i2d]
8379
pub extern "C" fn __floatsidf(i: i32) -> f64 {
84-
int_to_float(i)
80+
int_to_float!(i, i32, f64)
8581
}
8682

8783
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))]
@@ -92,46 +88,46 @@ intrinsics! {
9288
if cfg!(target_arch = "x86_64") {
9389
i as f64
9490
} else {
95-
int_to_float(i)
91+
int_to_float!(i, i64, f64)
9692
}
9793
}
9894

9995
#[unadjusted_on_win64]
10096
pub extern "C" fn __floattisf(i: i128) -> f32 {
101-
int_to_float(i)
97+
int_to_float!(i, i128, f32)
10298
}
10399

104100
#[unadjusted_on_win64]
105101
pub extern "C" fn __floattidf(i: i128) -> f64 {
106-
int_to_float(i)
102+
int_to_float!(i, i128, f64)
107103
}
108104

109105
#[arm_aeabi_alias = __aeabi_ui2f]
110106
pub extern "C" fn __floatunsisf(i: u32) -> f32 {
111-
int_to_float(i)
107+
int_to_float!(i, u32, f32)
112108
}
113109

114110
#[arm_aeabi_alias = __aeabi_ui2d]
115111
pub extern "C" fn __floatunsidf(i: u32) -> f64 {
116-
int_to_float(i)
112+
int_to_float!(i, u32, f64)
117113
}
118114

119115
#[use_c_shim_if(all(not(target_env = "msvc"),
120116
any(target_arch = "x86",
121117
all(not(windows), target_arch = "x86_64"))))]
122118
#[arm_aeabi_alias = __aeabi_ul2d]
123119
pub extern "C" fn __floatundidf(i: u64) -> f64 {
124-
int_to_float(i)
120+
int_to_float!(i, u64, f64)
125121
}
126122

127123
#[unadjusted_on_win64]
128124
pub extern "C" fn __floatuntisf(i: u128) -> f32 {
129-
int_to_float(i)
125+
int_to_float!(i, u128, f32)
130126
}
131127

132128
#[unadjusted_on_win64]
133129
pub extern "C" fn __floatuntidf(i: u128) -> f64 {
134-
int_to_float(i)
130+
int_to_float!(i, u128, f64)
135131
}
136132
}
137133

@@ -141,116 +137,115 @@ enum Sign {
141137
Negative
142138
}
143139

144-
fn float_to_int<F: Float, I: Int>(f: F) -> I where
145-
F::Int: CastInto<u32>,
146-
F::Int: CastInto<I>,
147-
{
148-
let f = f;
149-
let fixint_min = I::min_value();
150-
let fixint_max = I::max_value();
151-
let fixint_bits = I::BITS;
152-
let fixint_unsigned = fixint_min == I::ZERO;
153-
154-
let sign_bit = F::SIGN_MASK;
155-
let significand_bits = F::SIGNIFICAND_BITS;
156-
let exponent_bias = F::EXPONENT_BIAS;
157-
//let exponent_max = F::exponent_max() as usize;
158-
159-
// Break a into sign, exponent, significand
160-
let a_rep = F::repr(f);
161-
let a_abs = a_rep & !sign_bit;
162-
163-
// this is used to work around -1 not being available for unsigned
164-
let sign = if (a_rep & sign_bit) == F::Int::ZERO { Sign::Positive } else { Sign::Negative };
165-
let mut exponent: u32 = (a_abs >> significand_bits).cast();
166-
let significand = (a_abs & F::SIGNIFICAND_MASK) | F::IMPLICIT_BIT;
167-
168-
// if < 1 or unsigned & negative
169-
if exponent < exponent_bias ||
170-
fixint_unsigned && sign == Sign::Negative {
171-
return I::ZERO;
172-
}
173-
exponent -= exponent_bias;
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;
174168

175-
// If the value is infinity, saturate.
176-
// If the value is too large for the integer type, 0.
177-
if exponent >= (if fixint_unsigned {fixint_bits} else {fixint_bits -1}) {
178-
return if sign == Sign::Positive {fixint_max} else {fixint_min}
179-
}
180-
// If 0 <= exponent < significand_bits, right shift to get the result.
181-
// Otherwise, shift left.
182-
// (sign - 1) will never overflow as negative signs are already returned as 0 for unsigned
183-
let r: I = if exponent < significand_bits {
184-
(significand >> (significand_bits - exponent)).cast()
185-
} else {
186-
(significand << (exponent - significand_bits)).cast()
187-
};
188-
189-
if sign == Sign::Negative {
190-
(!r).wrapping_add(I::ONE)
191-
} else {
192-
r
193-
}
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+
})
194189
}
195190

196191
intrinsics! {
197192
#[arm_aeabi_alias = __aeabi_f2iz]
198193
pub extern "C" fn __fixsfsi(f: f32) -> i32 {
199-
float_to_int(f)
194+
float_to_int!(f, f32, i32)
200195
}
201196

202197
#[arm_aeabi_alias = __aeabi_f2lz]
203198
pub extern "C" fn __fixsfdi(f: f32) -> i64 {
204-
float_to_int(f)
199+
float_to_int!(f, f32, i64)
205200
}
206201

207202
#[unadjusted_on_win64]
208203
pub extern "C" fn __fixsfti(f: f32) -> i128 {
209-
float_to_int(f)
204+
float_to_int!(f, f32, i128)
210205
}
211206

212207
#[arm_aeabi_alias = __aeabi_d2iz]
213208
pub extern "C" fn __fixdfsi(f: f64) -> i32 {
214-
float_to_int(f)
209+
float_to_int!(f, f64, i32)
215210
}
216211

217212
#[arm_aeabi_alias = __aeabi_d2lz]
218213
pub extern "C" fn __fixdfdi(f: f64) -> i64 {
219-
float_to_int(f)
214+
float_to_int!(f, f64, i64)
220215
}
221216

222217
#[unadjusted_on_win64]
223218
pub extern "C" fn __fixdfti(f: f64) -> i128 {
224-
float_to_int(f)
219+
float_to_int!(f, f64, i128)
225220
}
226221

227222
#[arm_aeabi_alias = __aeabi_f2uiz]
228223
pub extern "C" fn __fixunssfsi(f: f32) -> u32 {
229-
float_to_int(f)
224+
float_to_int!(f, f32, u32)
230225
}
231226

232227
#[arm_aeabi_alias = __aeabi_f2ulz]
233228
pub extern "C" fn __fixunssfdi(f: f32) -> u64 {
234-
float_to_int(f)
229+
float_to_int!(f, f32, u64)
235230
}
236231

237232
#[unadjusted_on_win64]
238233
pub extern "C" fn __fixunssfti(f: f32) -> u128 {
239-
float_to_int(f)
234+
float_to_int!(f, f32, u128)
240235
}
241236

242237
#[arm_aeabi_alias = __aeabi_d2uiz]
243238
pub extern "C" fn __fixunsdfsi(f: f64) -> u32 {
244-
float_to_int(f)
239+
float_to_int!(f, f64, u32)
245240
}
246241

247242
#[arm_aeabi_alias = __aeabi_d2ulz]
248243
pub extern "C" fn __fixunsdfdi(f: f64) -> u64 {
249-
float_to_int(f)
244+
float_to_int!(f, f64, u64)
250245
}
251246

252247
#[unadjusted_on_win64]
253248
pub extern "C" fn __fixunsdfti(f: f64) -> u128 {
254-
float_to_int(f)
249+
float_to_int!(f, f64, u128)
255250
}
256251
}

0 commit comments

Comments
 (0)