src/simulator/high-precision-128.cc
changeset 4396 7d096e399d77
parent 4046 607136a642c3
equal deleted inserted replaced
4395:489abe44ed7e 4396:7d096e399d77
    17  *
    17  *
    18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    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 
    25 namespace ns3 {
    26 namespace ns3 {
    26 
    27 
   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