Skip to content

Commit 482d983

Browse files
committed
Convert int_to_float! to a function
1 parent ff63f7b commit 482d983

File tree

2 files changed

+101
-67
lines changed

2 files changed

+101
-67
lines changed

src/float/conv.rs

+70-66
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,87 @@
11
use float::Float;
22
use int::{Int, CastInto};
33

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-
}
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+
}
1013

11-
let mant_dig = <$fty>::SIGNIFICAND_BITS + 1;
12-
let exponent_bias = <$fty>::EXPONENT_BIAS;
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;
1318

14-
let n = <$ity>::BITS;
15-
let (s, a) = i.extract_sign();
16-
let mut a = a;
19+
let n = I::BITS;
20+
let (s, a) = i.extract_sign();
21+
let mut a = a;
1722

18-
// number of significant digits
19-
let sd = n - a.leading_zeros();
23+
// number of significant digits
24+
let sd = n - a.leading_zeros();
2025

21-
// exponent
22-
let mut e = sd - 1;
26+
// exponent
27+
let mut e = sd - 1;
2328

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-
}
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+
}
2934

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-
}
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 {
5949
a
60-
/* a is now rounded to mant_dig bits */
6150
} else {
62-
a.wrapping_shl(mant_dig - sd)
63-
/* a is now rounded to mant_dig bits */
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)
6453
};
6554

66-
<$fty>::from_parts(s,
67-
(e + exponent_bias) as <$fty as Float>::Int,
68-
a as <$fty as Float>::Int)
69-
})
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())
7074
}
7175

7276
intrinsics! {
7377
#[arm_aeabi_alias = __aeabi_i2f]
7478
pub extern "C" fn __floatsisf(i: i32) -> f32 {
75-
int_to_float!(i, i32, f32)
79+
int_to_float(i)
7680
}
7781

7882
#[arm_aeabi_alias = __aeabi_i2d]
7983
pub extern "C" fn __floatsidf(i: i32) -> f64 {
80-
int_to_float!(i, i32, f64)
84+
int_to_float(i)
8185
}
8286

8387
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))]
@@ -88,46 +92,46 @@ intrinsics! {
8892
if cfg!(target_arch = "x86_64") {
8993
i as f64
9094
} else {
91-
int_to_float!(i, i64, f64)
95+
int_to_float(i)
9296
}
9397
}
9498

9599
#[unadjusted_on_win64]
96100
pub extern "C" fn __floattisf(i: i128) -> f32 {
97-
int_to_float!(i, i128, f32)
101+
int_to_float(i)
98102
}
99103

100104
#[unadjusted_on_win64]
101105
pub extern "C" fn __floattidf(i: i128) -> f64 {
102-
int_to_float!(i, i128, f64)
106+
int_to_float(i)
103107
}
104108

105109
#[arm_aeabi_alias = __aeabi_ui2f]
106110
pub extern "C" fn __floatunsisf(i: u32) -> f32 {
107-
int_to_float!(i, u32, f32)
111+
int_to_float(i)
108112
}
109113

110114
#[arm_aeabi_alias = __aeabi_ui2d]
111115
pub extern "C" fn __floatunsidf(i: u32) -> f64 {
112-
int_to_float!(i, u32, f64)
116+
int_to_float(i)
113117
}
114118

115119
#[use_c_shim_if(all(not(target_env = "msvc"),
116120
any(target_arch = "x86",
117121
all(not(windows), target_arch = "x86_64"))))]
118122
#[arm_aeabi_alias = __aeabi_ul2d]
119123
pub extern "C" fn __floatundidf(i: u64) -> f64 {
120-
int_to_float!(i, u64, f64)
124+
int_to_float(i)
121125
}
122126

123127
#[unadjusted_on_win64]
124128
pub extern "C" fn __floatuntisf(i: u128) -> f32 {
125-
int_to_float!(i, u128, f32)
129+
int_to_float(i)
126130
}
127131

