# HG changeset patch # User Mathieu Lacage # Date 1282725861 -7200 # Node ID c3854df956034d80f633a77c2b0e3094a4b84d71 # Parent 47eba877c2d8ca4753d7a9aec6a180f8f5e9d902 rename diff -r 47eba877c2d8 -r c3854df95603 src/simulator/int64x64-128.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/simulator/int64x64-128.cc Wed Aug 25 10:44:21 2010 +0200 @@ -0,0 +1,138 @@ +#include "int64x64-128.h" +#include "ns3/abort.h" +#include "ns3/assert.h" + +namespace ns3 { + +#define OUTPUT_SIGN(sa,sb,ua,ub) \ + ({bool negA, negB; \ + negA = sa < 0; \ + negB = sb < 0; \ + ua = negA?-sa:sa; \ + ub = negB?-sb:sb; \ + (negA && !negB) || (!negA && negB);}) + + +#define MASK_LO ((((int128_t)1)<<64)-1) +#define MASK_HI (~MASK_LO) + +void +int64x64_t::Mul (int64x64_t const &o) +{ + bool negResult; + uint128_t a, b; + negResult = OUTPUT_SIGN (_v, o._v, a, b); + int128_t result = Umul (a, b); + // add the sign to the result + result = negResult ? -result : result; + _v = result; +} + +uint128_t +int64x64_t::Umul (uint128_t a, uint128_t b) +{ + uint128_t aL = a & MASK_LO; + uint128_t bL = b & MASK_LO; + uint128_t aH = (a >> 64) & MASK_LO; + uint128_t bH = (b >> 64) & MASK_LO; + + uint128_t result; + uint128_t hiPart,loPart,midPart; + + // Multiplying (a.h 2^64 + a.l) x (b.h 2^64 + b.l) = + // 2^128 a.h b.h + 2^64*(a.h b.l+b.h a.l) + a.l b.l + // get the low part a.l b.l + // multiply the fractional part + loPart = aL * bL; + // compute the middle part 2^64*(a.h b.l+b.h a.l) + midPart = aL * bH + aH * bL; + // truncate the low part + result = (loPart >> 64) + (midPart & MASK_LO); + // compute the high part 2^128 a.h b.h + hiPart = aH * bH; + // truncate the high part and only use the low part + result |= ((hiPart & MASK_LO) << 64) + (midPart & MASK_HI); + // if the high part is not zero, put a warning + NS_ABORT_MSG_IF ((hiPart & MASK_HI) != 0, + "High precision 128 bits multiplication error: multiplication overflow."); + return result; +} +void +int64x64_t::Div (int64x64_t const &o) +{ + bool negResult; + uint128_t a, b; + negResult = OUTPUT_SIGN (_v, o._v, a, b); + int128_t result = Divu (a, b); + result = negResult ? -result:result; + _v = result; +} + +uint128_t +int64x64_t::Divu (uint128_t a, uint128_t b) +{ + uint128_t quo = a / b; + uint128_t rem = (a % b); + uint128_t result = quo << 64; + // Now, manage the remainder + uint128_t tmp = rem >> 64; + uint128_t div; + if (tmp == 0) + { + rem = rem << 64; + div = b; + } + else + { + rem = rem; + div = b >> 64; + } + quo = rem / div; + result = result + quo; + return result; +} + +void +int64x64_t::MulByInvert (const int64x64_t &o) +{ + bool negResult = _v < 0; + uint128_t a = negResult?-_v:_v; + uint128_t result = UmulByInvert (a, o._v); + + _v = negResult?-result:result; +} +uint128_t +int64x64_t::UmulByInvert (uint128_t a, uint128_t b) +{ + uint128_t result, ah, bh, al, bl; + uint128_t hi, mid; + ah = a >> 64; + bh = b >> 64; + al = a & MASK_LO; + bl = b & MASK_LO; + hi = ah * bh; + mid = ah * bl + al * bh; + mid >>= 64; + result = ah * bh + mid; + return result; +} +int64x64_t +int64x64_t::Invert (uint64_t v) +{ + NS_ASSERT (v > 1); + uint128_t a; + a = 1; + a <<= 64; + int64x64_t result; + result._v = Divu (a, v); + int64x64_t tmp = int64x64_t (v, false); + tmp.MulByInvert (result); + if (tmp.GetHigh () != 1) + { + result._v += 1; + } + return result; +} + +} // namespace ns3 + diff -r 47eba877c2d8 -r c3854df95603 src/simulator/int64x64-128.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/simulator/int64x64-128.h Wed Aug 25 10:44:21 2010 +0200 @@ -0,0 +1,212 @@ +#ifndef INT64X64_128_H +#define INT64X64_128_H + +#include "ns3/simulator-config.h" +#include +#include + +#if defined(HAVE___UINT128_T) and !defined(HAVE_UINT128_T) +typedef __uint128_t uint128_t; +typedef __int128_t int128_t; +#endif + +namespace ns3 { + +#define HP128_MAX_64 18446744073709551615.0 +#define HP128_MASK_LO ((((int128_t)1)<<64)-1) + +class int64x64_t +{ +public: + inline int64x64_t () + : _v (0) + {} + explicit inline int64x64_t (double value) + { + bool is_negative = value < 0; + value = is_negative?-value:value; + double hi = floor (value); + double lo = (value - hi) * HP128_MAX_64; + _v = (int128_t)hi; + _v <<= 64; + _v += (int128_t)lo; + _v = is_negative?-_v:_v; + } + explicit inline int64x64_t (int v) + : _v (v) + { + _v <<= 64; + } + explicit inline int64x64_t (long int v) + : _v (v) + { + _v <<= 64; + } + explicit inline int64x64_t (long long int v) + : _v (v) + { + _v <<= 64; + } + explicit inline int64x64_t (unsigned int v) + : _v (v) + { + _v <<= 64; + } + explicit inline int64x64_t (unsigned long int v) + : _v (v) + { + _v <<= 64; + } + explicit inline int64x64_t (unsigned long long int v) + : _v (v) + { + _v <<= 64; + } + explicit inline int64x64_t (int64_t hi, uint64_t lo) + { + bool is_negative = hi<0; + _v = is_negative?-hi:hi; + _v <<= 64; + _v += lo; + _v = is_negative?-_v:_v; + } + + inline int64x64_t (const int64x64_t &o) + : _v (o._v) {} + inline int64x64_t &operator = (const int64x64_t &o) + { + _v = o._v; + return *this; + } + + inline double GetDouble (void) const + { + bool is_negative = _v < 0; + uint128_t value = is_negative ? -_v:_v; + uint64_t hi = value >> 64; + uint64_t lo = value; + double flo = lo; + flo /= HP128_MAX_64; + double retval = hi; + retval += flo; + retval = is_negative ? -retval : retval; + return retval; + } + inline int64_t GetHigh (void) const + { + bool negative = _v < 0; + int128_t v = negative?-_v:_v; + v >>= 64; + int64_t retval = v; + return negative?-retval:retval; + } + inline uint64_t GetLow (void) const + { + bool negative = _v < 0; + int128_t v = negative?-_v:_v; + int128_t low = v & HP128_MASK_LO; + uint64_t retval = low; + return retval; + } +#undef HP128_MAX_64 +#undef HP128_MASK_LO + + void MulByInvert (const int64x64_t &o); + + static int64x64_t Invert (uint64_t v); + +private: + friend bool operator == (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator != (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator <= (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator >= (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator < (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator > (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t &operator += (int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t &operator -= (int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t &operator *= (int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t &operator /= (int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator + (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator - (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator * (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator / (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator + (const int64x64_t &lhs); + friend int64x64_t operator - (const int64x64_t &lhs); + friend int64x64_t operator ! (const int64x64_t &lhs); + void Mul (const int64x64_t &o); + void Div (const int64x64_t &o); + static uint128_t UmulByInvert (uint128_t a, uint128_t b); + static uint128_t Umul (uint128_t a, uint128_t b); + static uint128_t Divu (uint128_t a, uint128_t b); + inline int64x64_t (int128_t v) + : _v (v) {} + + int128_t _v; +}; + +inline bool operator == (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v == rhs._v; +} + +inline bool operator != (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v != rhs._v; +} + +inline bool operator < (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v < rhs._v; +} +inline bool operator <= (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v <= rhs._v; +} + +inline bool operator >= (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v >= rhs._v; +} +inline bool operator > (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v > rhs._v; +} +inline int64x64_t &operator += (int64x64_t &lhs, const int64x64_t &rhs) +{ + lhs._v += rhs._v; + return lhs; +} +inline int64x64_t &operator -= (int64x64_t &lhs, const int64x64_t &rhs) +{ + lhs._v -= rhs._v; + return lhs; +} +inline int64x64_t &operator *= (int64x64_t &lhs, const int64x64_t &rhs) +{ + lhs.Mul (rhs); + return lhs; +} +inline int64x64_t &operator /= (int64x64_t &lhs, const int64x64_t &rhs) +{ + lhs.Div (rhs); + return lhs; +} + +inline int64x64_t operator + (const int64x64_t &lhs) +{ + return lhs; +} + +inline int64x64_t operator - (const int64x64_t &lhs) +{ + return int64x64_t (-lhs._v); +} + +inline int64x64_t operator ! (const int64x64_t &lhs) +{ + return int64x64_t (!lhs._v); +} + +} // namespace ns3 + +#endif /* INT64X64_128_H */ diff -r 47eba877c2d8 -r c3854df95603 src/simulator/int64x64-cairo.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/simulator/int64x64-cairo.cc Wed Aug 25 10:44:21 2010 +0200 @@ -0,0 +1,162 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006 INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#include "int64x64-cairo.h" +#include "ns3/test.h" +#include "ns3/abort.h" +#include "ns3/assert.h" +#include +#include + +namespace ns3 { + +#define OUTPUT_SIGN(sa,sb,ua,ub) \ + ({bool negA, negB; \ + negA = _cairo_int128_negative (sa); \ + negB = _cairo_int128_negative (sb); \ + ua = _cairo_int128_to_uint128 (sa); \ + ub = _cairo_int128_to_uint128 (sb); \ + ua = negA ? _cairo_uint128_negate (ua) : ua; \ + ub = negB ? _cairo_uint128_negate (ub) : ub; \ + (negA && !negB) || (!negA && negB);}) + +void +int64x64_t::Mul (int64x64_t const &o) +{ + cairo_uint128_t a, b, result; + bool sign = OUTPUT_SIGN (_v, o._v, a, b); + result = Umul (a, b); + _v = sign ? _cairo_uint128_negate (result) : result; +} + +/** + * this function multiplies two 128 bits fractions considering + * the high 64 bits as the integer part and the low 64 bits + * as the fractional part. It takes into account the sign + * of the operands to produce a signed 128 bits result. + */ +cairo_uint128_t +int64x64_t::Umul (cairo_uint128_t a, cairo_uint128_t b) +{ + cairo_uint128_t result; + cairo_uint128_t hiPart,loPart,midPart; + + // Multiplying (a.h 2^64 + a.l) x (b.h 2^64 + b.l) = + // 2^128 a.h b.h + 2^64*(a.h b.l+b.h a.l) + a.l b.l + // get the low part a.l b.l + // multiply the fractional part + loPart = _cairo_int64x64_128_mul (a.lo, b.lo); + // compute the middle part 2^64*(a.h b.l+b.h a.l) + midPart = _cairo_uint128_add (_cairo_int64x64_128_mul (a.lo, b.hi), + _cairo_int64x64_128_mul (a.hi, b.lo)); + // truncate the low part + result.lo = _cairo_uint64_add (loPart.hi,midPart.lo); + // compute the high part 2^128 a.h b.h + hiPart = _cairo_int64x64_128_mul (a.hi, b.hi); + // truncate the high part and only use the low part + result.hi = _cairo_uint64_add (hiPart.lo,midPart.hi); + // if the high part is not zero, put a warning + NS_ABORT_MSG_IF (hiPart.hi != 0, + "High precision 128 bits multiplication error: multiplication overflow."); + return result; +} + +void +int64x64_t::Div (int64x64_t const &o) +{ + cairo_uint128_t a, b, result; + bool sign = OUTPUT_SIGN (_v, o._v, a, b); + result = Udiv (a, b); + _v = sign ? _cairo_uint128_negate (result) : result; +} + +cairo_uint128_t +int64x64_t::Udiv (cairo_uint128_t a, cairo_uint128_t b) +{ + cairo_uquorem128_t qr = _cairo_uint128_divrem (a, b); + cairo_uint128_t result = _cairo_uint128_lsl (qr.quo, 64); + // Now, manage the remainder + cairo_uint128_t tmp = _cairo_uint128_rsl (qr.rem, 64); + cairo_uint128_t zero = _cairo_uint64_to_uint128 (0); + cairo_uint128_t rem, div; + if (_cairo_uint128_eq (tmp, zero)) + { + rem = _cairo_uint128_lsl (qr.rem, 64); + div = b; + } + else + { + rem = qr.rem; + div = _cairo_uint128_rsl (b, 64); + } + qr = _cairo_uint128_divrem (rem, div); + result = _cairo_uint128_add (result, qr.quo); + return result; +} + +void +int64x64_t::MulByInvert (const int64x64_t &o) +{ + bool negResult = _cairo_int128_negative (_v); + cairo_uint128_t a = negResult?_cairo_int128_negate(_v):_v; + cairo_uint128_t result = UmulByInvert (a, o._v); + + _v = negResult?_cairo_int128_negate(result):result; +} +cairo_uint128_t +int64x64_t::UmulByInvert (cairo_uint128_t a, cairo_uint128_t b) +{ + cairo_uint128_t result; + cairo_uint128_t hi, mid; + hi = _cairo_int64x64_128_mul (a.hi, b.hi); + mid = _cairo_uint128_add (_cairo_int64x64_128_mul (a.hi, b.lo), + _cairo_int64x64_128_mul (a.lo, b.hi)); + mid.lo = mid.hi; + mid.hi = 0; + result = _cairo_uint128_add (hi,mid); + return result; +} +int64x64_t +int64x64_t::Invert (uint64_t v) +{ + NS_ASSERT (v > 1); + cairo_uint128_t a, factor; + a.hi = 1; + a.lo = 0; + factor.hi = 0; + factor.lo = v; + int64x64_t result; + result._v = Udiv (a, factor); + int64x64_t tmp = int64x64_t (v, 0); + tmp.MulByInvert (result); + if (tmp.GetHigh () != 1) + { + cairo_uint128_t one = {1, 0}; + result._v = _cairo_uint128_add (result._v, one); + } + return result; +} + + +} // namespace ns3 + +// include directly to allow optimizations within the compilation unit. +extern "C" { +#include "cairo-wideint.c" +} diff -r 47eba877c2d8 -r c3854df95603 src/simulator/int64x64-cairo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/simulator/int64x64-cairo.h Wed Aug 25 10:44:21 2010 +0200 @@ -0,0 +1,242 @@ +#ifndef INT64X64_CAIRO_H +#define INT64X64_CAIRO_H + +#include +#include +#include "cairo-wideint-private.h" + +#ifdef __i386__ +// this assembly code does not appear to work right yet. +#define noInt64x64_CAIRO_ASM 1 +#endif + +namespace ns3 { + +class int64x64_t +{ +public: + inline int64x64_t () + { + _v.hi = 0; + _v.lo = 0; + } + explicit inline int64x64_t (double value) + { +#define HPCAIRO_MAX_64 18446744073709551615.0 + double fhi = floor (value); + int64_t hi = fhi; + uint64_t lo = (uint64_t) ((value - fhi) * HPCAIRO_MAX_64); + _v.hi = hi; + _v.lo = lo; +#undef HPCAIRO_MAX_64 + } + explicit inline int64x64_t (int v) + { + _v.hi = v; + _v.lo = 0; + } + explicit inline int64x64_t (long int v) + { + _v.hi = v; + _v.lo = 0; + } + explicit inline int64x64_t (long long int v) + { + _v.hi = v; + _v.lo = 0; + } + explicit inline int64x64_t (int64_t hi, uint64_t lo) + { + _v.hi = hi; + _v.lo = lo; + } + + inline int64x64_t (const int64x64_t &o) + : _v (o._v) {} + inline int64x64_t &operator = (const int64x64_t &o) + { + _v = o._v; + return *this; + } + + inline double GetDouble (void) const + { +#define HPCAIRO_MAX_64 18446744073709551615.0 + bool is_negative = IsNegative (); + cairo_int128_t value = is_negative ? _cairo_int128_negate (_v) : _v; + double flo = value.lo; + flo /= HPCAIRO_MAX_64; + double retval = value.hi; + retval += flo; + retval = is_negative ? -retval: retval; + return retval; +#undef HPCAIRO_MAX_64 + } + inline int64_t GetHigh (void) const + { + return (int64_t)_v.hi; + } + inline uint64_t GetLow (void) const + { + return _v.lo; + } + + void MulByInvert (const int64x64_t &o); + + static int64x64_t Invert (uint64_t v); + +private: + friend bool operator == (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator != (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator <= (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator >= (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator < (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator > (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t &operator += (int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t &operator -= (int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t &operator *= (int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t &operator /= (int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator + (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator - (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator * (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator / (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator + (const int64x64_t &lhs); + friend int64x64_t operator - (const int64x64_t &lhs); + friend int64x64_t operator ! (const int64x64_t &lhs); + void Mul (const int64x64_t &o); + void Div (const int64x64_t &o); + static cairo_uint128_t Umul (cairo_uint128_t a, cairo_uint128_t b); + static cairo_uint128_t Udiv (cairo_uint128_t a, cairo_uint128_t b); + static cairo_uint128_t UmulByInvert (cairo_uint128_t a, cairo_uint128_t b); + inline bool IsNegative (void) const + { + int64_t hi = _v.hi; + return hi < 0; + } + inline void Negate (void) + { + _v.lo = ~_v.lo; + _v.hi = ~_v.hi; + if (++_v.lo == 0) + { + ++_v.hi; + } + } + inline int Compare (const int64x64_t &o) const + { + int status; + int64x64_t tmp = *this; + tmp -= o; + status = (((int64_t)(tmp)._v.hi) < 0)?-1: + (((tmp)._v.hi == 0 && (tmp)._v.lo == 0))?0:1; + return status; + } + cairo_int128_t _v; +}; + +inline bool operator == (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v.hi == rhs._v.hi && lhs._v.lo == lhs._v.lo; +} + +inline bool operator != (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return ! (lhs == rhs); +} + +inline bool operator < (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs.Compare (rhs) < 0; +} +inline bool operator <= (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs.Compare (rhs) <= 0; +} + +inline bool operator >= (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs.Compare (rhs) >= 0; +} +inline bool operator > (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs.Compare (rhs) > 0; +} +inline int64x64_t &operator += (int64x64_t &lhs, const int64x64_t &rhs) +{ +#if Int64x64_CAIRO_ASM + asm ("mov 0(%1),%%eax\n\t" + "add %%eax,0(%0)\n\t" + "mov 4(%1),%%eax\n\t" + "adc %%eax,4(%0)\n\t" + "mov 8(%1),%%eax\n\t" + "adc %%eax,8(%0)\n\t" + "mov 12(%1),%%eax\n\t" + "adc %%eax,12(%0)\n\t" + : + : "r" (&lhs._v), "r" (&rhs._v) + : "%eax", "cc"); +#else + lhs._v.hi += rhs._v.hi; + lhs._v.lo += rhs._v.lo; + if (lhs._v.lo < rhs._v.lo) + { + lhs._v.hi++; + } +#endif + return lhs; +} +inline int64x64_t &operator -= (int64x64_t &lhs, const int64x64_t &rhs) +{ +#if Int64x64_CAIRO_ASM + asm ("mov 0(%1),%%eax\n\t" + "sub %%eax,0(%0)\n\t" + "mov 4(%1),%%eax\n\t" + "sbb %%eax,4(%0)\n\t" + "mov 8(%1),%%eax\n\t" + "sbb %%eax,8(%0)\n\t" + "mov 12(%1),%%eax\n\t" + "sbb %%eax,12(%0)\n\t" + : + : "r" (&lhs._v), "r" (&rhs._v) + : "%eax", "cc"); +#else + lhs._v.hi -= rhs._v.hi; + lhs._v.lo -= rhs._v.lo; + if (lhs._v.lo > rhs._v.lo) + { + lhs._v.hi--; + } +#endif + return lhs; +} +inline int64x64_t &operator *= (int64x64_t &lhs, const int64x64_t &rhs) +{ + lhs.Mul (rhs); + return lhs; +} +inline int64x64_t &operator /= (int64x64_t &lhs, const int64x64_t &rhs) +{ + lhs.Div (rhs); + return lhs; +} + +inline int64x64_t operator + (const int64x64_t &lhs) +{ + return lhs; +} + +inline int64x64_t operator - (const int64x64_t &lhs) +{ + int64x64_t tmp = lhs; + tmp.Negate (); + return tmp; +} + +inline int64x64_t operator ! (const int64x64_t &lhs) +{ + return (lhs._v.hi == 0 && lhs._v.lo == 0)?int64x64_t (1, 0):int64x64_t (); +} + +} // namespace ns3 + +#endif /* INT64X64_CAIRO_H */ diff -r 47eba877c2d8 -r c3854df95603 src/simulator/int64x64-double.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/simulator/int64x64-double.h Wed Aug 25 10:44:21 2010 +0200 @@ -0,0 +1,153 @@ +#ifndef INT64X64_DOUBLE_H +#define INT64X64_DOUBLE_H + +#include +#include + +namespace ns3 { + +class int64x64_t +{ +public: + inline int64x64_t () + : _v (0) {} + explicit inline int64x64_t (double v) + : _v (v) {} + explicit inline int64x64_t (int v) + : _v (v) {} + explicit inline int64x64_t (long int v) + : _v (v) {} + explicit inline int64x64_t (long long int v) + : _v (v) {} + inline int64x64_t (int64_t hi, uint64_t lo) + : _v (hi) {/* XXX */} + + inline int64x64_t (const int64x64_t &o) + : _v (o._v) {} + inline int64x64_t &operator = (const int64x64_t &o) + { + _v = o._v; + return *this; + } + + inline double GetDouble (void) const + { + return _v; + } + inline int64_t GetHigh (void) const + { + return (int64_t)floor (_v); + } + inline uint64_t GetLow (void) const + { + // XXX + return 0; + } + + inline void MulByInvert (const int64x64_t &o) + { + _v *= o._v; + } + + static inline int64x64_t Invert (uint64_t v) + { + double d = v; + return int64x64_t (1/d); + } + +private: + friend bool operator == (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator != (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator <= (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator >= (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator < (const int64x64_t &lhs, const int64x64_t &rhs); + friend bool operator > (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t &operator += (int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t &operator -= (int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t &operator *= (int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t &operator /= (int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator + (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator - (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator * (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator / (const int64x64_t &lhs, const int64x64_t &rhs); + friend int64x64_t operator + (const int64x64_t &lhs); + friend int64x64_t operator - (const int64x64_t &lhs); + friend int64x64_t operator ! (const int64x64_t &lhs); + + double _v; +}; + +inline bool operator == (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v == rhs._v; +} + +inline bool operator != (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v != rhs._v; +} + +inline bool operator <= (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v <= rhs._v; +} + +inline bool operator >= (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v >= rhs._v; +} +inline bool operator < (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v < rhs._v; +} +inline bool operator > (const int64x64_t &lhs, const int64x64_t &rhs) +{ + return lhs._v > rhs._v; +} +inline int64x64_t &operator += (int64x64_t &lhs, const int64x64_t &rhs) +{ + double tmp = lhs._v; + tmp += rhs._v; + lhs = int64x64_t (tmp); + return lhs; +} +inline int64x64_t &operator -= (int64x64_t &lhs, const int64x64_t &rhs) +{ + double tmp = lhs._v; + tmp -= rhs._v; + lhs = int64x64_t (tmp); + return lhs; +} +inline int64x64_t &operator *= (int64x64_t &lhs, const int64x64_t &rhs) +{ + double tmp = lhs._v; + tmp *= rhs._v; + lhs = int64x64_t (tmp); + return lhs; +} +inline int64x64_t &operator /= (int64x64_t &lhs, const int64x64_t &rhs) +{ + double tmp = lhs._v; + tmp /= rhs._v; + lhs = int64x64_t (tmp); + return lhs; +} + +inline int64x64_t operator + (const int64x64_t &lhs) +{ + return lhs; +} + +inline int64x64_t operator - (const int64x64_t &lhs) +{ + return int64x64_t (-lhs._v); +} + +inline int64x64_t operator ! (const int64x64_t &lhs) +{ + return int64x64_t (!lhs._v); +} + +} // namespace ns3 + +#endif /* INT64X64_DOUBLE_H */ diff -r 47eba877c2d8 -r c3854df95603 src/simulator/int64x64.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/simulator/int64x64.cc Wed Aug 25 10:44:21 2010 +0200 @@ -0,0 +1,460 @@ +#include "int64x64.h" +#include +#include +#include +#include "ns3/assert.h" + +namespace ns3 { + +static uint8_t MostSignificantDigit (uint64_t value) +{ + uint8_t n = 0; + do + { + n++; + value /= 10; + } while (value != 0); + return n; +} + +static uint64_t PowerOfTen (uint8_t n) +{ + uint64_t retval = 1; + while (n > 0) + { + retval *= 10; + n--; + } + return retval; +} + +std::ostream &operator << (std::ostream &os, const int64x64_t &value) +{ + int64_t hi = value.GetHigh (); + os << ((hi<0)?"-":"+") << ((hi<0)?-hi:hi) << "."; + uint64_t low = value.GetLow (); + uint8_t msd = MostSignificantDigit (~((uint64_t)0)); + do + { + msd--; + uint64_t pow = PowerOfTen (msd); + uint8_t digit = low / pow; + NS_ASSERT (digit < 10); + os << (uint16_t) digit; + low -= digit * pow; + } while (msd > 0 && low > 0); + return os; +} + +static uint64_t ReadDigits (std::string str) +{ + const char *buf = str.c_str (); + uint64_t retval = 0; + while (*buf != 0) + { + retval *= 10; + retval += *buf - 0x30; + buf++; + } + return retval; +} + +std::istream &operator >> (std::istream &is, int64x64_t &value) +{ + std::string str; + + is >> str; + bool negative; + // skip heading spaces + std::string::size_type cur; + cur = str.find_first_not_of (" "); + std::string::size_type next; + // first, remove the sign. + next = str.find ("-", cur); + if (next != std::string::npos) + { + negative = true; + next++; + } + else + { + next = str.find ("+", cur); + if (next != std::string::npos) + { + next++; + } + else + { + next = cur; + } + negative = false; + } + cur = next; + int64_t hi; + uint64_t lo; + next = str.find(".", cur); + if (next != std::string::npos) + { + hi = ReadDigits (str.substr (cur, next-cur)); + lo = ReadDigits (str.substr (next+1, str.size()-(next+1))); + } + else + { + hi = ReadDigits (str.substr (cur, str.size ()-cur)); + lo = 0; + } + hi = negative?-hi:hi; + value = int64x64_t (hi, lo); + return is; +} + +} // namespace ns3 + +#include "ns3/test.h" + +namespace ns3 +{ + +class Int64x64FracTestCase : public TestCase +{ +public: + Int64x64FracTestCase (); + virtual bool DoRun (void); + void CheckFrac (int64_t hi, uint64_t lo); +}; + +void +Int64x64FracTestCase::CheckFrac (int64_t hi, uint64_t lo) +{ + int64x64_t tmp = int64x64_t (hi,lo); + NS_TEST_EXPECT_MSG_EQ (tmp.GetHigh (), hi, + "High part does not match"); + NS_TEST_EXPECT_MSG_EQ (tmp.GetLow (), lo, + "Low part does not match"); +} + +Int64x64FracTestCase::Int64x64FracTestCase () + : TestCase ("Check that we can manipulate the high and low part of every number") +{ +} +bool +Int64x64FracTestCase::DoRun (void) +{ + CheckFrac (1, 0); + CheckFrac (1, 1); + CheckFrac (-1, 0); + CheckFrac (-1, 1); + return GetErrorStatus (); +} + + +class Int64x64InputTestCase : public TestCase +{ +public: + Int64x64InputTestCase (); + virtual bool DoRun (void); + void CheckString (std::string str, int64_t hi, uint64_t lo); +}; +Int64x64InputTestCase::Int64x64InputTestCase () + : TestCase ("Check that we parse Int64x64 numbers as strings") +{ +} +void +Int64x64InputTestCase::CheckString (std::string str, int64_t hi, uint64_t lo) +{ + std::istringstream iss; + iss.str (str); + int64x64_t hp; + iss >> hp; + NS_TEST_EXPECT_MSG_EQ (hp.GetHigh (), hi, "High parts do not match for input string " << str); + NS_TEST_EXPECT_MSG_EQ (hp.GetLow (), lo, "Low parts do not match for input string " << str); +} +bool +Int64x64InputTestCase::DoRun (void) +{ + CheckString ("1", 1, 0); + CheckString ("+1", 1, 0); + CheckString ("-1", -1, 0); + CheckString ("1.0", 1, 0); + CheckString ("+1.0", 1, 0); + CheckString ("001.0", 1, 0); + CheckString ("+001.0", 1, 0); + CheckString ("020.0", 20, 0); + CheckString ("+020.0", 20, 0); + CheckString ("-1.0", -1, 0); + CheckString ("-1.0000", -1, 0); + CheckString ("1.0000000", 1, 0); + CheckString ("1.08446744073709551615", 1, 8446744073709551615LL); + CheckString ("-1.08446744073709551615", -1, 8446744073709551615LL); + + return GetErrorStatus (); +} + +class Int64x64InputOutputTestCase : public TestCase +{ +public: + Int64x64InputOutputTestCase (); + virtual bool DoRun (void); + void CheckString (std::string str); +}; +Int64x64InputOutputTestCase::Int64x64InputOutputTestCase () + : TestCase ("Check that we can roundtrip Int64x64 numbers as strings") +{ +} +void +Int64x64InputOutputTestCase::CheckString (std::string str) +{ + std::istringstream iss; + iss.str (str); + int64x64_t value; + iss >> value; + std::ostringstream oss; + oss << value; + NS_TEST_EXPECT_MSG_EQ (oss.str (), str, "Converted string does not match expected string"); +} +bool +Int64x64InputOutputTestCase::DoRun (void) +{ + CheckString ("+1.0"); + CheckString ("-1.0"); + CheckString ("+20.0"); + CheckString ("+1.08446744073709551615"); + CheckString ("-1.08446744073709551615"); + CheckString ("+1.18446744073709551615"); + CheckString ("-1.18446744073709551615"); + + return GetErrorStatus (); +} + +#define CHECK_EXPECTED(a,b) \ + NS_TEST_ASSERT_MSG_EQ ((a).GetHigh (),b,"Arithmetic failure: " << ((a).GetHigh ()) << "!=" << (b)) + +#define V(v) \ + int64x64_t (v) + +class Int64x64ArithmeticTestCase : public TestCase +{ +public: + Int64x64ArithmeticTestCase (); + virtual bool DoRun (void); +}; + +Int64x64ArithmeticTestCase::Int64x64ArithmeticTestCase () + : TestCase ("Check basic arithmetic operations") +{ +} +bool +Int64x64ArithmeticTestCase::DoRun (void) +{ + int64x64_t a, b; + + CHECK_EXPECTED (V(1) - V(1), 0); + CHECK_EXPECTED (V(1) - V(2), -1); + CHECK_EXPECTED (V(1) - V(3), -2); + CHECK_EXPECTED (V(1) - V(-1), 2); + CHECK_EXPECTED (V(1) - V(-2), 3); + CHECK_EXPECTED (V(-3) - V(-4), 1); + CHECK_EXPECTED (V(-2) - V(3), -5); + CHECK_EXPECTED (V(1) + V(2), 3); + CHECK_EXPECTED (V(1) + V(-3), -2); + CHECK_EXPECTED (V(0) + V(0), 0); + CHECK_EXPECTED (V(0) * V(0), 0); + CHECK_EXPECTED (V(0) * V(1), 0); + CHECK_EXPECTED (V(0) * V(-1), 0); + CHECK_EXPECTED (V(1) * V(0), 0); + CHECK_EXPECTED (V(1) * V(1), 1); + CHECK_EXPECTED (V(1) * V(-1), -1); + CHECK_EXPECTED (V(-1) * V(-1), 1); + CHECK_EXPECTED (V(0) * V(1), 0); + CHECK_EXPECTED (V(0) * V(-1), 0); + CHECK_EXPECTED (V(-1) * V(1), -1); + + + CHECK_EXPECTED (V (2) * V(3) / V(3), 2); + + // Below, the division loses precision because 2/3 is not + // representable exactly in 64.64 integers. So, we got + // something super close but the final rounding kills us. + CHECK_EXPECTED (V(2) / V(3) * V(3), 1); + + // The example below shows that we really do not lose + // much precision internally: it is almost always the + // final conversion which loses precision. + CHECK_EXPECTED (V (2000000000) / V(3) * V(3), 1999999999); + + return GetErrorStatus (); +} + +class Int64x64Bug455TestCase : public TestCase +{ +public: + Int64x64Bug455TestCase (); + virtual bool DoRun (void); +}; + +Int64x64Bug455TestCase::Int64x64Bug455TestCase () + : TestCase ("Test case for bug 455") +{ +} +bool +Int64x64Bug455TestCase::DoRun (void) +{ + int64x64_t a = int64x64_t (0.1); + a /= int64x64_t (1.25); + NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 0.08, "The original testcase"); + a = int64x64_t (0.5); + a *= int64x64_t (5); + NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 2.5, "Simple test for multiplication"); + a = int64x64_t (-0.5); + a *= int64x64_t (5); + NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), -2.5, "Test sign, first operation negative"); + a = int64x64_t (-0.5); + a *=int64x64_t (-5); + NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 2.5, "both operands negative"); + a = int64x64_t (0.5); + a *= int64x64_t (-5); + NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), -2.5, "only second operand negative"); + + return GetErrorStatus (); +} + +class Int64x64Bug863TestCase : public TestCase +{ +public: + Int64x64Bug863TestCase (); + virtual bool DoRun (void); +}; + +Int64x64Bug863TestCase::Int64x64Bug863TestCase () + : TestCase ("Test case for bug 863") +{ +} +bool +Int64x64Bug863TestCase::DoRun (void) +{ + int64x64_t a = int64x64_t (0.9); + a /= int64x64_t (1); + NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 0.9, "The original testcase"); + a = int64x64_t (0.5); + a /= int64x64_t (0.5); + NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 1.0, "Simple test for division"); + a = int64x64_t (-0.5); + NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), -0.5, "Check that we actually convert doubles correctly"); + a /= int64x64_t (0.5); + NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), -1.0, "first argument negative"); + a = int64x64_t (0.5); + a /= int64x64_t (-0.5); + NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), -1.0, "second argument negative"); + a = int64x64_t (-0.5); + a /= int64x64_t (-0.5); + NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 1.0, "both arguments negative"); + + return GetErrorStatus (); +} + +class Int64x64CompareTestCase : public TestCase +{ +public: + Int64x64CompareTestCase (); + virtual bool DoRun (void); +}; +Int64x64CompareTestCase::Int64x64CompareTestCase () + : TestCase ("Check basic compare operations") +{ +} +bool +Int64x64CompareTestCase::DoRun (void) +{ + + NS_TEST_ASSERT_MSG_EQ ((V(-1) < V(1)), true, "a is smaller than b"); + NS_TEST_ASSERT_MSG_EQ ((V(-1) > V(-2)), true, "a is bigger than b"); + NS_TEST_ASSERT_MSG_EQ ((V(-1) == V(-1)), true, "a is equal to b"); + + NS_TEST_ASSERT_MSG_EQ ((V(1) > V(-1)), true, "a is bigger than b"); + NS_TEST_ASSERT_MSG_EQ ((V(1) < V(2)), true, "a is smaller than b"); + + return GetErrorStatus (); +} + +class Int64x64InvertTestCase : public TestCase +{ +public: + Int64x64InvertTestCase (); + virtual bool DoRun (void); +}; + +Int64x64InvertTestCase::Int64x64InvertTestCase () + : TestCase ("Test case for invertion") +{ +} + +bool +Int64x64InvertTestCase::DoRun (void) +{ +#define TEST(factor) \ + do { \ + int64x64_t a; \ + a = int64x64_t::Invert (factor); \ + int64x64_t b = V (factor); \ + b.MulByInvert (a); \ + NS_TEST_ASSERT_MSG_EQ (b.GetHigh (), 1, \ + "x * 1/x should be 1 for x=" << factor); \ + int64x64_t c = V (1); \ + c.MulByInvert (a); \ + NS_TEST_ASSERT_MSG_EQ (c.GetHigh (), 0, \ + "1 * 1/x should be 0 for x=" << factor); \ + int64x64_t d = V (1); \ + d /= (V(factor)); \ + NS_TEST_ASSERT_MSG_EQ (d.GetDouble (), c.GetDouble (), \ + "1 * 1/x should be equal to 1/x for x=" << factor); \ + int64x64_t e = V (-factor); \ + e.MulByInvert (a); \ + NS_TEST_ASSERT_MSG_EQ (e.GetHigh (), -1, \ + "-x * 1/x should be -1 for x=" << factor); \ + } while(false) + TEST(2); + TEST(3); + TEST(4); + TEST(5); + TEST(6); + TEST(10); + TEST(99); + TEST(100); + TEST(1000); + TEST(10000); + TEST(100000); + TEST(100000); + TEST(1000000); + TEST(10000000); + TEST(100000000); + TEST(1000000000); + TEST(10000000000LL); + TEST(100000000000LL); + TEST(1000000000000LL); + TEST(10000000000000LL); + TEST(100000000000000LL); + TEST(1000000000000000LL); +#undef TEST + return GetErrorStatus (); +} + + + +static class Int64x64128TestSuite : public TestSuite +{ +public: + Int64x64128TestSuite () + : TestSuite ("int64x64", UNIT) + { + AddTestCase (new Int64x64FracTestCase ()); + AddTestCase (new Int64x64InputTestCase ()); + AddTestCase (new Int64x64InputOutputTestCase ()); + AddTestCase (new Int64x64ArithmeticTestCase ()); + AddTestCase (new Int64x64Bug455TestCase ()); + AddTestCase (new Int64x64Bug863TestCase ()); + AddTestCase (new Int64x64CompareTestCase ()); + AddTestCase (new Int64x64InvertTestCase ()); + } +} g_int64x64TestSuite; + +} // namespace ns3 diff -r 47eba877c2d8 -r c3854df95603 src/simulator/int64x64.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/simulator/int64x64.h Wed Aug 25 10:44:21 2010 +0200 @@ -0,0 +1,51 @@ +#ifndef INT64X64_H +#define INT64X64_H + +#include "ns3/simulator-config.h" + +#if defined (INT64X64_USE_DOUBLE) +#include "int64x64-double.h" +#elif defined (INT64X64_USE_CAIRO) +#include "int64x64-cairo.h" +#elif defined (INT64X64_USE_128) +#include "int64x64-128.h" +#endif + +#include + +namespace ns3 { + +inline int64x64_t operator + (const int64x64_t &lhs, const int64x64_t &rhs) +{ + int64x64_t tmp = lhs; + tmp += rhs; + return tmp; +} + +inline int64x64_t operator - (const int64x64_t &lhs, const int64x64_t &rhs) +{ + int64x64_t tmp = lhs; + tmp -= rhs; + return tmp; +} + +inline int64x64_t operator * (const int64x64_t &lhs, const int64x64_t &rhs) +{ + int64x64_t tmp = lhs; + tmp *= rhs; + return tmp; +} + +inline int64x64_t operator / (const int64x64_t &lhs, const int64x64_t &rhs) +{ + int64x64_t tmp = lhs; + tmp /= rhs; + return tmp; +} + +std::ostream &operator << (std::ostream &os, const int64x64_t &val); +std::istream &operator << (std::istream &is, int64x64_t &val); + +} // namespace ns3 + +#endif /* INT64X64_H */ diff -r 47eba877c2d8 -r c3854df95603 src/simulator/uint64x64-128.cc --- a/src/simulator/uint64x64-128.cc Wed Aug 25 10:36:43 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -#include "uint64x64-128.h" -#include "ns3/abort.h" -#include "ns3/assert.h" - -namespace ns3 { - -#define OUTPUT_SIGN(sa,sb,ua,ub) \ - ({bool negA, negB; \ - negA = sa < 0; \ - negB = sb < 0; \ - ua = negA?-sa:sa; \ - ub = negB?-sb:sb; \ - (negA && !negB) || (!negA && negB);}) - - -#define MASK_LO ((((int128_t)1)<<64)-1) -#define MASK_HI (~MASK_LO) - -void -uint64x64_t::Mul (uint64x64_t const &o) -{ - bool negResult; - uint128_t a, b; - negResult = OUTPUT_SIGN (_v, o._v, a, b); - int128_t result = Umul (a, b); - // add the sign to the result - result = negResult ? -result : result; - _v = result; -} - -uint128_t -uint64x64_t::Umul (uint128_t a, uint128_t b) -{ - uint128_t aL = a & MASK_LO; - uint128_t bL = b & MASK_LO; - uint128_t aH = (a >> 64) & MASK_LO; - uint128_t bH = (b >> 64) & MASK_LO; - - uint128_t result; - uint128_t hiPart,loPart,midPart; - - // Multiplying (a.h 2^64 + a.l) x (b.h 2^64 + b.l) = - // 2^128 a.h b.h + 2^64*(a.h b.l+b.h a.l) + a.l b.l - // get the low part a.l b.l - // multiply the fractional part - loPart = aL * bL; - // compute the middle part 2^64*(a.h b.l+b.h a.l) - midPart = aL * bH + aH * bL; - // truncate the low part - result = (loPart >> 64) + (midPart & MASK_LO); - // compute the high part 2^128 a.h b.h - hiPart = aH * bH; - // truncate the high part and only use the low part - result |= ((hiPart & MASK_LO) << 64) + (midPart & MASK_HI); - // if the high part is not zero, put a warning - NS_ABORT_MSG_IF ((hiPart & MASK_HI) != 0, - "High precision 128 bits multiplication error: multiplication overflow."); - return result; -} -void -uint64x64_t::Div (uint64x64_t const &o) -{ - bool negResult; - uint128_t a, b; - negResult = OUTPUT_SIGN (_v, o._v, a, b); - int128_t result = Divu (a, b); - result = negResult ? -result:result; - _v = result; -} - -uint128_t -uint64x64_t::Divu (uint128_t a, uint128_t b) -{ - uint128_t quo = a / b; - uint128_t rem = (a % b); - uint128_t result = quo << 64; - // Now, manage the remainder - uint128_t tmp = rem >> 64; - uint128_t div; - if (tmp == 0) - { - rem = rem << 64; - div = b; - } - else - { - rem = rem; - div = b >> 64; - } - quo = rem / div; - result = result + quo; - return result; -} - -void -uint64x64_t::MulByInvert (const uint64x64_t &o) -{ - bool negResult = _v < 0; - uint128_t a = negResult?-_v:_v; - uint128_t result = UmulByInvert (a, o._v); - - _v = negResult?-result:result; -} -uint128_t -uint64x64_t::UmulByInvert (uint128_t a, uint128_t b) -{ - uint128_t result, ah, bh, al, bl; - uint128_t hi, mid; - ah = a >> 64; - bh = b >> 64; - al = a & MASK_LO; - bl = b & MASK_LO; - hi = ah * bh; - mid = ah * bl + al * bh; - mid >>= 64; - result = ah * bh + mid; - return result; -} -uint64x64_t -uint64x64_t::Invert (uint64_t v) -{ - NS_ASSERT (v > 1); - uint128_t a; - a = 1; - a <<= 64; - uint64x64_t result; - result._v = Divu (a, v); - uint64x64_t tmp = uint64x64_t (v, false); - tmp.MulByInvert (result); - if (tmp.GetHigh () != 1) - { - result._v += 1; - } - return result; -} - -} // namespace ns3 - diff -r 47eba877c2d8 -r c3854df95603 src/simulator/uint64x64-128.h --- a/src/simulator/uint64x64-128.h Wed Aug 25 10:36:43 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -#ifndef UINT64X64_128_H -#define UINT64X64_128_H - -#include "ns3/simulator-config.h" -#include -#include - -#if defined(HAVE___UINT128_T) and !defined(HAVE_UINT128_T) -typedef __uint128_t uint128_t; -typedef __int128_t int128_t; -#endif - -namespace ns3 { - -#define HP128_MAX_64 18446744073709551615.0 -#define HP128_MASK_LO ((((int128_t)1)<<64)-1) - -class uint64x64_t -{ -public: - inline uint64x64_t () - : _v (0) - {} - explicit inline uint64x64_t (double value) - { - bool is_negative = value < 0; - value = is_negative?-value:value; - double hi = floor (value); - double lo = (value - hi) * HP128_MAX_64; - _v = (int128_t)hi; - _v <<= 64; - _v += (int128_t)lo; - _v = is_negative?-_v:_v; - } - explicit inline uint64x64_t (int v) - : _v (v) - { - _v <<= 64; - } - explicit inline uint64x64_t (long int v) - : _v (v) - { - _v <<= 64; - } - explicit inline uint64x64_t (long long int v) - : _v (v) - { - _v <<= 64; - } - explicit inline uint64x64_t (unsigned int v) - : _v (v) - { - _v <<= 64; - } - explicit inline uint64x64_t (unsigned long int v) - : _v (v) - { - _v <<= 64; - } - explicit inline uint64x64_t (unsigned long long int v) - : _v (v) - { - _v <<= 64; - } - explicit inline uint64x64_t (int64_t hi, uint64_t lo) - { - bool is_negative = hi<0; - _v = is_negative?-hi:hi; - _v <<= 64; - _v += lo; - _v = is_negative?-_v:_v; - } - - inline uint64x64_t (const uint64x64_t &o) - : _v (o._v) {} - inline uint64x64_t &operator = (const uint64x64_t &o) - { - _v = o._v; - return *this; - } - - inline double GetDouble (void) const - { - bool is_negative = _v < 0; - uint128_t value = is_negative ? -_v:_v; - uint64_t hi = value >> 64; - uint64_t lo = value; - double flo = lo; - flo /= HP128_MAX_64; - double retval = hi; - retval += flo; - retval = is_negative ? -retval : retval; - return retval; - } - inline int64_t GetHigh (void) const - { - bool negative = _v < 0; - int128_t v = negative?-_v:_v; - v >>= 64; - int64_t retval = v; - return negative?-retval:retval; - } - inline uint64_t GetLow (void) const - { - bool negative = _v < 0; - int128_t v = negative?-_v:_v; - int128_t low = v & HP128_MASK_LO; - uint64_t retval = low; - return retval; - } -#undef HP128_MAX_64 -#undef HP128_MASK_LO - - void MulByInvert (const uint64x64_t &o); - - static uint64x64_t Invert (uint64_t v); - -private: - friend bool operator == (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator != (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator <= (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator >= (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator < (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator > (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t &operator += (uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t &operator -= (uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t &operator *= (uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t &operator /= (uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator + (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator - (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator * (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator / (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator + (const uint64x64_t &lhs); - friend uint64x64_t operator - (const uint64x64_t &lhs); - friend uint64x64_t operator ! (const uint64x64_t &lhs); - void Mul (const uint64x64_t &o); - void Div (const uint64x64_t &o); - static uint128_t UmulByInvert (uint128_t a, uint128_t b); - static uint128_t Umul (uint128_t a, uint128_t b); - static uint128_t Divu (uint128_t a, uint128_t b); - inline uint64x64_t (int128_t v) - : _v (v) {} - - int128_t _v; -}; - -inline bool operator == (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v == rhs._v; -} - -inline bool operator != (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v != rhs._v; -} - -inline bool operator < (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v < rhs._v; -} -inline bool operator <= (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v <= rhs._v; -} - -inline bool operator >= (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v >= rhs._v; -} -inline bool operator > (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v > rhs._v; -} -inline uint64x64_t &operator += (uint64x64_t &lhs, const uint64x64_t &rhs) -{ - lhs._v += rhs._v; - return lhs; -} -inline uint64x64_t &operator -= (uint64x64_t &lhs, const uint64x64_t &rhs) -{ - lhs._v -= rhs._v; - return lhs; -} -inline uint64x64_t &operator *= (uint64x64_t &lhs, const uint64x64_t &rhs) -{ - lhs.Mul (rhs); - return lhs; -} -inline uint64x64_t &operator /= (uint64x64_t &lhs, const uint64x64_t &rhs) -{ - lhs.Div (rhs); - return lhs; -} - -inline uint64x64_t operator + (const uint64x64_t &lhs) -{ - return lhs; -} - -inline uint64x64_t operator - (const uint64x64_t &lhs) -{ - return uint64x64_t (-lhs._v); -} - -inline uint64x64_t operator ! (const uint64x64_t &lhs) -{ - return uint64x64_t (!lhs._v); -} - -} // namespace ns3 - -#endif /* UINT64X64_128_H */ diff -r 47eba877c2d8 -r c3854df95603 src/simulator/uint64x64-cairo.cc --- a/src/simulator/uint64x64-cairo.cc Wed Aug 25 10:36:43 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2006 INRIA - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ -#include "uint64x64-cairo.h" -#include "ns3/test.h" -#include "ns3/abort.h" -#include "ns3/assert.h" -#include -#include - -namespace ns3 { - -#define OUTPUT_SIGN(sa,sb,ua,ub) \ - ({bool negA, negB; \ - negA = _cairo_int128_negative (sa); \ - negB = _cairo_int128_negative (sb); \ - ua = _cairo_int128_to_uint128 (sa); \ - ub = _cairo_int128_to_uint128 (sb); \ - ua = negA ? _cairo_uint128_negate (ua) : ua; \ - ub = negB ? _cairo_uint128_negate (ub) : ub; \ - (negA && !negB) || (!negA && negB);}) - -void -uint64x64_t::Mul (uint64x64_t const &o) -{ - cairo_uint128_t a, b, result; - bool sign = OUTPUT_SIGN (_v, o._v, a, b); - result = Umul (a, b); - _v = sign ? _cairo_uint128_negate (result) : result; -} - -/** - * this function multiplies two 128 bits fractions considering - * the high 64 bits as the integer part and the low 64 bits - * as the fractional part. It takes into account the sign - * of the operands to produce a signed 128 bits result. - */ -cairo_uint128_t -uint64x64_t::Umul (cairo_uint128_t a, cairo_uint128_t b) -{ - cairo_uint128_t result; - cairo_uint128_t hiPart,loPart,midPart; - - // Multiplying (a.h 2^64 + a.l) x (b.h 2^64 + b.l) = - // 2^128 a.h b.h + 2^64*(a.h b.l+b.h a.l) + a.l b.l - // get the low part a.l b.l - // multiply the fractional part - loPart = _cairo_uint64x64_128_mul (a.lo, b.lo); - // compute the middle part 2^64*(a.h b.l+b.h a.l) - midPart = _cairo_uint128_add (_cairo_uint64x64_128_mul (a.lo, b.hi), - _cairo_uint64x64_128_mul (a.hi, b.lo)); - // truncate the low part - result.lo = _cairo_uint64_add (loPart.hi,midPart.lo); - // compute the high part 2^128 a.h b.h - hiPart = _cairo_uint64x64_128_mul (a.hi, b.hi); - // truncate the high part and only use the low part - result.hi = _cairo_uint64_add (hiPart.lo,midPart.hi); - // if the high part is not zero, put a warning - NS_ABORT_MSG_IF (hiPart.hi != 0, - "High precision 128 bits multiplication error: multiplication overflow."); - return result; -} - -void -uint64x64_t::Div (uint64x64_t const &o) -{ - cairo_uint128_t a, b, result; - bool sign = OUTPUT_SIGN (_v, o._v, a, b); - result = Udiv (a, b); - _v = sign ? _cairo_uint128_negate (result) : result; -} - -cairo_uint128_t -uint64x64_t::Udiv (cairo_uint128_t a, cairo_uint128_t b) -{ - cairo_uquorem128_t qr = _cairo_uint128_divrem (a, b); - cairo_uint128_t result = _cairo_uint128_lsl (qr.quo, 64); - // Now, manage the remainder - cairo_uint128_t tmp = _cairo_uint128_rsl (qr.rem, 64); - cairo_uint128_t zero = _cairo_uint64_to_uint128 (0); - cairo_uint128_t rem, div; - if (_cairo_uint128_eq (tmp, zero)) - { - rem = _cairo_uint128_lsl (qr.rem, 64); - div = b; - } - else - { - rem = qr.rem; - div = _cairo_uint128_rsl (b, 64); - } - qr = _cairo_uint128_divrem (rem, div); - result = _cairo_uint128_add (result, qr.quo); - return result; -} - -void -uint64x64_t::MulByInvert (const uint64x64_t &o) -{ - bool negResult = _cairo_int128_negative (_v); - cairo_uint128_t a = negResult?_cairo_int128_negate(_v):_v; - cairo_uint128_t result = UmulByInvert (a, o._v); - - _v = negResult?_cairo_int128_negate(result):result; -} -cairo_uint128_t -uint64x64_t::UmulByInvert (cairo_uint128_t a, cairo_uint128_t b) -{ - cairo_uint128_t result; - cairo_uint128_t hi, mid; - hi = _cairo_uint64x64_128_mul (a.hi, b.hi); - mid = _cairo_uint128_add (_cairo_uint64x64_128_mul (a.hi, b.lo), - _cairo_uint64x64_128_mul (a.lo, b.hi)); - mid.lo = mid.hi; - mid.hi = 0; - result = _cairo_uint128_add (hi,mid); - return result; -} -uint64x64_t -uint64x64_t::Invert (uint64_t v) -{ - NS_ASSERT (v > 1); - cairo_uint128_t a, factor; - a.hi = 1; - a.lo = 0; - factor.hi = 0; - factor.lo = v; - uint64x64_t result; - result._v = Udiv (a, factor); - uint64x64_t tmp = uint64x64_t (v, 0); - tmp.MulByInvert (result); - if (tmp.GetHigh () != 1) - { - cairo_uint128_t one = {1, 0}; - result._v = _cairo_uint128_add (result._v, one); - } - return result; -} - - -} // namespace ns3 - -// include directly to allow optimizations within the compilation unit. -extern "C" { -#include "cairo-wideint.c" -} diff -r 47eba877c2d8 -r c3854df95603 src/simulator/uint64x64-cairo.h --- a/src/simulator/uint64x64-cairo.h Wed Aug 25 10:36:43 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,242 +0,0 @@ -#ifndef UINT64X64_CAIRO_H -#define UINT64X64_CAIRO_H - -#include -#include -#include "cairo-wideint-private.h" - -#ifdef __i386__ -// this assembly code does not appear to work right yet. -#define noUINT64x64_CAIRO_ASM 1 -#endif - -namespace ns3 { - -class uint64x64_t -{ -public: - inline uint64x64_t () - { - _v.hi = 0; - _v.lo = 0; - } - explicit inline uint64x64_t (double value) - { -#define HPCAIRO_MAX_64 18446744073709551615.0 - double fhi = floor (value); - int64_t hi = fhi; - uint64_t lo = (uint64_t) ((value - fhi) * HPCAIRO_MAX_64); - _v.hi = hi; - _v.lo = lo; -#undef HPCAIRO_MAX_64 - } - explicit inline uint64x64_t (int v) - { - _v.hi = v; - _v.lo = 0; - } - explicit inline uint64x64_t (long int v) - { - _v.hi = v; - _v.lo = 0; - } - explicit inline uint64x64_t (long long int v) - { - _v.hi = v; - _v.lo = 0; - } - explicit inline uint64x64_t (int64_t hi, uint64_t lo) - { - _v.hi = hi; - _v.lo = lo; - } - - inline uint64x64_t (const uint64x64_t &o) - : _v (o._v) {} - inline uint64x64_t &operator = (const uint64x64_t &o) - { - _v = o._v; - return *this; - } - - inline double GetDouble (void) const - { -#define HPCAIRO_MAX_64 18446744073709551615.0 - bool is_negative = IsNegative (); - cairo_int128_t value = is_negative ? _cairo_int128_negate (_v) : _v; - double flo = value.lo; - flo /= HPCAIRO_MAX_64; - double retval = value.hi; - retval += flo; - retval = is_negative ? -retval: retval; - return retval; -#undef HPCAIRO_MAX_64 - } - inline int64_t GetHigh (void) const - { - return (int64_t)_v.hi; - } - inline uint64_t GetLow (void) const - { - return _v.lo; - } - - void MulByInvert (const uint64x64_t &o); - - static uint64x64_t Invert (uint64_t v); - -private: - friend bool operator == (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator != (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator <= (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator >= (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator < (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator > (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t &operator += (uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t &operator -= (uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t &operator *= (uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t &operator /= (uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator + (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator - (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator * (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator / (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator + (const uint64x64_t &lhs); - friend uint64x64_t operator - (const uint64x64_t &lhs); - friend uint64x64_t operator ! (const uint64x64_t &lhs); - void Mul (const uint64x64_t &o); - void Div (const uint64x64_t &o); - static cairo_uint128_t Umul (cairo_uint128_t a, cairo_uint128_t b); - static cairo_uint128_t Udiv (cairo_uint128_t a, cairo_uint128_t b); - static cairo_uint128_t UmulByInvert (cairo_uint128_t a, cairo_uint128_t b); - inline bool IsNegative (void) const - { - int64_t hi = _v.hi; - return hi < 0; - } - inline void Negate (void) - { - _v.lo = ~_v.lo; - _v.hi = ~_v.hi; - if (++_v.lo == 0) - { - ++_v.hi; - } - } - inline int Compare (const uint64x64_t &o) const - { - int status; - uint64x64_t tmp = *this; - tmp -= o; - status = (((int64_t)(tmp)._v.hi) < 0)?-1: - (((tmp)._v.hi == 0 && (tmp)._v.lo == 0))?0:1; - return status; - } - cairo_int128_t _v; -}; - -inline bool operator == (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v.hi == rhs._v.hi && lhs._v.lo == lhs._v.lo; -} - -inline bool operator != (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return ! (lhs == rhs); -} - -inline bool operator < (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs.Compare (rhs) < 0; -} -inline bool operator <= (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs.Compare (rhs) <= 0; -} - -inline bool operator >= (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs.Compare (rhs) >= 0; -} -inline bool operator > (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs.Compare (rhs) > 0; -} -inline uint64x64_t &operator += (uint64x64_t &lhs, const uint64x64_t &rhs) -{ -#if UINT64x64_CAIRO_ASM - asm ("mov 0(%1),%%eax\n\t" - "add %%eax,0(%0)\n\t" - "mov 4(%1),%%eax\n\t" - "adc %%eax,4(%0)\n\t" - "mov 8(%1),%%eax\n\t" - "adc %%eax,8(%0)\n\t" - "mov 12(%1),%%eax\n\t" - "adc %%eax,12(%0)\n\t" - : - : "r" (&lhs._v), "r" (&rhs._v) - : "%eax", "cc"); -#else - lhs._v.hi += rhs._v.hi; - lhs._v.lo += rhs._v.lo; - if (lhs._v.lo < rhs._v.lo) - { - lhs._v.hi++; - } -#endif - return lhs; -} -inline uint64x64_t &operator -= (uint64x64_t &lhs, const uint64x64_t &rhs) -{ -#if UINT64x64_CAIRO_ASM - asm ("mov 0(%1),%%eax\n\t" - "sub %%eax,0(%0)\n\t" - "mov 4(%1),%%eax\n\t" - "sbb %%eax,4(%0)\n\t" - "mov 8(%1),%%eax\n\t" - "sbb %%eax,8(%0)\n\t" - "mov 12(%1),%%eax\n\t" - "sbb %%eax,12(%0)\n\t" - : - : "r" (&lhs._v), "r" (&rhs._v) - : "%eax", "cc"); -#else - lhs._v.hi -= rhs._v.hi; - lhs._v.lo -= rhs._v.lo; - if (lhs._v.lo > rhs._v.lo) - { - lhs._v.hi--; - } -#endif - return lhs; -} -inline uint64x64_t &operator *= (uint64x64_t &lhs, const uint64x64_t &rhs) -{ - lhs.Mul (rhs); - return lhs; -} -inline uint64x64_t &operator /= (uint64x64_t &lhs, const uint64x64_t &rhs) -{ - lhs.Div (rhs); - return lhs; -} - -inline uint64x64_t operator + (const uint64x64_t &lhs) -{ - return lhs; -} - -inline uint64x64_t operator - (const uint64x64_t &lhs) -{ - uint64x64_t tmp = lhs; - tmp.Negate (); - return tmp; -} - -inline uint64x64_t operator ! (const uint64x64_t &lhs) -{ - return (lhs._v.hi == 0 && lhs._v.lo == 0)?uint64x64_t (1, 0):uint64x64_t (); -} - -} // namespace ns3 - -#endif /* UINT64X64_CAIRO_H */ diff -r 47eba877c2d8 -r c3854df95603 src/simulator/uint64x64-double.h --- a/src/simulator/uint64x64-double.h Wed Aug 25 10:36:43 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -#ifndef UINT64X64_DOUBLE_H -#define UINT64X64_DOUBLE_H - -#include -#include - -namespace ns3 { - -class uint64x64_t -{ -public: - inline uint64x64_t () - : _v (0) {} - explicit inline uint64x64_t (double v) - : _v (v) {} - explicit inline uint64x64_t (int v) - : _v (v) {} - explicit inline uint64x64_t (long int v) - : _v (v) {} - explicit inline uint64x64_t (long long int v) - : _v (v) {} - inline uint64x64_t (int64_t hi, uint64_t lo) - : _v (hi) {/* XXX */} - - inline uint64x64_t (const uint64x64_t &o) - : _v (o._v) {} - inline uint64x64_t &operator = (const uint64x64_t &o) - { - _v = o._v; - return *this; - } - - inline double GetDouble (void) const - { - return _v; - } - inline int64_t GetHigh (void) const - { - return (int64_t)floor (_v); - } - inline uint64_t GetLow (void) const - { - // XXX - return 0; - } - - inline void MulByInvert (const uint64x64_t &o) - { - _v *= o._v; - } - - static inline uint64x64_t Invert (uint64_t v) - { - double d = v; - return uint64x64_t (1/d); - } - -private: - friend bool operator == (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator != (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator <= (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator >= (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator < (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend bool operator > (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t &operator += (uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t &operator -= (uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t &operator *= (uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t &operator /= (uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator + (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator - (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator * (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator / (const uint64x64_t &lhs, const uint64x64_t &rhs); - friend uint64x64_t operator + (const uint64x64_t &lhs); - friend uint64x64_t operator - (const uint64x64_t &lhs); - friend uint64x64_t operator ! (const uint64x64_t &lhs); - - double _v; -}; - -inline bool operator == (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v == rhs._v; -} - -inline bool operator != (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v != rhs._v; -} - -inline bool operator <= (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v <= rhs._v; -} - -inline bool operator >= (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v >= rhs._v; -} -inline bool operator < (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v < rhs._v; -} -inline bool operator > (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - return lhs._v > rhs._v; -} -inline uint64x64_t &operator += (uint64x64_t &lhs, const uint64x64_t &rhs) -{ - double tmp = lhs._v; - tmp += rhs._v; - lhs = uint64x64_t (tmp); - return lhs; -} -inline uint64x64_t &operator -= (uint64x64_t &lhs, const uint64x64_t &rhs) -{ - double tmp = lhs._v; - tmp -= rhs._v; - lhs = uint64x64_t (tmp); - return lhs; -} -inline uint64x64_t &operator *= (uint64x64_t &lhs, const uint64x64_t &rhs) -{ - double tmp = lhs._v; - tmp *= rhs._v; - lhs = uint64x64_t (tmp); - return lhs; -} -inline uint64x64_t &operator /= (uint64x64_t &lhs, const uint64x64_t &rhs) -{ - double tmp = lhs._v; - tmp /= rhs._v; - lhs = uint64x64_t (tmp); - return lhs; -} - -inline uint64x64_t operator + (const uint64x64_t &lhs) -{ - return lhs; -} - -inline uint64x64_t operator - (const uint64x64_t &lhs) -{ - return uint64x64_t (-lhs._v); -} - -inline uint64x64_t operator ! (const uint64x64_t &lhs) -{ - return uint64x64_t (!lhs._v); -} - -} // namespace ns3 - -#endif /* UINT64X64_DOUBLE_H */ diff -r 47eba877c2d8 -r c3854df95603 src/simulator/uint64x64.cc --- a/src/simulator/uint64x64.cc Wed Aug 25 10:36:43 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,460 +0,0 @@ -#include "uint64x64.h" -#include -#include -#include -#include "ns3/assert.h" - -namespace ns3 { - -static uint8_t MostSignificantDigit (uint64_t value) -{ - uint8_t n = 0; - do - { - n++; - value /= 10; - } while (value != 0); - return n; -} - -static uint64_t PowerOfTen (uint8_t n) -{ - uint64_t retval = 1; - while (n > 0) - { - retval *= 10; - n--; - } - return retval; -} - -std::ostream &operator << (std::ostream &os, const uint64x64_t &value) -{ - int64_t hi = value.GetHigh (); - os << ((hi<0)?"-":"+") << ((hi<0)?-hi:hi) << "."; - uint64_t low = value.GetLow (); - uint8_t msd = MostSignificantDigit (~((uint64_t)0)); - do - { - msd--; - uint64_t pow = PowerOfTen (msd); - uint8_t digit = low / pow; - NS_ASSERT (digit < 10); - os << (uint16_t) digit; - low -= digit * pow; - } while (msd > 0 && low > 0); - return os; -} - -static uint64_t ReadDigits (std::string str) -{ - const char *buf = str.c_str (); - uint64_t retval = 0; - while (*buf != 0) - { - retval *= 10; - retval += *buf - 0x30; - buf++; - } - return retval; -} - -std::istream &operator >> (std::istream &is, uint64x64_t &value) -{ - std::string str; - - is >> str; - bool negative; - // skip heading spaces - std::string::size_type cur; - cur = str.find_first_not_of (" "); - std::string::size_type next; - // first, remove the sign. - next = str.find ("-", cur); - if (next != std::string::npos) - { - negative = true; - next++; - } - else - { - next = str.find ("+", cur); - if (next != std::string::npos) - { - next++; - } - else - { - next = cur; - } - negative = false; - } - cur = next; - int64_t hi; - uint64_t lo; - next = str.find(".", cur); - if (next != std::string::npos) - { - hi = ReadDigits (str.substr (cur, next-cur)); - lo = ReadDigits (str.substr (next+1, str.size()-(next+1))); - } - else - { - hi = ReadDigits (str.substr (cur, str.size ()-cur)); - lo = 0; - } - hi = negative?-hi:hi; - value = uint64x64_t (hi, lo); - return is; -} - -} // namespace ns3 - -#include "ns3/test.h" - -namespace ns3 -{ - -class Uint64x64FracTestCase : public TestCase -{ -public: - Uint64x64FracTestCase (); - virtual bool DoRun (void); - void CheckFrac (int64_t hi, uint64_t lo); -}; - -void -Uint64x64FracTestCase::CheckFrac (int64_t hi, uint64_t lo) -{ - uint64x64_t tmp = uint64x64_t (hi,lo); - NS_TEST_EXPECT_MSG_EQ (tmp.GetHigh (), hi, - "High part does not match"); - NS_TEST_EXPECT_MSG_EQ (tmp.GetLow (), lo, - "Low part does not match"); -} - -Uint64x64FracTestCase::Uint64x64FracTestCase () - : TestCase ("Check that we can manipulate the high and low part of every number") -{ -} -bool -Uint64x64FracTestCase::DoRun (void) -{ - CheckFrac (1, 0); - CheckFrac (1, 1); - CheckFrac (-1, 0); - CheckFrac (-1, 1); - return GetErrorStatus (); -} - - -class Uint64x64InputTestCase : public TestCase -{ -public: - Uint64x64InputTestCase (); - virtual bool DoRun (void); - void CheckString (std::string str, int64_t hi, uint64_t lo); -}; -Uint64x64InputTestCase::Uint64x64InputTestCase () - : TestCase ("Check that we parse Uint64x64 numbers as strings") -{ -} -void -Uint64x64InputTestCase::CheckString (std::string str, int64_t hi, uint64_t lo) -{ - std::istringstream iss; - iss.str (str); - uint64x64_t hp; - iss >> hp; - NS_TEST_EXPECT_MSG_EQ (hp.GetHigh (), hi, "High parts do not match for input string " << str); - NS_TEST_EXPECT_MSG_EQ (hp.GetLow (), lo, "Low parts do not match for input string " << str); -} -bool -Uint64x64InputTestCase::DoRun (void) -{ - CheckString ("1", 1, 0); - CheckString ("+1", 1, 0); - CheckString ("-1", -1, 0); - CheckString ("1.0", 1, 0); - CheckString ("+1.0", 1, 0); - CheckString ("001.0", 1, 0); - CheckString ("+001.0", 1, 0); - CheckString ("020.0", 20, 0); - CheckString ("+020.0", 20, 0); - CheckString ("-1.0", -1, 0); - CheckString ("-1.0000", -1, 0); - CheckString ("1.0000000", 1, 0); - CheckString ("1.08446744073709551615", 1, 8446744073709551615LL); - CheckString ("-1.08446744073709551615", -1, 8446744073709551615LL); - - return GetErrorStatus (); -} - -class Uint64x64InputOutputTestCase : public TestCase -{ -public: - Uint64x64InputOutputTestCase (); - virtual bool DoRun (void); - void CheckString (std::string str); -}; -Uint64x64InputOutputTestCase::Uint64x64InputOutputTestCase () - : TestCase ("Check that we can roundtrip Uint64x64 numbers as strings") -{ -} -void -Uint64x64InputOutputTestCase::CheckString (std::string str) -{ - std::istringstream iss; - iss.str (str); - uint64x64_t value; - iss >> value; - std::ostringstream oss; - oss << value; - NS_TEST_EXPECT_MSG_EQ (oss.str (), str, "Converted string does not match expected string"); -} -bool -Uint64x64InputOutputTestCase::DoRun (void) -{ - CheckString ("+1.0"); - CheckString ("-1.0"); - CheckString ("+20.0"); - CheckString ("+1.08446744073709551615"); - CheckString ("-1.08446744073709551615"); - CheckString ("+1.18446744073709551615"); - CheckString ("-1.18446744073709551615"); - - return GetErrorStatus (); -} - -#define CHECK_EXPECTED(a,b) \ - NS_TEST_ASSERT_MSG_EQ ((a).GetHigh (),b,"Arithmetic failure: " << ((a).GetHigh ()) << "!=" << (b)) - -#define V(v) \ - uint64x64_t (v) - -class Uint64x64ArithmeticTestCase : public TestCase -{ -public: - Uint64x64ArithmeticTestCase (); - virtual bool DoRun (void); -}; - -Uint64x64ArithmeticTestCase::Uint64x64ArithmeticTestCase () - : TestCase ("Check basic arithmetic operations") -{ -} -bool -Uint64x64ArithmeticTestCase::DoRun (void) -{ - uint64x64_t a, b; - - CHECK_EXPECTED (V(1) - V(1), 0); - CHECK_EXPECTED (V(1) - V(2), -1); - CHECK_EXPECTED (V(1) - V(3), -2); - CHECK_EXPECTED (V(1) - V(-1), 2); - CHECK_EXPECTED (V(1) - V(-2), 3); - CHECK_EXPECTED (V(-3) - V(-4), 1); - CHECK_EXPECTED (V(-2) - V(3), -5); - CHECK_EXPECTED (V(1) + V(2), 3); - CHECK_EXPECTED (V(1) + V(-3), -2); - CHECK_EXPECTED (V(0) + V(0), 0); - CHECK_EXPECTED (V(0) * V(0), 0); - CHECK_EXPECTED (V(0) * V(1), 0); - CHECK_EXPECTED (V(0) * V(-1), 0); - CHECK_EXPECTED (V(1) * V(0), 0); - CHECK_EXPECTED (V(1) * V(1), 1); - CHECK_EXPECTED (V(1) * V(-1), -1); - CHECK_EXPECTED (V(-1) * V(-1), 1); - CHECK_EXPECTED (V(0) * V(1), 0); - CHECK_EXPECTED (V(0) * V(-1), 0); - CHECK_EXPECTED (V(-1) * V(1), -1); - - - CHECK_EXPECTED (V (2) * V(3) / V(3), 2); - - // Below, the division loses precision because 2/3 is not - // representable exactly in 64.64 integers. So, we got - // something super close but the final rounding kills us. - CHECK_EXPECTED (V(2) / V(3) * V(3), 1); - - // The example below shows that we really do not lose - // much precision internally: it is almost always the - // final conversion which loses precision. - CHECK_EXPECTED (V (2000000000) / V(3) * V(3), 1999999999); - - return GetErrorStatus (); -} - -class Uint64x64Bug455TestCase : public TestCase -{ -public: - Uint64x64Bug455TestCase (); - virtual bool DoRun (void); -}; - -Uint64x64Bug455TestCase::Uint64x64Bug455TestCase () - : TestCase ("Test case for bug 455") -{ -} -bool -Uint64x64Bug455TestCase::DoRun (void) -{ - uint64x64_t a = uint64x64_t (0.1); - a /= uint64x64_t (1.25); - NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 0.08, "The original testcase"); - a = uint64x64_t (0.5); - a *= uint64x64_t (5); - NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 2.5, "Simple test for multiplication"); - a = uint64x64_t (-0.5); - a *= uint64x64_t (5); - NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), -2.5, "Test sign, first operation negative"); - a = uint64x64_t (-0.5); - a *=uint64x64_t (-5); - NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 2.5, "both operands negative"); - a = uint64x64_t (0.5); - a *= uint64x64_t (-5); - NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), -2.5, "only second operand negative"); - - return GetErrorStatus (); -} - -class Uint64x64Bug863TestCase : public TestCase -{ -public: - Uint64x64Bug863TestCase (); - virtual bool DoRun (void); -}; - -Uint64x64Bug863TestCase::Uint64x64Bug863TestCase () - : TestCase ("Test case for bug 863") -{ -} -bool -Uint64x64Bug863TestCase::DoRun (void) -{ - uint64x64_t a = uint64x64_t (0.9); - a /= uint64x64_t (1); - NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 0.9, "The original testcase"); - a = uint64x64_t (0.5); - a /= uint64x64_t (0.5); - NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 1.0, "Simple test for division"); - a = uint64x64_t (-0.5); - NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), -0.5, "Check that we actually convert doubles correctly"); - a /= uint64x64_t (0.5); - NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), -1.0, "first argument negative"); - a = uint64x64_t (0.5); - a /= uint64x64_t (-0.5); - NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), -1.0, "second argument negative"); - a = uint64x64_t (-0.5); - a /= uint64x64_t (-0.5); - NS_TEST_ASSERT_MSG_EQ (a.GetDouble (), 1.0, "both arguments negative"); - - return GetErrorStatus (); -} - -class Uint64x64CompareTestCase : public TestCase -{ -public: - Uint64x64CompareTestCase (); - virtual bool DoRun (void); -}; -Uint64x64CompareTestCase::Uint64x64CompareTestCase () - : TestCase ("Check basic compare operations") -{ -} -bool -Uint64x64CompareTestCase::DoRun (void) -{ - - NS_TEST_ASSERT_MSG_EQ ((V(-1) < V(1)), true, "a is smaller than b"); - NS_TEST_ASSERT_MSG_EQ ((V(-1) > V(-2)), true, "a is bigger than b"); - NS_TEST_ASSERT_MSG_EQ ((V(-1) == V(-1)), true, "a is equal to b"); - - NS_TEST_ASSERT_MSG_EQ ((V(1) > V(-1)), true, "a is bigger than b"); - NS_TEST_ASSERT_MSG_EQ ((V(1) < V(2)), true, "a is smaller than b"); - - return GetErrorStatus (); -} - -class Uint64x64InvertTestCase : public TestCase -{ -public: - Uint64x64InvertTestCase (); - virtual bool DoRun (void); -}; - -Uint64x64InvertTestCase::Uint64x64InvertTestCase () - : TestCase ("Test case for invertion") -{ -} - -bool -Uint64x64InvertTestCase::DoRun (void) -{ -#define TEST(factor) \ - do { \ - uint64x64_t a; \ - a = uint64x64_t::Invert (factor); \ - uint64x64_t b = V (factor); \ - b.MulByInvert (a); \ - NS_TEST_ASSERT_MSG_EQ (b.GetHigh (), 1, \ - "x * 1/x should be 1 for x=" << factor); \ - uint64x64_t c = V (1); \ - c.MulByInvert (a); \ - NS_TEST_ASSERT_MSG_EQ (c.GetHigh (), 0, \ - "1 * 1/x should be 0 for x=" << factor); \ - uint64x64_t d = V (1); \ - d /= (V(factor)); \ - NS_TEST_ASSERT_MSG_EQ (d.GetDouble (), c.GetDouble (), \ - "1 * 1/x should be equal to 1/x for x=" << factor); \ - uint64x64_t e = V (-factor); \ - e.MulByInvert (a); \ - NS_TEST_ASSERT_MSG_EQ (e.GetHigh (), -1, \ - "-x * 1/x should be -1 for x=" << factor); \ - } while(false) - TEST(2); - TEST(3); - TEST(4); - TEST(5); - TEST(6); - TEST(10); - TEST(99); - TEST(100); - TEST(1000); - TEST(10000); - TEST(100000); - TEST(100000); - TEST(1000000); - TEST(10000000); - TEST(100000000); - TEST(1000000000); - TEST(10000000000LL); - TEST(100000000000LL); - TEST(1000000000000LL); - TEST(10000000000000LL); - TEST(100000000000000LL); - TEST(1000000000000000LL); -#undef TEST - return GetErrorStatus (); -} - - - -static class Uint64x64128TestSuite : public TestSuite -{ -public: - Uint64x64128TestSuite () - : TestSuite ("uint64x64", UNIT) - { - AddTestCase (new Uint64x64FracTestCase ()); - AddTestCase (new Uint64x64InputTestCase ()); - AddTestCase (new Uint64x64InputOutputTestCase ()); - AddTestCase (new Uint64x64ArithmeticTestCase ()); - AddTestCase (new Uint64x64Bug455TestCase ()); - AddTestCase (new Uint64x64Bug863TestCase ()); - AddTestCase (new Uint64x64CompareTestCase ()); - AddTestCase (new Uint64x64InvertTestCase ()); - } -} g_uint64x64TestSuite; - -} // namespace ns3 diff -r 47eba877c2d8 -r c3854df95603 src/simulator/uint64x64.h --- a/src/simulator/uint64x64.h Wed Aug 25 10:36:43 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -#ifndef UINT64X64_H -#define UINT64X64_H - -#include "ns3/simulator-config.h" - -#if defined (UINT64x64_USE_DOUBLE) -#include "uint64x64-double.h" -#elif defined (UINT64x64_USE_CAIRO) -#include "uint64x64-cairo.h" -#elif defined (UINT64x64_USE_128) -#include "uint64x64-128.h" -#endif - -#include - -namespace ns3 { - -inline uint64x64_t operator + (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - uint64x64_t tmp = lhs; - tmp += rhs; - return tmp; -} - -inline uint64x64_t operator - (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - uint64x64_t tmp = lhs; - tmp -= rhs; - return tmp; -} - -inline uint64x64_t operator * (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - uint64x64_t tmp = lhs; - tmp *= rhs; - return tmp; -} - -inline uint64x64_t operator / (const uint64x64_t &lhs, const uint64x64_t &rhs) -{ - uint64x64_t tmp = lhs; - tmp /= rhs; - return tmp; -} - -std::ostream &operator << (std::ostream &os, const uint64x64_t &val); -std::istream &operator << (std::istream &is, uint64x64_t &val); - -} // namespace ns3 - -#endif /* UINT64X64_H */ diff -r 47eba877c2d8 -r c3854df95603 src/simulator/wscript --- a/src/simulator/wscript Wed Aug 25 10:36:43 2010 +0200 +++ b/src/simulator/wscript Wed Aug 25 10:44:21 2010 +0200 @@ -20,15 +20,15 @@ if Options.options.high_precision_as_double: - conf.define('UINT64x64_USE_DOUBLE', 1) + conf.define('INT64X64_USE_DOUBLE', 1) conf.env['USE_HIGH_PRECISION_DOUBLE'] = 1 highprec = 'long double' elif a or b: - conf.define('UINT64x64_USE_128', 1) + conf.define('INT64X64_USE_128', 1) conf.env['USE_HIGH_PRECISION_128'] = 1 highprec = '128-bit integer' else: - conf.define('UINT64x64_USE_CAIRO', 1) + conf.define('INT64X64_USE_CAIRO', 1) conf.env['USE_HIGH_PRECISION_CAIRO'] = 1 highprec = 'cairo 128-bit integer' @@ -54,7 +54,7 @@ def build(bld): sim = bld.create_ns3_module('simulator', ['core']) sim.source = [ - 'uint64x64.cc', + 'int64x64.cc', 'time.cc', 'event-id.cc', 'scheduler.cc', @@ -76,7 +76,7 @@ headers = bld.new_task_gen('ns3header') headers.module = 'simulator' headers.source = [ - 'uint64x64.h', + 'int64x64.h', 'nstime.h', 'event-id.h', 'event-impl.h', @@ -99,16 +99,16 @@ env = bld.env_of_name('default') if env['USE_HIGH_PRECISION_DOUBLE']: - headers.source.extend(['uint64x64-double.h']) + headers.source.extend(['int64x64-double.h']) elif env['USE_HIGH_PRECISION_128']: - headers.source.extend(['uint64x64-128.h']) - sim.source.extend(['uint64x64-128.cc']) + headers.source.extend(['int64x64-128.h']) + sim.source.extend(['int64x64-128.cc']) elif env['USE_HIGH_PRECISION_CAIRO']: sim.source.extend([ - 'uint64x64-cairo.cc', + 'int64x64-cairo.cc', ]) headers.source.extend([ - 'uint64x64-cairo.h', + 'int64x64-cairo.h', 'cairo-wideint-private.h', ])