A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Documentation ▼
Installation
Manual
Models
Contributing
Wiki
Development ▼
API Docs
Issue Tracker
Merge Requests
API
Loading...
Searching...
No Matches
int64x64.cc
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2010 INRIA
3
*
4
* SPDX-License-Identifier: GPL-2.0-only
5
*/
6
7
#include "
int64x64.h
"
8
9
#include "
assert.h
"
10
#include "
log.h
"
11
12
#include <iomanip>
// showpos
13
#include <iostream>
14
#include <limits>
15
#include <sstream>
16
#include <stdint.h>
17
18
/**
19
* @file
20
* @ingroup highprec
21
* Implementation of the streaming input and output operators for
22
* the ns3::int64x64_t type.
23
*/
24
25
namespace
ns3
26
{
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
NS_LOG_COMPONENT_DEFINE_MASK
(
"int64x64"
,
LOG_PREFIX_TIME
);
32
33
/**
34
* @ingroup highprec
35
* Print the high and low words of an int64x64 in hex, for debugging.
36
*
37
* @param [in] hi The high (integer) word.
38
* @param [in] lo The low (fractional) work.
39
*/
40
#define HEXHILOW(hi, lo) \
41
std::hex << std::setfill('0') << std::right << " (0x" << std::setw(16) << hi << " " \
42
<< std::setw(16) << lo << std::dec << std::setfill(' ') << std::left << ")"
43
44
/**
45
* @internal
46
* This algorithm is exact to the precision requested, up to the full
47
* 64 decimal digits required to exactly represent a 64-bit fraction.
48
*
49
* Proper rounding turns out to be surprisingly hard.
50
* In `y.xxxx5|6`, where the `|` marks follows the last output digit,
51
* rounding the `5|6` to `6|` is straightforward. However,
52
* rounding `y.xxx99|6` should result in `y.xx100|`. Notice the
53
* effect of rounding percolates to higher digits.
54
* We accumulate the output digits in a string, then carry out
55
* the rounding in the string directly.
56
*/
57
std::ostream&
58
operator<<
(std::ostream& os,
const
int64x64_t
&
value
)
59
{
60
const
bool
negative
= (
value
< 0);
61
62
uint64_t hi;
63
int64x64_t
low
;
64
if
(
value
!=
int64x64_t
(std::numeric_limits<int64_t>::min(), 0))
65
{
66
const
int64x64_t
absVal
= (
negative
? -
value
:
value
);
67
hi =
absVal
.
GetHigh
();
68
low
=
int64x64_t
(0,
absVal
.GetLow());
69
}
70
else
71
{
72
hi =
static_cast<
uint64_t
>
(1) << 63;
73
}
74
75
// Save stream format flags
76
auto
precision
=
static_cast<
std::size_t
>
(os.precision());
77
std::ios_base::fmtflags
ff
= os.flags();
78
const
bool
floatfield
= os.flags() & std::ios_base::floatfield;
79
os << std::setw(1) << std::noshowpos;
80
81
os << std::right << (
negative
?
"-"
:
"+"
);
82
83
std::ostringstream
oss
;
84
oss
<< hi <<
"."
;
// collect the digits here so we can round properly
85
86
std::size_t
places
= 0;
// Number of decimal places printed so far
87
bool
more
=
true
;
// Should we print more digits?
88
89
NS_LOG_LOGIC
(std::endl
90
<< (
floatfield
?
" f"
:
" "
) <<
"["
<<
precision
<<
"] "
<< hi <<
". "
91
<<
HEXHILOW
(hi,
low
.GetLow()));
92
93
int64_t
digit
;
94
do
95
{
96
low
*= 10;
97
digit
=
low
.GetHigh();
98
NS_ASSERT_MSG
((0 <=
digit
) && (
digit
<= 9),
99
"digit "
<<
digit
<<
" out of range [0,9] "
100
<<
" streaming out "
<<
HEXHILOW
(
value
.GetHigh(),
value
.GetLow()));
101
low
-=
digit
;
102
103
oss
<< std::setw(1) <<
digit
;
104
105
++
places
;
106
if
(
floatfield
)
107
{
108
more
=
places
<
precision
;
109
}
110
else
// default
111
{
112
// Full resolution is 20 decimal digits
113
more
=
low
.GetLow() && (
places
< 20);
114
}
115
116
NS_LOG_LOGIC
((
more
?
"+"
:
" "
) << (
floatfield
?
"f"
:
" "
) <<
"["
<<
places
<<
"] "
117
<<
digit
<<
HEXHILOW
(
low
.GetHigh(),
low
.GetLow())
118
<< std::dec << std::setfill(
' '
) << std::left);
119
120
}
while
(
more
);
121
122
// Check if we need to round the last printed digit,
123
// based on the first unprinted digit
124
std::string
digits
=
oss
.str();
125
low
*= 10;
126
int64_t
nextDigit
=
low
.GetHigh();
127
if
((
nextDigit
> 5) || ((
nextDigit
== 5) && (
digit
% 2 == 1)))
128
{
129
// Walk backwards with the carry
130
bool
carry
=
true
;
131
for
(std::string::reverse_iterator
rit
=
digits
.rbegin();
rit
!=
digits
.rend(); ++
rit
)
132
{
133
if
(*
rit
==
'.'
)
// Skip over the decimal point
134
{
135
continue
;
136
}
137
138
++(*rit);
// Add the carry
139
if
(*
rit
<=
'9'
)
// Relies on character order...
140
{
141
carry
=
false
;
142
break
;
// Carry complete
143
}
144
else
145
{
146
*
rit
=
'0'
;
// Continue carry to next higher digit
147
}
148
}
149
if
(
carry
)
// If we still have a carry...
150
{
151
digits
.insert(
digits
.begin(),
'1'
);
152
}
153
}
154
os <<
digits
;
155
156
os.flags(
ff
);
// Restore stream flags
157
return
os;
158
}
159
160
/**
161
* @ingroup highprec
162
* Read the integer portion of a number from a string containing
163
* just the integral digits (no decimal point or fractional part).
164
*
165
* @param [in] str The string representation of the integral part
166
* of a number, with no fractional part or decimal point.
167
* @returns The integer.
168
*/
169
static
uint64_t
170
ReadHiDigits
(std::string str)
171
{
172
const
char
* buf = str.c_str();
173
uint64_t
retval
= 0;
174
while
(*buf != 0)
175
{
176
retval
*= 10;
177
retval
+= *buf -
'0'
;
178
buf++;
179
}
180
return
retval
;
181
}
182
183
/**
184
* @ingroup highprec
185
* Read the fractional part of a number from a string containing
186
* just the decimal digits of the fractional part (no integral part
187
* or decimal point).
188
*
189
* @param [in] str The string representation of the fractional part
190
* of a number, without integral part or decimal point.
191
* @returns The decimal portion of the input number.
192
*/
193
static
uint64_t
194
ReadLoDigits
(std::string str)
195
{
196
int64x64_t
low
;
197
const
int64x64_t
round
(0, 5);
// Round last place in division
198
199
for
(std::string::const_reverse_iterator
rit
= str.rbegin();
rit
!= str.rend(); ++
rit
)
200
{
201
int
digit
= *
rit
-
'0'
;
202
NS_ASSERT_MSG
((0 <=
digit
) && (
digit
<= 9),
203
"digit "
<<
digit
<<
" out of range [0,9]"
204
<<
" streaming in low digits \""
<< str <<
"\""
);
205
low
= (
low
+
digit
+
round
) / 10;
206
}
207
208
return
low
.GetLow();
209
}
210
211
std::istream&
212
operator>>
(std::istream& is,
int64x64_t
&
value
)
213
{
214
std::string str;
215
216
is >> str;
217
bool
negative
;
218
// skip heading spaces
219
std::string::size_type
cur
;
220
cur
= str.find_first_not_of(
' '
);
221
std::string::size_type next;
222
// first, remove the sign.
223
next = str.find(
'-'
,
cur
);
224
if
(next != std::string::npos)
225
{
226
negative
=
true
;
227
next++;
228
}
229
else
230
{
231
next = str.find(
'+'
,
cur
);
232
if
(next != std::string::npos)
233
{
234
next++;
235
}
236
else
237
{
238
next =
cur
;
239
}
240
negative
=
false
;
241
}
242
cur
= next;
243
int64_t hi;
244
uint64_t lo;
245
next = str.find(
'.'
,
cur
);
246
if
(next != std::string::npos)
247
{
248
hi =
ReadHiDigits
(str.substr(
cur
, next -
cur
));
249
lo =
ReadLoDigits
(str.substr(next + 1, str.size() - (next + 1)));
250
}
251
else
if
(
cur
!= std::string::npos)
252
{
253
hi =
ReadHiDigits
(str.substr(
cur
, str.size() -
cur
));
254
lo = 0;
255
}
256
else
257
{
258
hi = 0;
259
lo = 0;
260
}
261
262
value
=
int64x64_t
(hi, lo);
263
value
=
negative
? -
value
:
value
;
264
265
return
is;
266
}
267
268
}
// namespace ns3
assert.h
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
ns3::int64x64_t
High precision numerical type, implementing Q64.64 fixed precision.
Definition
int64x64-128.h:46
ns3::int64x64_t::GetHigh
int64_t GetHigh() const
Get the integer portion.
Definition
int64x64-128.h:235
NS_ASSERT_MSG
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition
assert.h:75
ns3::ReadHiDigits
static uint64_t ReadHiDigits(std::string str)
Read the integer portion of a number from a string containing just the integral digits (no decimal po...
Definition
int64x64.cc:170
HEXHILOW
#define HEXHILOW(hi, lo)
Print the high and low words of an int64x64 in hex, for debugging.
Definition
int64x64.cc:40
ns3::ReadLoDigits
static uint64_t ReadLoDigits(std::string str)
Read the fractional part of a number from a string containing just the decimal digits of the fraction...
Definition
int64x64.cc:194
NS_LOG_COMPONENT_DEFINE_MASK
#define NS_LOG_COMPONENT_DEFINE_MASK(name, mask)
Define a logging component with a mask.
Definition
log.h:202
NS_LOG_LOGIC
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition
log.h:271
ns3::Create
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition
ptr.h:436
int64x64.h
Declaration of the ns3::int64x64_t type and associated operators.
log.h
Debug message logging.
ns3
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ns3::operator<<
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition
angles.cc:148
ns3::value
static unsigned int value(char c)
Definition
qkd-encryptor.cc:267
ns3::operator>>
std::istream & operator>>(std::istream &is, Angles &a)
Definition
angles.cc:172
ns3::LOG_PREFIX_TIME
@ LOG_PREFIX_TIME
Prefix all trace prints with simulation time.
Definition
log.h:108
src
core
model
int64x64.cc
Generated on Mon Dec 15 2025 15:21:50 for ns-3 by
1.9.8