Skip to content

Commit a272d75

Browse files
committed
Don't use the Wrapping wrapper in float addition
Inspired by a patch by mattico.
1 parent 72ed4c8 commit a272d75

File tree

1 file changed

+52
-54
lines changed

1 file changed

+52
-54
lines changed

src/float/add.rs

+52-54
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use core::num::Wrapping;
2-
31
use int::Int;
42
use float::Float;
53

@@ -8,44 +6,44 @@ macro_rules! add {
86
($a:expr, $b:expr, $ty:ty) => ({
97
let a = $a;
108
let b = $b;
11-
let one = Wrapping(<$ty as Float>::Int::ONE);
12-
let zero = Wrapping(<$ty as Float>::Int::ZERO);
9+
let one = <$ty as Float>::Int::ONE;
10+
let zero = <$ty as Float>::Int::ZERO;
1311

14-
let bits = Wrapping(<$ty>::BITS as <$ty as Float>::Int);
15-
let significand_bits = Wrapping(<$ty>::SIGNIFICAND_BITS as <$ty as Float>::Int);
16-
let exponent_bits = bits - significand_bits - one;
17-
let max_exponent = (one << exponent_bits.0 as usize) - one;
12+
let bits = <$ty>::BITS as <$ty as Float>::Int;
13+
let significand_bits = <$ty>::SIGNIFICAND_BITS as <$ty as Float>::Int;
14+
let exponent_bits = <$ty>::EXPONENT_BITS as <$ty as Float>::Int;
15+
let max_exponent = (one << exponent_bits as usize) - one;
1816

19-
let implicit_bit = one << significand_bits.0 as usize;
17+
let implicit_bit = one << significand_bits as usize;
2018
let significand_mask = implicit_bit - one;
21-
let sign_bit = one << (significand_bits + exponent_bits).0 as usize;
19+
let sign_bit = <$ty>::SIGN_MASK as <$ty as Float>::Int;
2220
let abs_mask = sign_bit - one;
2321
let exponent_mask = abs_mask ^ significand_mask;
2422
let inf_rep = exponent_mask;
2523
let quiet_bit = implicit_bit >> 1;
2624
let qnan_rep = exponent_mask | quiet_bit;
2725

28-
let mut a_rep = Wrapping(a.repr());
29-
let mut b_rep = Wrapping(b.repr());
26+
let mut a_rep = a.repr();
27+
let mut b_rep = b.repr();
3028
let a_abs = a_rep & abs_mask;
3129
let b_abs = b_rep & abs_mask;
3230

3331
// Detect if a or b is zero, infinity, or NaN.
34-
if a_abs - one >= inf_rep - one ||
35-
b_abs - one >= inf_rep - one {
32+
if a_abs.wrapping_sub(one) >= inf_rep - one ||
33+
b_abs.wrapping_sub(one) >= inf_rep - one {
3634
// NaN + anything = qNaN
3735
if a_abs > inf_rep {
38-
return <$ty as Float>::from_repr((a_abs | quiet_bit).0);
36+
return <$ty as Float>::from_repr(a_abs | quiet_bit);
3937
}
4038
// anything + NaN = qNaN
4139
if b_abs > inf_rep {
42-
return <$ty as Float>::from_repr((b_abs | quiet_bit).0);
40+
return <$ty as Float>::from_repr(b_abs | quiet_bit);
4341
}
4442

4543
if a_abs == inf_rep {
4644
// +/-infinity + -/+infinity = qNaN
47-
if (a.repr() ^ b.repr()) == sign_bit.0 {
48-
return <$ty as Float>::from_repr(qnan_rep.0);
45+
if (a.repr() ^ b.repr()) == sign_bit {
46+
return <$ty as Float>::from_repr(qnan_rep);
4947
} else {
5048
// +/-infinity + anything remaining = +/- infinity
5149
return a;
@@ -58,17 +56,17 @@ macro_rules! add {
5856
}
5957

6058
// zero + anything = anything
61-
if a_abs.0 == 0 {
59+
if a_abs == 0 {
6260
// but we need to get the sign right for zero + zero
63-
if b_abs.0 == 0 {
61+
if b_abs == 0 {
6462
return <$ty as Float>::from_repr(a.repr() & b.repr());
6563
} else {
6664
return b;
6765
}
6866
}
6967

7068
// anything + zero = anything
71-
if b_abs.0 == 0 {
69+
if b_abs == 0 {
7270
return a;
7371
}
7472
}
@@ -82,21 +80,21 @@ macro_rules! add {
8280
}
8381

8482
// Extract the exponent and significand from the (possibly swapped) a and b.
85-
let mut a_exponent = Wrapping((a_rep >> significand_bits.0 as usize & max_exponent).0 as i32);
86-
let mut b_exponent = Wrapping((b_rep >> significand_bits.0 as usize & max_exponent).0 as i32);
83+
let mut a_exponent = ((a_rep >> significand_bits) & max_exponent) as i32;
84+
let mut b_exponent = ((b_rep >> significand_bits) & max_exponent) as i32;
8785
let mut a_significand = a_rep & significand_mask;
8886
let mut b_significand = b_rep & significand_mask;
8987

9088
// normalize any denormals, and adjust the exponent accordingly.
91-
if a_exponent.0 == 0 {
92-
let (exponent, significand) = <$ty>::normalize(a_significand.0);
93-
a_exponent = Wrapping(exponent);
94-
a_significand = Wrapping(significand);
89+
if a_exponent == 0 {
90+
let (exponent, significand) = <$ty>::normalize(a_significand);
91+
a_exponent = exponent;
92+
a_significand = significand;
9593
}
96-
if b_exponent.0 == 0 {
97-
let (exponent, significand) = <$ty>::normalize(b_significand.0);
98-
b_exponent = Wrapping(exponent);
99-
b_significand = Wrapping(significand);
94+
if b_exponent == 0 {
95+
let (exponent, significand) = <$ty>::normalize(b_significand);
96+
b_exponent = exponent;
97+
b_significand = significand;
10098
}
10199

102100
// The sign of the result is the sign of the larger operand, a. If they
@@ -113,72 +111,72 @@ macro_rules! add {
113111

114112
// Shift the significand of b by the difference in exponents, with a sticky
115113
// bottom bit to get rounding correct.
116-
let align = Wrapping((a_exponent - b_exponent).0 as <$ty as Float>::Int);
117-
if align.0 != 0 {
114+
let align = a_exponent.wrapping_sub(b_exponent) as <$ty as Float>::Int;
115+
if align != 0 {
118116
if align < bits {
119-
let sticky = ((b_significand << (bits - align).0 as usize).0 != 0) as <$ty as Float>::Int;
120-
b_significand = (b_significand >> align.0 as usize) | Wrapping(sticky);
117+
let sticky = (b_significand << (bits.wrapping_sub(align) as usize) != 0) as <$ty as Float>::Int;
118+
b_significand = (b_significand >> align as usize) | sticky;
121119
} else {
122120
b_significand = one; // sticky; b is known to be non-zero.
123121
}
124122
}
125123
if subtraction {
126-
a_significand -= b_significand;
124+
a_significand = a_significand.wrapping_sub(b_significand);
127125
// If a == -b, return +zero.
128-
if a_significand.0 == 0 {
126+
if a_significand == 0 {
129127
return <$ty as Float>::from_repr(0);
130128
}
131129

132130
// If partial cancellation occured, we need to left-shift the result
133131
// and adjust the exponent:
134132
if a_significand < implicit_bit << 3 {
135-
let shift = a_significand.0.leading_zeros() as i32
136-
- (implicit_bit << 3).0.leading_zeros() as i32;
133+
let shift = a_significand.leading_zeros() as i32
134+
- (implicit_bit << 3).leading_zeros() as i32;
137135
a_significand <<= shift as usize;
138-
a_exponent -= Wrapping(shift);
136+
a_exponent -= shift;
139137
}
140138
} else /* addition */ {
141139
a_significand += b_significand;
142140

143141
// If the addition carried up, we need to right-shift the result and
144142
// adjust the exponent:
145-
if (a_significand & implicit_bit << 4).0 != 0 {
146-
let sticky = ((a_significand & one).0 != 0) as <$ty as Float>::Int;
147-
a_significand = a_significand >> 1 | Wrapping(sticky);
148-
a_exponent += Wrapping(1);
143+
if a_significand & implicit_bit << 4 != 0 {
144+
let sticky = (a_significand & one != 0) as <$ty as Float>::Int;
145+
a_significand = a_significand >> 1 | sticky;
146+
a_exponent += 1;
149147
}
150148
}
151149

152150
// If we have overflowed the type, return +/- infinity:
153-
if a_exponent >= Wrapping(max_exponent.0 as i32) {
154-
return <$ty>::from_repr((inf_rep | result_sign).0);
151+
if a_exponent >= max_exponent as i32 {
152+
return <$ty>::from_repr(inf_rep | result_sign);
155153
}
156154

157-
if a_exponent.0 <= 0 {
155+
if a_exponent <= 0 {
158156
// Result is denormal before rounding; the exponent is zero and we
159157
// need to shift the significand.
160-
let shift = Wrapping((Wrapping(1) - a_exponent).0 as <$ty as Float>::Int);
161-
let sticky = ((a_significand << (bits - shift).0 as usize).0 != 0) as <$ty as Float>::Int;
162-
a_significand = a_significand >> shift.0 as usize | Wrapping(sticky);
163-
a_exponent = Wrapping(0);
158+
let shift = (1 - a_exponent) as <$ty as Float>::Int;
159+
let sticky = ((a_significand << bits.wrapping_sub(shift) as usize) != 0) as <$ty as Float>::Int;
160+
a_significand = a_significand >> shift as usize | sticky;
161+
a_exponent = 0;
164162
}
165163

166164
// Low three bits are round, guard, and sticky.
167-
let round_guard_sticky: i32 = (a_significand.0 & 0x7) as i32;
165+
let round_guard_sticky: i32 = (a_significand & 0x7) as i32;
168166

169167
// Shift the significand into place, and mask off the implicit bit.
170168
let mut result = a_significand >> 3 & significand_mask;
171169

172170
// Insert the exponent and sign.
173-
result |= Wrapping(a_exponent.0 as <$ty as Float>::Int) << significand_bits.0 as usize;
171+
result |= (a_exponent as <$ty as Float>::Int) << (significand_bits as usize);
174172
result |= result_sign;
175173

176174
// Final rounding. The result may overflow to infinity, but that is the
177175
// correct result in that case.
178176
if round_guard_sticky > 0x4 { result += one; }
179177
if round_guard_sticky == 0x4 { result += result & one; }
180178

181-
<$ty>::from_repr(result.0)
179+
<$ty>::from_repr(result)
182180
})
183181
}
184182

0 commit comments

Comments
 (0)