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 
35 namespace 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 
69 std::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 
180 static 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 
203 static 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 
222 std::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.
Definition: int64x64-128.h:56
int64_t GetHigh(void) const
Get the integer portion.
Definition: int64x64-128.h:247
uint64_t GetLow(void) const
Get the fractional portion of this value, unscaled.
Definition: int64x64-128.h:257
#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.
@ LOG_PREFIX_TIME
Prefix all trace prints with simulation time.
Definition: log.h:119
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:162
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:139