|
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