A Discrete-Event Network Simulator
API
int64x64.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2010 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 */
19
20#include "int64x64.h"
21#include <stdint.h>
22#include <iostream>
23#include <iomanip> // showpos
24#include <sstream>
25#include "assert.h"
26#include "log.h"
27
35namespace ns3 {
36
37// Note: Logging in this file is largely avoided due to the
38// number of calls that are made to these functions and the possibility
39// of causing recursions leading to stack overflow
41
49#define HEXHILOW(hi, lo) \
50 std::hex << std::setfill ('0') << std::right << " (0x" \
51 << std::setw (16) << hi << " " \
52 << std::setw (16) << lo \
53 << std::dec << std::setfill (' ') << std::left << ")"
54
55
69std::ostream &operator << (std::ostream &os, const int64x64_t &value)
70{
71 const bool negative = (value < 0);
72 const int64x64_t absVal = (negative ? -value : value);
73
74 int64_t hi = absVal.GetHigh ();
75
76 // Save stream format flags
77 std::size_t precision = static_cast<std::size_t> (os.precision ());
78 std::ios_base::fmtflags ff = os.flags ();
79 const bool floatfield = os.flags () & std::ios_base::floatfield;
80 os << std::setw (1) << std::noshowpos;
81
82 os << std::right << (negative ? "-" : "+");
83
84 std::ostringstream oss;
85 oss << hi << "."; // collect the digits here so we can round properly
86
87
88 int64x64_t low (0, absVal.GetLow ());
89 std::size_t places = 0; // Number of decimal places printed so far
90 bool more = true; // Should we print more digits?
91
92 NS_LOG_LOGIC (std::endl
93 << (floatfield ? " f" : " ")
94 << "[" << precision << "] " << hi << ". "
95 << HEXHILOW (hi, low.GetLow ())
96 );
97
98 int64_t digit;
99 do
100 {
101 low *= 10;
102 digit = low.GetHigh ();
103 NS_ASSERT_MSG ( (0 <= digit) && (digit <= 9),
104 "digit " << digit << " out of range [0,9] " <<
105 " streaming out " <<
106 HEXHILOW (value.GetHigh (), value.GetLow ()) );
107 low -= digit;
108
109 oss << std::setw (1) << digit;
110
111 ++places;
112 if (floatfield)
113 {
114 more = places < precision;
115 }
116 else // default
117 {
118 // Full resolution is 20 decimal digits
119 more = low.GetLow () && (places < 20);
120 }
121
122 NS_LOG_LOGIC ((more ? "+" : " ")
123 << (floatfield ? "f" : " ")
124 << "[" << places << "] " << digit
125 << HEXHILOW (low.GetHigh (), low.GetLow ())
126 << std::dec << std::setfill (' ' ) << std::left);
127
128 }
129 while (more);
130
131 // Check if we need to round the last printed digit,
132 // based on the first unprinted digit
133 std::string digits = oss.str ();
134 low *= 10;
135 int64_t nextDigit = low.GetHigh ();
136 if ( (nextDigit > 5) || ((nextDigit == 5) && (digit % 2 == 1)) )
137 {
138 // Walk backwards with the carry
139 bool carry = true;
140 for (std::string::reverse_iterator rit = digits.rbegin ();
141 rit != digits.rend ();
142 ++rit)
143 {
144 if (*rit == '.') // Skip over the decimal point
145 {
146 continue;
147 }
148
149 ++(*rit); // Add the carry
150 if (*rit <= '9') // Relies on character order...
151 {
152 carry = false;
153 break; // Carry complete
154 }
155 else
156 {
157 *rit = '0'; // Continue carry to next higher digit
158 }
159 }
160 if (carry) // If we still have a carry...
161 {
162 digits.insert (digits.begin (), '1');
163 }
164 }
165 os << digits;
166
167 os.flags (ff); // Restore stream flags
168 return os;
169}
170
180static uint64_t ReadHiDigits (std::string str)
181{
182 const char *buf = str.c_str ();
183 uint64_t retval = 0;
184 while (*buf != 0)
185 {
186 retval *= 10;
187 retval += *buf - '0';
188 buf++;
189 }
190 return retval;
191}
192
203static uint64_t ReadLoDigits (std::string str)
204{
205 int64x64_t low;
206 const int64x64_t round (0, 5); // Round last place in division
207
208 for (std::string::const_reverse_iterator rit = str.rbegin ();
209 rit != str.rend ();
210 ++rit)
211 {
212 int digit = *rit - '0';
213 NS_ASSERT_MSG ( (0 <= digit) && (digit <= 9),
214 "digit " << digit << " out of range [0,9]" <<
215 " streaming in low digits \"" << str << "\"");
216 low = (low + digit + round) / 10;
217 }
218
219 return low.GetLow ();
220}
221
222std::istream &operator >> (std::istream &is, int64x64_t &value)
223{
224 std::string str;
225
226 is >> str;
227 bool negative;
228 // skip heading spaces
229 std::string::size_type cur;
230 cur = str.find_first_not_of (" ");
231 std::string::size_type next;
232 // first, remove the sign.
233 next = str.find ("-", cur);
234 if (next != std::string::npos)
235 {
236 negative = true;
237 next++;
238 }
239 else
240 {
241 next = str.find ("+", cur);
242 if (next != std::string::npos)
243 {
244 next++;
245 }
246 else
247 {
248 next = cur;
249 }
250 negative = false;
251 }
252 cur = next;
253 int64_t hi;
254 uint64_t lo;
255 next = str.find (".", cur);
256 if (next != std::string::npos)
257 {
258 hi = ReadHiDigits (str.substr (cur, next - cur));
259 lo = ReadLoDigits (str.substr (next + 1, str.size () - (next + 1)));
260 }
261 else if (cur != std::string::npos)
262 {
263 hi = ReadHiDigits (str.substr (cur, str.size () - cur));
264 lo = 0;
265 }
266 else
267 {
268 hi = 0;
269 lo = 0;
270 }
271
272 value = int64x64_t (hi, lo);
273 value = negative ? -value : value;
274
275 return is;
276}
277
278} // namespace ns3
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
High precision numerical type, implementing Q64.64 fixed precision.
int64_t GetHigh(void) const
Get the integer portion.
uint64_t GetLow(void) const
Get the fractional portion of this value, unscaled.
#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:88
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:180
#define HEXHILOW(hi, lo)
Print the high and low words of an int64x64 in hex, for debugging.
Definition: int64x64.cc:49
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:203
#define NS_LOG_COMPONENT_DEFINE_MASK(name, mask)
Define a logging component with a mask.
Definition: log.h:216
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
Declaration of the ns3::int64x64_t type and associated operators.
Debug message logging.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:139
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:162
@ LOG_PREFIX_TIME
Prefix all trace prints with simulation time.
Definition: log.h:119