149 bool |
150 bool |
150 HighPrecision::SlowMul (HighPrecision const &o) |
151 HighPrecision::SlowMul (HighPrecision const &o) |
151 { |
152 { |
152 EnsureSlow (); |
153 EnsureSlow (); |
153 const_cast<HighPrecision &> (o).EnsureSlow (); |
154 const_cast<HighPrecision &> (o).EnsureSlow (); |
154 cairo_int128_t other = _cairo_int128_rsa (o.m_slowValue, 64); |
155 //use the 128 bits multiplication |
155 m_slowValue = _cairo_int128_mul (m_slowValue, other); |
156 m_slowValue = Mul128(m_slowValue,o.m_slowValue); |
156 return false; |
157 return false; |
157 } |
158 } |
|
159 /** |
|
160 * this function multiplies two 128 bits fractions considering |
|
161 * the high 64 bits as the integer part and the low 64 bits |
|
162 * as the fractional part. It takes into account the sign |
|
163 * of the operands to produce a signed 128 bits result. |
|
164 */ |
|
165 cairo_int128_t |
|
166 HighPrecision::Mul128(cairo_int128_t a, cairo_int128_t b ) |
|
167 { |
|
168 //Implement the 128 bits multiplication |
|
169 cairo_int128_t result; |
|
170 cairo_uint128_t hiPart,loPart,midPart; |
|
171 bool resultNegative = false, signA = false,signB = false; |
|
172 |
|
173 //take the sign of the operands |
|
174 signA = _cairo_int128_negative (a); |
|
175 signB = _cairo_int128_negative (b); |
|
176 //the result is negative only if one of the operand is negative |
|
177 if ((signA == true && signB == false) ||(signA == false && signB == true)) |
|
178 { |
|
179 resultNegative = true; |
|
180 } |
|
181 //now take the absolute part to make sure that the resulting operands are positive |
|
182 if (signA == true) |
|
183 { |
|
184 a = _cairo_int128_negate (a); |
|
185 } |
|
186 if (signB == true) |
|
187 { |
|
188 b = _cairo_int128_negate (b); |
|
189 } |
|
190 |
|
191 //Multiplying (a.h 2^64 + a.l) x (b.h 2^64 + b.l) = |
|
192 // 2^128 a.h b.h + 2^64*(a.h b.l+b.h a.l) + a.l b.l |
|
193 //get the low part a.l b.l |
|
194 //multiply the fractional part |
|
195 loPart = _cairo_uint64x64_128_mul (a.lo, b.lo); |
|
196 //compute the middle part 2^64*(a.h b.l+b.h a.l) |
|
197 midPart = _cairo_uint128_add(_cairo_uint64x64_128_mul(a.lo, b.hi), |
|
198 _cairo_uint64x64_128_mul(a.hi, b.lo)) ; |
|
199 //truncate the low part |
|
200 result.lo = _cairo_uint64_add(loPart.hi,midPart.lo); |
|
201 //compute the high part 2^128 a.h b.h |
|
202 hiPart = _cairo_uint64x64_128_mul (a.hi, b.hi); |
|
203 //truncate the high part and only use the low part |
|
204 result.hi = _cairo_uint64_add(hiPart.lo,midPart.hi); |
|
205 //if the high part is not zero, put a warning |
|
206 if (hiPart.hi !=0) |
|
207 { |
|
208 NS_FATAL_ERROR("High precision 128 bits multiplication error: multiplication overflow."); |
|
209 } |
|
210 //add the sign to the result |
|
211 if (resultNegative) |
|
212 { |
|
213 result = _cairo_int128_negate (result); |
|
214 } |
|
215 return result; |
|
216 } |
|
217 |
158 bool |
218 bool |
159 HighPrecision::Div (HighPrecision const &o) |
219 HighPrecision::Div (HighPrecision const &o) |
160 { |
220 { |
161 HP128INC (m_ndivs++); |
221 HP128INC (m_ndivs++); |
162 EnsureSlow (); |
222 EnsureSlow (); |
349 |
409 |
350 // Bug 455 |
410 // Bug 455 |
351 a = HighPrecision (0.1); |
411 a = HighPrecision (0.1); |
352 a.Div (HighPrecision (1.25)); |
412 a.Div (HighPrecision (1.25)); |
353 NS_TEST_ASSERT_EQUAL (a.GetDouble (), 0.08); |
413 NS_TEST_ASSERT_EQUAL (a.GetDouble (), 0.08); |
|
414 //test the multiplication |
|
415 a = HighPrecision (0.5); |
|
416 a.Mul(HighPrecision (5)); |
|
417 NS_TEST_ASSERT_EQUAL (a.GetDouble (), 2.5); |
|
418 //test the sign of multiplication, first operand negative |
|
419 a = HighPrecision (-0.5); |
|
420 a.Mul(HighPrecision (5)); |
|
421 NS_TEST_ASSERT_EQUAL (a.GetDouble (), -2.5); |
|
422 //two negative |
|
423 a = HighPrecision (-0.5); |
|
424 a.Mul(HighPrecision (-5)); |
|
425 NS_TEST_ASSERT_EQUAL (a.GetDouble (), 2.5); |
|
426 //second operand negative |
|
427 a = HighPrecision (0.5); |
|
428 a.Mul(HighPrecision (-5)); |
|
429 NS_TEST_ASSERT_EQUAL (a.GetDouble (), -2.5); |
354 |
430 |
355 |
431 |
356 return result; |
432 return result; |
357 } |
433 } |
358 |
434 |