A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
int64x64.cc
Go to the documentation of this file.
1 #include "int64x64.h"
2 #include <stdint.h>
3 #include <iostream>
4 #include <iomanip> // showpos
5 #include <sstream>
6 #include "assert.h"
7 #include "log.h"
8 
9 // Note: Logging in this file is largely avoided due to the
10 // number of calls that are made to these functions and the possibility
11 // of causing recursions leading to stack overflow
12 
13 NS_LOG_COMPONENT_DEFINE ("int64x64");
14 
15 namespace ns3 {
16 
30 std::ostream &operator << (std::ostream &os, const int64x64_t &value)
31 {
32  const bool negative = (value < 0);
33  const int64x64_t absVal = (negative ? -value : value);
34 
35  int64_t hi = absVal.GetHigh ();
36 
37  // Save stream format flags
38  const std::streamsize precision = os.precision ();
39  std::ios_base::fmtflags ff = os.flags ();
40  const bool floatfield = os.flags () & std::ios_base::floatfield;
41  os << std::setw (1) << std::noshowpos;
42 
43  os << std::right << (negative ? "-" : "+");
44 
45  std::ostringstream oss;
46  oss << hi << "."; // collect the digits here so we can round properly
47 
48 
49  int64x64_t low(0, absVal.GetLow ());
50  int places = 0; // Number of decimal places printed so far
51  bool more = true; // Should we print more digits?
52 
53 #define HEXHILOW(hi, lo) \
54  std::hex << std::setfill ('0') << std::right << " (0x" \
55  << std::setw (16) << hi << " " \
56  << std::setw (16) << lo \
57  << std::dec << std::setfill (' ') << std::left << ")"
58 
59 
60  NS_LOG_LOGIC (std::endl
61  << (floatfield ? " f" : " ")
62  << "[" << precision << "] " << hi << ". "
63  << HEXHILOW (hi, low.GetLow ())
64  );
65 
66  int64_t digit;
67  do
68  {
69  low *= 10;
70  digit = low.GetHigh ();
71  NS_ASSERT_MSG ( (0 <= digit) && (digit <= 9),
72  "digit " << digit << " out of range [0,9] "
73  << " streaming out "
74  << HEXHILOW (value.GetHigh (), value.GetLow ()) );
75  low -= digit;
76 
77  oss << std::setw (1) << digit;
78 
79  ++places;
80  if (floatfield)
81  {
82  more = places < precision;
83  }
84  else // default
85  {
86  // Full resolution is 20 decimal digits
87  more = low.GetLow () && (places < 20);
88  }
89 
90  NS_LOG_LOGIC ((more ? "+" : " ")
91  << (floatfield ? "f" : " ")
92  << "[" << places << "] " << digit
93  << HEXHILOW (low.GetHigh (), low.GetLow ())
94  << std::dec << std::setfill (' ' ) << std::left);
95 
96  } while (more);
97 
98  // Check if we need to round the last printed digit,
99  // based on the first unprinted digit
100  std::string digits = oss.str ();
101  low *= 10;
102  int64_t nextDigit = low.GetHigh ();
103  if ( (nextDigit > 5) || ((nextDigit == 5) && (digit % 2 == 1)) )
104  {
105  // Walk backwards with the carry
106  bool carry = true;
107  for (std::string::reverse_iterator rit = digits.rbegin ();
108  rit != digits.rend ();
109  ++rit)
110  {
111  if (*rit == '.') // Skip over the decimal point
112  {
113  continue ;
114  }
115 
116  ++(*rit); // Add the carry
117  if (*rit <= '9') // Relies on character order...
118  {
119  carry = false;
120  break ; // Carry complete
121  }
122  else
123  {
124  *rit = '0'; // Continue carry to next higher digit
125  }
126  }
127  if (carry) // If we still have a carry...
128  {
129  digits.insert (digits.begin (), '1');
130  }
131  }
132  os << digits;
133 
134  os.flags (ff); // Restore stream flags
135  return os;
136 }
137 
138 static uint64_t ReadHiDigits (std::string str)
139 {
140  const char *buf = str.c_str ();
141  uint64_t retval = 0;
142  while (*buf != 0)
143  {
144  retval *= 10;
145  retval += *buf - '0';
146  buf++;
147  }
148  return retval;
149 }
150 
151 static uint64_t ReadLoDigits (std::string str)
152 {
153  int64x64_t low;
154  const int64x64_t round (0, 5); // Round last place in division
155 
156  for (std::string::const_reverse_iterator rit = str.rbegin ();
157  rit != str.rend ();
158  ++rit)
159  {
160  int digit = *rit - '0';
161  NS_ASSERT_MSG ( (0 <= digit) && (digit <= 9),
162  "digit " << digit << " out of range [0,9]"
163  << " streaming in low digits \"" << str << "\"");
164  low = (low + digit + round) / 10;
165  }
166 
167  return low.GetLow ();
168 }
169 
170 std::istream &operator >> (std::istream &is, int64x64_t &value)
171 {
172  std::string str;
173 
174  is >> str;
175  bool negative;
176  // skip heading spaces
177  std::string::size_type cur;
178  cur = str.find_first_not_of (" ");
179  std::string::size_type next;
180  // first, remove the sign.
181  next = str.find ("-", cur);
182  if (next != std::string::npos)
183  {
184  negative = true;
185  next++;
186  }
187  else
188  {
189  next = str.find ("+", cur);
190  if (next != std::string::npos)
191  {
192  next++;
193  }
194  else
195  {
196  next = cur;
197  }
198  negative = false;
199  }
200  cur = next;
201  int64_t hi;
202  uint64_t lo;
203  next = str.find (".", cur);
204  if (next != std::string::npos)
205  {
206  hi = ReadHiDigits (str.substr (cur, next-cur));
207  lo = ReadLoDigits (str.substr (next+1, str.size ()-(next+1)));
208  }
209  else if (cur != std::string::npos)
210  {
211  hi = ReadHiDigits (str.substr (cur, str.size ()-cur));
212  lo = 0;
213  }
214  else
215  {
216  hi = 0;
217  lo = 0;
218  }
219 
220  value = int64x64_t (hi, lo);
221  value = negative ? -value : value;
222 
223  return is;
224 }
225 
226 } // namespace ns3
std::istream & operator>>(std::istream &is, Angles &a)
initialize a struct Angles from input
Definition: angles.cc:49
uint64_t GetLow(void) const
Get the fractional portion of this value, unscaled.
Definition: int64x64-128.h:201
High precision numerical type, implementing Q64.64 fixed precision.
Definition: int64x64-128.h:20
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
#define HEXHILOW(hi, lo)
static uint64_t ReadLoDigits(std::string str)
Definition: int64x64.cc:151
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:233
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
Definition: angles.cc:43
#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:84
int64_t GetHigh(void) const
Get the integer portion.
Definition: int64x64-128.h:191
static uint64_t ReadHiDigits(std::string str)
Definition: int64x64.cc:138