Skip to content

Commit fed121f

Browse files
committed
Add repr() and from_repr() to Float
1 parent 9d88687 commit fed121f

File tree

2 files changed

+39
-16
lines changed

2 files changed

+39
-16
lines changed

src/float/add.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
use core::mem::transmute;
2-
31
use float::Float;
42

53
macro_rules! add {
64
($intrinsic:ident: $ty:ty) => {
75
/// Returns `a + b`
6+
#[allow(unused_parens)]
87
#[cfg_attr(not(test), no_mangle)]
98
pub extern fn $intrinsic(a: $ty, b: $ty) -> $ty {
109
let bits = <$ty>::bits() as <$ty as Float>::Int;
@@ -21,8 +20,8 @@ macro_rules! add {
2120
let quiet_bit = implicit_bit >> 1;
2221
let qnan_rep = exponent_mask | quiet_bit;
2322

24-
let mut a_rep = unsafe { transmute::<_, <$ty as Float>::Int>(a) };
25-
let mut b_rep = unsafe { transmute::<_, <$ty as Float>::Int>(b) };
23+
let mut a_rep = a.repr();
24+
let mut b_rep = b.repr();
2625
let a_abs = a_rep & abs_mask;
2726
let b_abs = b_rep & abs_mask;
2827

@@ -31,17 +30,17 @@ macro_rules! add {
3130
b_abs - 1 >= inf_rep - 1 {
3231
// NaN + anything = qNaN
3332
if a_abs > inf_rep {
34-
return unsafe { transmute(transmute::<_, <$ty as Float>::Int>(a) | quiet_bit) };
33+
return (<$ty as Float>::from_repr(a_abs | quiet_bit));
3534
}
3635
// anything + NaN = qNaN
3736
if b_abs > inf_rep {
38-
return unsafe { transmute(transmute::<_, <$ty as Float>::Int>(b) | quiet_bit) };
37+
return (<$ty as Float>::from_repr(b_abs | quiet_bit));
3938
}
4039

4140
if a_abs == inf_rep {
4241
// +/-infinity + -/+infinity = qNaN
43-
if unsafe { transmute::<_, <$ty as Float>::Int>(a) ^ transmute::<_, <$ty as Float>::Int>(b) == sign_bit } {
44-
return unsafe { transmute(qnan_rep) };
42+
if a.repr() ^ b.repr() == sign_bit {
43+
return (<$ty as Float>::from_repr(qnan_rep));
4544
} else {
4645
// +/-infinity + anything remaining = +/- infinity
4746
return a;
@@ -57,7 +56,7 @@ macro_rules! add {
5756
if a_abs == 0 {
5857
// but we need to get the sign right for zero + zero
5958
if b_abs == 0 {
60-
return unsafe { transmute(transmute::<_, <$ty as Float>::Int>(a) & transmute::<_, <$ty as Float>::Int>(b)) };
59+
return (<$ty as Float>::from_repr(a.repr() & b.repr()));
6160
} else {
6261
return b;
6362
}
@@ -120,14 +119,17 @@ macro_rules! add {
120119
if subtraction {
121120
a_significand -= b_significand;
122121
// If a == -b, return +zero.
123-
if a_significand == 0 { return unsafe { transmute(0 as <$ty as Float>::Int) }; }
122+
if a_significand == 0 {
123+
return (<$ty as Float>::from_repr(0));
124+
}
124125

125126
// If partial cancellation occured, we need to left-shift the result
126127
// and adjust the exponent:
127128
if a_significand < implicit_bit << 3 {
128-
let shift = <<$ty as Float>::Int>::leading_zeros(a_significand) - <<$ty as Float>::Int>::leading_zeros(implicit_bit << 3);
129+
let shift = (a_significand.leading_zeros()
130+
- (implicit_bit << 3).leading_zeros()) as <$ty as Float>::Int;
129131
a_significand <<= shift;
130-
a_exponent -= shift as <$ty as Float>::Int;
132+
a_exponent -= shift;
131133
}
132134
} else /* addition */ {
133135
a_significand += b_significand;
@@ -142,7 +144,9 @@ macro_rules! add {
142144
}
143145

144146
// If we have overflowed the type, return +/- infinity:
145-
if a_exponent >= max_exponent { return unsafe { transmute(inf_rep | result_sign) }; }
147+
if a_exponent >= max_exponent {
148+
return (<$ty>::from_repr(inf_rep | result_sign));
149+
}
146150

147151
if a_exponent <= 0 {
148152
// Result is denormal before rounding; the exponent is zero and we
@@ -167,7 +171,7 @@ macro_rules! add {
167171
// correct result in that case.
168172
if round_guard_sticky > 0x4 { result += 1; }
169173
if round_guard_sticky == 0x4 { result += result & 1; }
170-
return unsafe { transmute(result) };
174+
return (<$ty>::from_repr(result));
171175
}
172176
}
173177
}

src/float/mod.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
use core::ops::*;
1+
use core::mem::transmute;
22
use core::num::One;
3+
use core::ops::*;
34

45
pub mod add;
56

67
/// Trait for some basic operations on floats
7-
pub trait Float {
8+
pub trait Float: Sized {
89
/// A uint of the same with as the float
910
type Int: Sized + Copy + Clone + Sub<Output=Self::Int> +
1011
ShlAssign<Self::Int> + Shl<Self::Int, Output=Self::Int> + One;
@@ -15,6 +16,12 @@ pub trait Float {
1516
/// Returns the bitwidth of the significand
1617
fn significand_bits() -> u32;
1718

19+
/// Returns `self` transmuted to `Self::Int`
20+
fn repr(self) -> Self::Int;
21+
22+
/// Returns a `Self::Int` transmuted back to `Self`
23+
fn from_repr(a: Self::Int) -> Self;
24+
1825
/// Returns (normalized exponent, normalized significand)
1926
fn normalize(significand: Self::Int) -> (Self::Int, Self::Int);
2027
}
@@ -27,6 +34,12 @@ impl Float for f32 {
2734
fn significand_bits() -> u32 {
2835
23
2936
}
37+
fn repr(self) -> Self::Int {
38+
unsafe { transmute(self) }
39+
}
40+
fn from_repr(a: Self::Int) -> Self {
41+
unsafe { transmute(a) }
42+
}
3043
fn normalize(significand: Self::Int) -> (Self::Int, Self::Int) {
3144
let shift = Self::Int::leading_zeros(significand)
3245
- Self::Int::leading_zeros(Self::Int::one() << Self::significand_bits());
@@ -41,6 +54,12 @@ impl Float for f64 {
4154
fn significand_bits() -> u32 {
4255
52
4356
}
57+
fn repr(self) -> Self::Int {
58+
unsafe { transmute(self) }
59+
}
60+
fn from_repr(a: Self::Int) -> Self {
61+
unsafe { transmute(a) }
62+
}
4463
fn normalize(significand: Self::Int) -> (Self::Int, Self::Int) {
4564
let shift = Self::Int::leading_zeros(significand)
4665
- Self::Int::leading_zeros(Self::Int::one() << Self::significand_bits());

0 commit comments

Comments
 (0)