|
19 |
*/ |
19 |
*/ |
20 |
#include "high-precision-128.h" |
20 |
#include "high-precision-128.h" |
21 |
#include "ns3/test.h" |
21 |
#include "ns3/test.h" |
|
|
22 |
#include "ns3/fatal-error.h" |
22 |
#include <math.h> |
23 |
#include <math.h> |
23 |
#include <iostream> |
24 |
#include <iostream> |
24 |
|
25 |
|
|
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 |
{ |
|
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; |