A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Portuguese
Docs ▼
Wiki
Manual
Models
Develop ▼
API
Bugs
API
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Properties
Friends
Macros
Groups
Pages
int64x64-cairo.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
* Copyright (c) 2006 INRIA
4
*
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 2 as
7
* published by the Free Software Foundation;
8
*
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
*
18
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
*/
20
#include "
int64x64-cairo.h
"
21
#include "
test.h
"
22
#include "
abort.h
"
23
#include "
assert.h
"
24
#include <math.h>
25
#include <iostream>
26
27
namespace
ns3 {
28
29
#define OUTPUT_SIGN(sa,sb,ua,ub) \
30
({ bool negA, negB; \
31
negA = _cairo_int128_negative (sa); \
32
negB = _cairo_int128_negative (sb); \
33
ua = _cairo_int128_to_uint128 (sa); \
34
ub = _cairo_int128_to_uint128 (sb); \
35
ua = negA ? _cairo_uint128_negate (ua) : ua; \
36
ub = negB ? _cairo_uint128_negate (ub) : ub; \
37
(negA && !negB) || (!negA && negB); })
38
39
void
40
int64x64_t::Mul (int64x64_t
const
&o)
41
{
42
cairo_uint128_t a, b, result;
43
bool
sign =
OUTPUT_SIGN
(_v, o._v, a, b);
44
result = Umul (a, b);
45
_v = sign ?
_cairo_uint128_negate
(result) : result;
46
}
47
54
cairo_uint128_t
55
int64x64_t::Umul (cairo_uint128_t a, cairo_uint128_t b)
56
{
57
cairo_uint128_t result;
58
cairo_uint128_t hiPart,loPart,midPart;
59
60
// Multiplying (a.h 2^64 + a.l) x (b.h 2^64 + b.l) =
61
// 2^128 a.h b.h + 2^64*(a.h b.l+b.h a.l) + a.l b.l
62
// get the low part a.l b.l
63
// multiply the fractional part
64
loPart =
_cairo_uint64x64_128_mul
(a.lo, b.lo);
65
// compute the middle part 2^64*(a.h b.l+b.h a.l)
66
midPart =
_cairo_uint128_add
(
_cairo_uint64x64_128_mul
(a.lo, b.hi),
67
_cairo_uint64x64_128_mul
(a.hi, b.lo));
68
// truncate the low part
69
result.lo =
_cairo_uint64_add
(loPart.hi,midPart.lo);
70
// compute the high part 2^128 a.h b.h
71
hiPart =
_cairo_uint64x64_128_mul
(a.hi, b.hi);
72
// truncate the high part and only use the low part
73
result.hi =
_cairo_uint64_add
(hiPart.lo,midPart.hi);
74
// if the high part is not zero, put a warning
75
NS_ABORT_MSG_IF
(hiPart.hi != 0,
76
"High precision 128 bits multiplication error: multiplication overflow."
);
77
return
result;
78
}
79
80
void
81
int64x64_t::Div (int64x64_t
const
&o)
82
{
83
cairo_uint128_t a, b, result;
84
bool
sign =
OUTPUT_SIGN
(_v, o._v, a, b);
85
result = Udiv (a, b);
86
_v = sign ?
_cairo_uint128_negate
(result) : result;
87
}
88
89
cairo_uint128_t
90
int64x64_t::Udiv (cairo_uint128_t a, cairo_uint128_t b)
91
{
92
cairo_uquorem128_t
qr =
_cairo_uint128_divrem
(a, b);
93
cairo_uint128_t result =
_cairo_uint128_lsl
(qr.
quo
, 64);
94
// Now, manage the remainder
95
cairo_uint128_t tmp =
_cairo_uint128_rsl
(qr.
rem
, 64);
96
cairo_uint128_t
zero
=
_cairo_uint64_to_uint128
(0);
97
cairo_uint128_t rem, div;
98
if
(
_cairo_uint128_eq
(tmp, zero))
99
{
100
rem =
_cairo_uint128_lsl
(qr.
rem
, 64);
101
div = b;
102
}
103
else
104
{
105
rem = qr.
rem
;
106
div =
_cairo_uint128_rsl
(b, 64);
107
}
108
qr =
_cairo_uint128_divrem
(rem, div);
109
result =
_cairo_uint128_add
(result, qr.
quo
);
110
return
result;
111
}
112
113
void
114
int64x64_t::MulByInvert (
const
int64x64_t &o)
115
{
116
bool
negResult =
_cairo_int128_negative
(_v);
117
cairo_uint128_t a = negResult ?
_cairo_int128_negate
(_v) : _v;
118
cairo_uint128_t result = UmulByInvert (a, o._v);
119
120
_v = negResult ?
_cairo_int128_negate
(result) : result;
121
}
122
cairo_uint128_t
123
int64x64_t::UmulByInvert (cairo_uint128_t a, cairo_uint128_t b)
124
{
125
cairo_uint128_t result;
126
cairo_uint128_t hi, mid;
127
hi =
_cairo_uint64x64_128_mul
(a.hi, b.hi);
128
mid =
_cairo_uint128_add
(
_cairo_uint64x64_128_mul
(a.hi, b.lo),
129
_cairo_uint64x64_128_mul
(a.lo, b.hi));
130
mid.lo = mid.hi;
131
mid.hi = 0;
132
result =
_cairo_uint128_add
(hi,mid);
133
return
result;
134
}
135
int64x64_t
136
int64x64_t::Invert (uint64_t v)
137
{
138
NS_ASSERT
(v > 1);
139
cairo_uint128_t a, factor;
140
a.hi = 1;
141
a.lo = 0;
142
factor.hi = 0;
143
factor.lo = v;
144
int64x64_t result;
145
result._v = Udiv (a, factor);
146
int64x64_t tmp = int64x64_t (v, 0);
147
tmp.MulByInvert (result);
148
if
(tmp.GetHigh () != 1)
149
{
150
cairo_uint128_t one = { 1, 0};
151
result._v =
_cairo_uint128_add
(result._v, one);
152
}
153
return
result;
154
}
155
156
157
}
// namespace ns3
158
159
// include directly to allow optimizations within the compilation unit.
160
extern
"C"
{
161
#include "
cairo-wideint.c
"
162
}
src
core
model
int64x64-cairo.cc
Generated on Tue Nov 13 2012 10:32:10 for ns-3 by
1.8.1.2