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 "
log.h
"
25
#include <cmath>
26
#include <iostream>
27
28
// Note: Logging in this file is largely avoided due to the
29
// number of calls that are made to these functions and the possibility
30
// of causing recursions leading to stack overflow
31
32
NS_LOG_COMPONENT_DEFINE
(
"int64x64-cairo"
);
33
34
namespace
ns3 {
35
36
#define OUTPUT_SIGN(sa,sb,ua,ub) \
37
({ bool negA, negB; \
38
negA = _cairo_int128_negative (sa); \
39
negB = _cairo_int128_negative (sb); \
40
ua = _cairo_int128_to_uint128 (sa); \
41
ub = _cairo_int128_to_uint128 (sb); \
42
ua = negA ? _cairo_uint128_negate (ua) : ua; \
43
ub = negB ? _cairo_uint128_negate (ub) : ub; \
44
(negA && !negB) || (!negA && negB); })
45
46
void
47
int64x64_t::Mul (int64x64_t
const
&o)
48
{
49
cairo_uint128_t a, b, result;
50
bool
sign =
OUTPUT_SIGN
(_v, o._v, a, b);
51
result = Umul (a, b);
52
_v = sign ?
_cairo_uint128_negate
(result) : result;
53
}
54
61
cairo_uint128_t
62
int64x64_t::Umul (cairo_uint128_t a, cairo_uint128_t b)
63
{
64
cairo_uint128_t result;
65
cairo_uint128_t hiPart,loPart,midPart;
66
67
// Multiplying (a.h 2^64 + a.l) x (b.h 2^64 + b.l) =
68
// 2^128 a.h b.h + 2^64*(a.h b.l+b.h a.l) + a.l b.l
69
// get the low part a.l b.l
70
// multiply the fractional part
71
loPart =
_cairo_uint64x64_128_mul
(a.lo, b.lo);
72
// compute the middle part 2^64*(a.h b.l+b.h a.l)
73
midPart =
_cairo_uint128_add
(
_cairo_uint64x64_128_mul
(a.lo, b.hi),
74
_cairo_uint64x64_128_mul
(a.hi, b.lo));
75
// truncate the low part
76
result.lo =
_cairo_uint64_add
(loPart.hi,midPart.lo);
77
// compute the high part 2^128 a.h b.h
78
hiPart =
_cairo_uint64x64_128_mul
(a.hi, b.hi);
79
// truncate the high part and only use the low part
80
result.hi =
_cairo_uint64_add
(hiPart.lo,midPart.hi);
81
// if the high part is not zero, put a warning
82
NS_ABORT_MSG_IF
(hiPart.hi != 0,
83
"High precision 128 bits multiplication error: multiplication overflow."
);
84
return
result;
85
}
86
87
void
88
int64x64_t::Div (int64x64_t
const
&o)
89
{
90
cairo_uint128_t a, b, result;
91
bool
sign =
OUTPUT_SIGN
(_v, o._v, a, b);
92
result = Udiv (a, b);
93
_v = sign ?
_cairo_uint128_negate
(result) : result;
94
}
95
96
cairo_uint128_t
97
int64x64_t::Udiv (cairo_uint128_t a, cairo_uint128_t b)
98
{
99
cairo_uquorem128_t
qr =
_cairo_uint128_divrem
(a, b);
100
cairo_uint128_t result =
_cairo_uint128_lsl
(qr.
quo
, 64);
101
// Now, manage the remainder
102
cairo_uint128_t tmp =
_cairo_uint128_rsl
(qr.
rem
, 64);
103
cairo_uint128_t
zero
=
_cairo_uint64_to_uint128
(0);
104
cairo_uint128_t rem, div;
105
if
(
_cairo_uint128_eq
(tmp, zero))
106
{
107
rem =
_cairo_uint128_lsl
(qr.
rem
, 64);
108
div = b;
109
}
110
else
111
{
112
rem = qr.
rem
;
113
div =
_cairo_uint128_rsl
(b, 64);
114
}
115
qr =
_cairo_uint128_divrem
(rem, div);
116
result =
_cairo_uint128_add
(result, qr.
quo
);
117
return
result;
118
}
119
120
void
121
int64x64_t::MulByInvert (
const
int64x64_t &o)
122
{
123
bool
negResult =
_cairo_int128_negative
(_v);
124
cairo_uint128_t a = negResult ?
_cairo_int128_negate
(_v) : _v;
125
cairo_uint128_t result = UmulByInvert (a, o._v);
126
127
_v = negResult ?
_cairo_int128_negate
(result) : result;
128
}
129
cairo_uint128_t
130
int64x64_t::UmulByInvert (cairo_uint128_t a, cairo_uint128_t b)
131
{
132
cairo_uint128_t result;
133
cairo_uint128_t hi, mid;
134
hi =
_cairo_uint64x64_128_mul
(a.hi, b.hi);
135
mid =
_cairo_uint128_add
(
_cairo_uint64x64_128_mul
(a.hi, b.lo),
136
_cairo_uint64x64_128_mul
(a.lo, b.hi));
137
mid.lo = mid.hi;
138
mid.hi = 0;
139
result =
_cairo_uint128_add
(hi,mid);
140
return
result;
141
}
142
int64x64_t
143
int64x64_t::Invert (uint64_t v)
144
{
145
NS_ASSERT
(v > 1);
146
cairo_uint128_t a, factor;
147
a.hi = 1;
148
a.lo = 0;
149
factor.hi = 0;
150
factor.lo = v;
151
int64x64_t result;
152
result._v = Udiv (a, factor);
153
int64x64_t tmp = int64x64_t (v, 0);
154
tmp.MulByInvert (result);
155
if
(tmp.GetHigh () != 1)
156
{
157
cairo_uint128_t one = { 1, 0};
158
result._v =
_cairo_uint128_add
(result._v, one);
159
}
160
return
result;
161
}
162
163
164
}
// namespace ns3
165
166
// include directly to allow optimizations within the compilation unit.
167
extern
"C"
{
168
#include "
cairo-wideint.c
"
169
}
src
core
model
int64x64-cairo.cc
Generated on Tue May 14 2013 11:08:17 for ns-3 by
1.8.1.2