128132
#[unadjusted_on_win64]
129133
pub extern "C" fn __floatuntidf(i: u128) -> f64 {
130-
int_to_float!(i, u128, f64)
134+
int_to_float(i)
131135
}
132136
}
133137

src/int/mod.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ pub trait Int:
2323
PartialEq +
2424
PartialOrd +
2525
ops::AddAssign +
26+
ops::BitAndAssign +
27+
ops::BitOrAssign +
28+
ops::ShrAssign<u32> +
2629
ops::Add<Output = Self> +
2730
ops::Sub<Output = Self> +
2831
ops::Div<Output = Self> +
@@ -31,7 +34,6 @@ pub trait Int:
3134
ops::BitOr<Output = Self> +
3235
ops::BitXor<Output = Self> +
3336
ops::BitAnd<Output = Self> +
34-
ops::BitAndAssign +
3537
ops::Not<Output = Self> +
3638
{
3739
/// Type with the same width but other signedness
@@ -60,14 +62,18 @@ pub trait Int:
6062
fn unsigned(self) -> Self::UnsignedInt;
6163
fn from_unsigned(unsigned: Self::UnsignedInt) -> Self;
6264

65+
fn from_bool(b: bool) -> Self;
66+
6367
// copied from primitive integers, but put in a trait
6468
fn max_value() -> Self;
6569
fn min_value() -> Self;
6670
fn wrapping_add(self, other: Self) -> Self;
6771
fn wrapping_mul(self, other: Self) -> Self;
6872
fn wrapping_sub(self, other: Self) -> Self;
73+
fn wrapping_shl(self, other: u32) -> Self;
6974
fn aborting_div(self, other: Self) -> Self;
7075
fn aborting_rem(self, other: Self) -> Self;
76+
fn leading_zeros(self) -> u32;
7177
}
7278

7379
fn unwrap<T>(t: Option<T>) -> T {
@@ -100,6 +106,10 @@ macro_rules! int_impl {
100106
me
101107
}
102108

109+
fn from_bool(b: bool) -> Self {
110+
b as $uty
111+
}
112+
103113
fn max_value() -> Self {
104114
<Self>::max_value()
105115
}
@@ -120,13 +130,21 @@ macro_rules! int_impl {
120130
<Self>::wrapping_sub(self, other)
121131
}
122132

133+
fn wrapping_shl(self, other: u32) -> Self {
134+
<Self>::wrapping_shl(self, other)
135+
}
136+
123137
fn aborting_div(self, other: Self) -> Self {
124138
unwrap(<Self>::checked_div(self, other))
125139
}
126140

127141
fn aborting_rem(self, other: Self) -> Self {
128142
unwrap(<Self>::checked_rem(self, other))
129143
}
144+
145+
fn leading_zeros(self) -> u32 {
146+
<Self>::leading_zeros(self)
147+
}
130148
}
131149

132150
impl Int for $ity {
@@ -154,6 +172,10 @@ macro_rules! int_impl {
154172
me as $ity
155173
}
156174

175+
fn from_bool(b: bool) -> Self {
176+
b as $ity
177+
}
178+
157179
fn max_value() -> Self {
158180
<Self>::max_value()
159181
}
@@ -174,13 +196,21 @@ macro_rules! int_impl {
174196
<Self>::wrapping_sub(self, other)
175197
}
176198

199+
fn wrapping_shl(self, other: u32) -> Self {
200+
<Self>::wrapping_shl(self, other)
201+
}
202+
177203
fn aborting_div(self, other: Self) -> Self {
178204
unwrap(<Self>::checked_div(self, other))
179205
}
180206

181207
fn aborting_rem(self, other: Self) -> Self {
182208
unwrap(<Self>::checked_rem(self, other))
183209
}
210+
211+
fn leading_zeros(self) -> u32 {
212+
<Self>::leading_zeros(self)
213+
}
184214
}
185215
}
186216
}

0 commit comments

Comments
 (0)