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
40 NS_LOG_COMPONENT_DEFINE ("int64x64");
41 
55 std::ostream &operator << (std::ostream &os, const int64x64_t &value)
56 {
57  const bool negative = (value < 0);
58  const int64x64_t absVal = (negative ? -value : value);
59 
60  int64_t hi = absVal.GetHigh ();
61 
62  // Save stream format flags
63  const std::streamsize precision = os.precision ();
64  std::ios_base::fmtflags ff = os.flags ();
65  const bool floatfield = os.flags () & std::ios_base::floatfield;
66  os << std::setw (1) << std::noshowpos;
67 
68  os << std::right << (negative ? "-" : "+");
69 
70  std::ostringstream oss;
71  oss << hi << "."; // collect the digits here so we can round properly
72 
73 
74  int64x64_t low(0, absVal.GetLow ());
75  int places = 0; // Number of decimal places printed so far
76  bool more = true; // Should we print more digits?
77 
78 #define HEXHILOW(hi, lo) \
79  std::hex << std::setfill ('0') << std::right << " (0x" \
80  << std::setw (16) << hi << " " \
81  << std::setw (16) << lo \
82  << std::dec << std::setfill (' ') << std::left << ")"
83 
84 
85  NS_LOG_LOGIC (std::endl
86  << (floatfield ? " f" : " ")
87  << "[" << precision << "] " << hi << ". "
88  << HEXHILOW (hi, low.GetLow ())
89  );
90 
91  int64_t digit;
92  do
93  {
94  low *= 10;
95  digit = low.GetHigh ();
96  NS_ASSERT_MSG ( (0 <= digit) && (digit <= 9),
97  "digit " << digit << " out of range [0,9] "
98  << " streaming out "
99  << HEXHILOW (value.GetHigh (), value.GetLow ()) );
100  low -= digit;
101 
102  oss << std::setw (1) << digit;
103 
104  ++places;
105  if (floatfield)
106  {
107  more = places < precision;
108  }
109  else // default
110  {
111  // Full resolution is 20 decimal digits
112  more = low.GetLow () && (places < 20);
113  }
114 
115  NS_LOG_LOGIC ((more ? "+" : " ")
116  << (floatfield ? "f" : " ")
117  << "[" << places << "] " << digit
118  << HEXHILOW (low.GetHigh (), low.GetLow ())
119  << std::dec << std::setfill (' ' ) << std::left);
120 
121  } while (more);
122 
123  // Check if we need to round the last printed digit,
124  // based on the first unprinted digit
125  std::string digits = oss.str ();
126  low *= 10;
127  int64_t nextDigit = low.GetHigh ();
128  if ( (nextDigit > 5) || ((nextDigit == 5) && (digit % 2 == 1)) )
129  {
130  // Walk backwards with the carry
131  bool carry = true;
132  for (std::string::reverse_iterator rit = digits.rbegin ();
133  rit != digits.rend ();
134  ++rit)
135  {
136  if (*rit == '.') // Skip over the decimal point
137  {
138  continue ;
139  }
140 
141  ++(*rit); // Add the carry
142  if (*rit <= '9') // Relies on character order...
143  {
144  carry = false;
145  break ; // Carry complete
146  }
147  else
148  {
149  *rit = '0'; // Continue carry to next higher digit
150  }
151  }
152  if (carry) // If we still have a carry...
153  {
154  digits.insert (digits.begin (), '1');
155  }
156  }
157  os << digits;
158 
159  os.flags (ff); // Restore stream flags
160  return os;
161 }
162 
172 static uint64_t ReadHiDigits (std::string str)
173 {
174  const char *buf = str.c_str ();
175  uint64_t retval = 0;
176  while (*buf != 0)
177  {
178  retval *= 10;
179  retval += *buf - '0';
180  buf++;
181  }
182  return retval;
183 }
184 
195 static uint64_t ReadLoDigits (std::string str)
196 {
197  int64x64_t low;
198  const int64x64_t round (0, 5); // Round last place in division
199 
200  for (std::string::const_reverse_iterator rit = str.rbegin ();
201  rit != str.rend ();
202  ++rit)
203  {
204  int digit = *rit - '0';
205  NS_ASSERT_MSG ( (0 <= digit) && (digit <= 9),
206  "digit " << digit << " out of range [0,9]"
207  << " streaming in low digits \"" << str << "\"");
208  low = (low + digit + round) / 10;
209  }
210 
211  return low.GetLow ();
212 }
213 
214 std::istream &operator >> (std::istream &is, int64x64_t &value)
215 {
216  std::string str;
217 
218  is >> str;
219  bool negative;
220  // skip heading spaces
221  std::string::size_type cur;
222  cur = str.find_first_not_of (" ");
223  std::string::size_type next;
224  // first, remove the sign.
225  next = str.find ("-", cur);
226  if (next != std::string::npos)
227  {
228  negative = true;
229  next++;
230  }
231  else
232  {
233  next = str.find ("+", cur);
234  if (next != std::string::npos)
235  {
236  next++;
237  }
238  else
239  {
240  next = cur;
241  }
242  negative = false;
243  }
244  cur = next;
245  int64_t hi;
246  uint64_t lo;
247  next = str.find (".", cur);
248  if (next != std::string::npos)
249  {
250  hi = ReadHiDigits (str.substr (cur, next-cur));
251  lo = ReadLoDigits (str.substr (next+1, str.size ()-(next+1)));
252  }
253  else if (cur != std::string::npos)
254  {
255  hi = ReadHiDigits (str.substr (cur, str.size ()-cur));
256  lo = 0;
257  }
258  else
259  {
260  hi = 0;
261  lo = 0;
262  }
263 
264  value = int64x64_t (hi, lo);
265  value = negative ? -value : value;
266 
267  return is;
268 }
269 
270 } // namespace ns3
std::istream & operator>>(std::istream &is, Angles &a)
initialize a struct Angles from input
Definition: angles.cc:48
uint64_t GetLow(void) const
Get the fractional portion of this value, unscaled.
Definition: int64x64-128.h:229
High precision numerical type, implementing Q64.64 fixed precision.
Definition: int64x64-128.h:45
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
#define HEXHILOW(hi, lo)
Definition of assertion macros NS_ASSERT() and NS_ASSERT_MSG().
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
Definition: angles.cc:42
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:172
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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:195
#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:90
int64_t GetHigh(void) const
Get the integer portion.
Definition: int64x64-128.h:219
Debug message logging.
Declaration of the ns3::int64x64_t type and associated operators.