|
1 | | -use int::Int; |
| 1 | +use int::{Int, CastInto}; |
2 | 2 | use float::Float; |
3 | 3 |
|
4 | 4 | /// Returns `a + b` |
5 | | -macro_rules! add { |
6 | | - ($a:expr, $b:expr, $ty:ty) => ({ |
7 | | - let a = $a; |
8 | | - let b = $b; |
9 | | - let one = <$ty as Float>::Int::ONE; |
10 | | - let zero = <$ty as Float>::Int::ZERO; |
11 | | - |
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; |
16 | | - |
17 | | - let implicit_bit = one << significand_bits as usize; |
18 | | - let significand_mask = implicit_bit - one; |
19 | | - let sign_bit = <$ty>::SIGN_MASK as <$ty as Float>::Int; |
20 | | - let abs_mask = sign_bit - one; |
21 | | - let exponent_mask = abs_mask ^ significand_mask; |
22 | | - let inf_rep = exponent_mask; |
23 | | - let quiet_bit = implicit_bit >> 1; |
24 | | - let qnan_rep = exponent_mask | quiet_bit; |
25 | | - |
26 | | - let mut a_rep = a.repr(); |
27 | | - let mut b_rep = b.repr(); |
28 | | - let a_abs = a_rep & abs_mask; |
29 | | - let b_abs = b_rep & abs_mask; |
30 | | - |
31 | | - // Detect if a or b is zero, infinity, or NaN. |
32 | | - if a_abs.wrapping_sub(one) >= inf_rep - one || |
33 | | - b_abs.wrapping_sub(one) >= inf_rep - one { |
34 | | - // NaN + anything = qNaN |
35 | | - if a_abs > inf_rep { |
36 | | - return <$ty as Float>::from_repr(a_abs | quiet_bit); |
37 | | - } |
38 | | - // anything + NaN = qNaN |
39 | | - if b_abs > inf_rep { |
40 | | - return <$ty as Float>::from_repr(b_abs | quiet_bit); |
41 | | - } |
42 | | - |
43 | | - if a_abs == inf_rep { |
44 | | - // +/-infinity + -/+infinity = qNaN |
45 | | - if (a.repr() ^ b.repr()) == sign_bit { |
46 | | - return <$ty as Float>::from_repr(qnan_rep); |
47 | | - } else { |
48 | | - // +/-infinity + anything remaining = +/- infinity |
49 | | - return a; |
50 | | - } |
51 | | - } |
| 5 | +fn add<F: Float>(a: F, b: F) -> F where |
| 6 | + u32: CastInto<F::Int>, |
| 7 | + F::Int: CastInto<u32>, |
| 8 | + i32: CastInto<F::Int>, |
| 9 | + F::Int: CastInto<i32>, |
| 10 | +{ |
| 11 | + let one = F::Int::ONE; |
| 12 | + let zero = F::Int::ZERO; |
| 13 | + |
| 14 | + let bits = F::BITS.cast(); |
| 15 | + let significand_bits = F::SIGNIFICAND_BITS; |
| 16 | + let max_exponent = F::EXPONENT_MAX; |
| 17 | + |
| 18 | + let implicit_bit = F::IMPLICIT_BIT; |
| 19 | + let significand_mask = F::SIGNIFICAND_MASK; |
| 20 | + let sign_bit = F::SIGN_MASK as F::Int; |
| 21 | + let abs_mask = sign_bit - one; |
| 22 | + let exponent_mask = F::EXPONENT_MASK; |
| 23 | + let inf_rep = exponent_mask; |
| 24 | + let quiet_bit = implicit_bit >> 1; |
| 25 | + let qnan_rep = exponent_mask | quiet_bit; |
| 26 | + |
| 27 | + let mut a_rep = a.repr(); |
| 28 | + let mut b_rep = b.repr(); |
| 29 | + let a_abs = a_rep & abs_mask; |
| 30 | + let b_abs = b_rep & abs_mask; |
| 31 | + |
| 32 | + // Detect if a or b is zero, infinity, or NaN. |
| 33 | + if a_abs.wrapping_sub(one) >= inf_rep - one || |
| 34 | + b_abs.wrapping_sub(one) >= inf_rep - one { |
| 35 | + // NaN + anything = qNaN |
| 36 | + if a_abs > inf_rep { |
| 37 | + return F::from_repr(a_abs | quiet_bit); |
| 38 | + } |
| 39 | + // anything + NaN = qNaN |
| 40 | + if b_abs > inf_rep { |
| 41 | + return F::from_repr(b_abs | quiet_bit); |
| 42 | + } |
52 | 43 |
|
53 | | - // anything remaining + +/-infinity = +/-infinity |
54 | | - if b_abs == inf_rep { |
55 | | - return b; |
| 44 | + if a_abs == inf_rep { |
| 45 | + // +/-infinity + -/+infinity = qNaN |
| 46 | + if (a.repr() ^ b.repr()) == sign_bit { |
| 47 | + return F::from_repr(qnan_rep); |
| 48 | + } else { |
| 49 | + // +/-infinity + anything remaining = +/- infinity |
| 50 | + return a; |
56 | 51 | } |
| 52 | + } |
57 | 53 |
|
58 | | - // zero + anything = anything |
59 | | - if a_abs == 0 { |
60 | | - // but we need to get the sign right for zero + zero |
61 | | - if b_abs == 0 { |
62 | | - return <$ty as Float>::from_repr(a.repr() & b.repr()); |
63 | | - } else { |
64 | | - return b; |
65 | | - } |
66 | | - } |
| 54 | + // anything remaining + +/-infinity = +/-infinity |
| 55 | + if b_abs == inf_rep { |
| 56 | + return b; |
| 57 | + } |
67 | 58 |
|
68 | | - // anything + zero = anything |
69 | | - if b_abs == 0 { |
70 | | - return a; |
| 59 | + // zero + anything = anything |
| 60 | + if a_abs == Int::ZERO { |
| 61 | + // but we need to get the sign right for zero + zero |
| 62 | + if b_abs == Int::ZERO { |
| 63 | + return F::from_repr(a.repr() & b.repr()); |
| 64 | + } else { |
| 65 | + return b; |
71 | 66 | } |
72 | 67 | } |
73 | 68 |
|
74 | | - // Swap a and b if necessary so that a has the larger absolute value. |
75 | | - if b_abs > a_abs { |
76 | | - // Don't use mem::swap because it may generate references to memcpy in unoptimized code. |
77 | | - let tmp = a_rep; |
78 | | - a_rep = b_rep; |
79 | | - b_rep = tmp; |
| 69 | + // anything + zero = anything |
| 70 | + if b_abs == Int::ZERO { |
| 71 | + return a; |
80 | 72 | } |
| 73 | + } |
| 74 | + |
| 75 | + // Swap a and b if necessary so that a has the larger absolute value. |
| 76 | + if b_abs > a_abs { |
| 77 | + // Don't use mem::swap because it may generate references to memcpy in unoptimized code. |
| 78 | + let tmp = a_rep; |
| 79 | + a_rep = b_rep; |
| 80 | + b_rep = tmp; |
| 81 | + } |
81 | 82 |
|
82 | | - // Extract the exponent and significand from the (possibly swapped) a and b. |
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; |
85 | | - let mut a_significand = a_rep & significand_mask; |
86 | | - let mut b_significand = b_rep & significand_mask; |
87 | | - |
88 | | - // normalize any denormals, and adjust the exponent accordingly. |
89 | | - if a_exponent == 0 { |
90 | | - let (exponent, significand) = <$ty>::normalize(a_significand); |
91 | | - a_exponent = exponent; |
92 | | - a_significand = significand; |
| 83 | + // Extract the exponent and significand from the (possibly swapped) a and b. |
| 84 | + let mut a_exponent: i32 = ((a_rep & exponent_mask) >> significand_bits).cast(); |
| 85 | + let mut b_exponent: i32 = ((b_rep & exponent_mask) >> significand_bits).cast(); |
| 86 | + let mut a_significand = a_rep & significand_mask; |
| 87 | + let mut b_significand = b_rep & significand_mask; |
| 88 | + |
| 89 | + // normalize any denormals, and adjust the exponent accordingly. |
| 90 | + if a_exponent == 0 { |
| 91 | + let (exponent, significand) = F::normalize(a_significand); |
| 92 | + a_exponent = exponent; |
| 93 | + a_significand = significand; |
| 94 | + } |
| 95 | + if b_exponent == 0 { |
| 96 | + let (exponent, significand) = F::normalize(b_significand); |
| 97 | + b_exponent = exponent; |
| 98 | + b_significand = significand; |
| 99 | + } |
| 100 | + |
| 101 | + // The sign of the result is the sign of the larger operand, a. If they |
| 102 | + // have opposite signs, we are performing a subtraction; otherwise addition. |
| 103 | + let result_sign = a_rep & sign_bit; |
| 104 | + let subtraction = ((a_rep ^ b_rep) & sign_bit) != zero; |
| 105 | + |
| 106 | + // Shift the significands to give us round, guard and sticky, and or in the |
| 107 | + // implicit significand bit. (If we fell through from the denormal path it |
| 108 | + // was already set by normalize(), but setting it twice won't hurt |
| 109 | + // anything.) |
| 110 | + a_significand = (a_significand | implicit_bit) << 3; |
| 111 | + b_significand = (b_significand | implicit_bit) << 3; |
| 112 | + |
| 113 | + // Shift the significand of b by the difference in exponents, with a sticky |
| 114 | + // bottom bit to get rounding correct. |
| 115 | + let align = a_exponent.wrapping_sub(b_exponent).cast(); |
| 116 | + if align != Int::ZERO { |
| 117 | + if align < bits { |
| 118 | + let sticky = F::Int::from_bool(b_significand << bits.wrapping_sub(align).cast() != Int::ZERO); |
| 119 | + b_significand = (b_significand >> align.cast()) | sticky; |
| 120 | + } else { |
| 121 | + b_significand = one; // sticky; b is known to be non-zero. |
93 | 122 | } |
94 | | - if b_exponent == 0 { |
95 | | - let (exponent, significand) = <$ty>::normalize(b_significand); |
96 | | - b_exponent = exponent; |
97 | | - b_significand = significand; |
| 123 | + } |
| 124 | + if subtraction { |
| 125 | + a_significand = a_significand.wrapping_sub(b_significand); |
| 126 | + // If a == -b, return +zero. |
| 127 | + if a_significand == Int::ZERO { |
| 128 | + return F::from_repr(Int::ZERO); |
98 | 129 | } |
99 | 130 |
|
100 | | - // The sign of the result is the sign of the larger operand, a. If they |
101 | | - // have opposite signs, we are performing a subtraction; otherwise addition. |
102 | | - let result_sign = a_rep & sign_bit; |
103 | | - let subtraction = ((a_rep ^ b_rep) & sign_bit) != zero; |
104 | | - |
105 | | - // Shift the significands to give us round, guard and sticky, and or in the |
106 | | - // implicit significand bit. (If we fell through from the denormal path it |
107 | | - // was already set by normalize(), but setting it twice won't hurt |
108 | | - // anything.) |
109 | | - a_significand = (a_significand | implicit_bit) << 3; |
110 | | - b_significand = (b_significand | implicit_bit) << 3; |
111 | | - |
112 | | - // Shift the significand of b by the difference in exponents, with a sticky |
113 | | - // bottom bit to get rounding correct. |
114 | | - let align = a_exponent.wrapping_sub(b_exponent) as <$ty as Float>::Int; |
115 | | - if align != 0 { |
116 | | - if align < bits { |
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; |
119 | | - } else { |
120 | | - b_significand = one; // sticky; b is known to be non-zero. |
121 | | - } |
| 131 | + // If partial cancellation occured, we need to left-shift the result |
| 132 | + // and adjust the exponent: |
| 133 | + if a_significand < implicit_bit << 3 { |
| 134 | + let shift = a_significand.leading_zeros() as i32 |
| 135 | + - (implicit_bit << 3).leading_zeros() as i32; |
| 136 | + a_significand <<= shift; |
| 137 | + a_exponent -= shift; |
122 | 138 | } |
123 | | - if subtraction { |
124 | | - a_significand = a_significand.wrapping_sub(b_significand); |
125 | | - // If a == -b, return +zero. |
126 | | - if a_significand == 0 { |
127 | | - return <$ty as Float>::from_repr(0); |
128 | | - } |
129 | | - |
130 | | - // If partial cancellation occured, we need to left-shift the result |
131 | | - // and adjust the exponent: |
132 | | - if a_significand < implicit_bit << 3 { |
133 | | - let shift = a_significand.leading_zeros() as i32 |
134 | | - - (implicit_bit << 3).leading_zeros() as i32; |
135 | | - a_significand <<= shift as usize; |
136 | | - a_exponent -= shift; |
137 | | - } |
138 | | - } else /* addition */ { |
139 | | - a_significand += b_significand; |
140 | | - |
141 | | - // If the addition carried up, we need to right-shift the result and |
142 | | - // adjust the exponent: |
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; |
147 | | - } |
| 139 | + } else /* addition */ { |
| 140 | + a_significand += b_significand; |
| 141 | + |
| 142 | + // If the addition carried up, we need to right-shift the result and |
| 143 | + // adjust the exponent: |
| 144 | + if a_significand & implicit_bit << 4 != Int::ZERO { |
| 145 | + let sticky = F::Int::from_bool(a_significand & one != Int::ZERO); |
| 146 | + a_significand = a_significand >> 1 | sticky; |
| 147 | + a_exponent += 1; |
148 | 148 | } |
| 149 | + } |
149 | 150 |
|
150 | | - // If we have overflowed the type, return +/- infinity: |
151 | | - if a_exponent >= max_exponent as i32 { |
152 | | - return <$ty>::from_repr(inf_rep | result_sign); |
153 | | - } |
| 151 | + // If we have overflowed the type, return +/- infinity: |
| 152 | + if a_exponent >= max_exponent as i32 { |
| 153 | + return F::from_repr(inf_rep | result_sign); |
| 154 | + } |
154 | 155 |
|
155 | | - if a_exponent <= 0 { |
156 | | - // Result is denormal before rounding; the exponent is zero and we |
157 | | - // need to shift the significand. |
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; |
162 | | - } |
| 156 | + if a_exponent <= 0 { |
| 157 | + // Result is denormal before rounding; the exponent is zero and we |
| 158 | + // need to shift the significand. |
| 159 | + let shift = (1 - a_exponent).cast(); |
| 160 | + let sticky = F::Int::from_bool((a_significand << bits.wrapping_sub(shift).cast()) != Int::ZERO); |
| 161 | + a_significand = a_significand >> shift.cast() | sticky; |
| 162 | + a_exponent = 0; |
| 163 | + } |
163 | 164 |
|
164 | | - // Low three bits are round, guard, and sticky. |
165 | | - let round_guard_sticky: i32 = (a_significand & 0x7) as i32; |
| 165 | + // Low three bits are round, guard, and sticky. |
| 166 | + let a_significand_i32: i32 = a_significand.cast(); |
| 167 | + let round_guard_sticky: i32 = a_significand_i32 & 0x7; |
166 | 168 |
|
167 | | - // Shift the significand into place, and mask off the implicit bit. |
168 | | - let mut result = a_significand >> 3 & significand_mask; |
| 169 | + // Shift the significand into place, and mask off the implicit bit. |
| 170 | + let mut result = a_significand >> 3 & significand_mask; |
169 | 171 |
|
170 | | - // Insert the exponent and sign. |
171 | | - result |= (a_exponent as <$ty as Float>::Int) << (significand_bits as usize); |
172 | | - result |= result_sign; |
| 172 | + // Insert the exponent and sign. |
| 173 | + result |= a_exponent.cast() << significand_bits; |
| 174 | + result |= result_sign; |
173 | 175 |
|
174 | | - // Final rounding. The result may overflow to infinity, but that is the |
175 | | - // correct result in that case. |
176 | | - if round_guard_sticky > 0x4 { result += one; } |
177 | | - if round_guard_sticky == 0x4 { result += result & one; } |
| 176 | + // Final rounding. The result may overflow to infinity, but that is the |
| 177 | + // correct result in that case. |
| 178 | + if round_guard_sticky > 0x4 { result += one; } |
| 179 | + if round_guard_sticky == 0x4 { result += result & one; } |
178 | 180 |
|
179 | | - <$ty>::from_repr(result) |
180 | | - }) |
| 181 | + F::from_repr(result) |
181 | 182 | } |
182 | 183 |
|
183 | 184 | intrinsics! { |
184 | 185 | #[aapcs_on_arm] |
185 | 186 | #[arm_aeabi_alias = __aeabi_fadd] |
186 | 187 | pub extern "C" fn __addsf3(a: f32, b: f32) -> f32 { |
187 | | - add!(a, b, f32) |
| 188 | + add(a, b) |
188 | 189 | } |
189 | 190 |
|
190 | 191 | #[aapcs_on_arm] |
191 | 192 | #[arm_aeabi_alias = __aeabi_dadd] |
192 | 193 | pub extern "C" fn __adddf3(a: f64, b: f64) -> f64 { |
193 | | - add!(a, b, f64) |
| 194 | + add(a, b) |
194 | 195 | } |
195 | 196 | } |
0 commit comments