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 
28 
29 namespace ns3 {
30 
31 // Note: Logging in this file is largely avoided due to the
32 // number of calls that are made to these functions and the possibility
33 // of causing recursions leading to stack overflow
34 NS_LOG_COMPONENT_DEFINE ("int64x64");
35 
49 std::ostream &operator << (std::ostream &os, const int64x64_t &value)
50 {
51  const bool negative = (value < 0);
52  const int64x64_t absVal = (negative ? -value : value);
53 
54  int64_t hi = absVal.GetHigh ();
55 
56  // Save stream format flags
57  const std::streamsize precision = os.precision ();
58  std::ios_base::fmtflags ff = os.flags ();
59  const bool floatfield = os.flags () & std::ios_base::floatfield;
60  os << std::setw (1) << std::noshowpos;
61 
62  os << std::right << (negative ? "-" : "+");
63 
64  std::ostringstream oss;
65  oss << hi << "."; // collect the digits here so we can round properly
66 
67 
68  int64x64_t low(0, absVal.GetLow ());
69  int places = 0; // Number of decimal places printed so far
70  bool more = true; // Should we print more digits?
71 
72 #define HEXHILOW(hi, lo) \
73  std::hex << std::setfill ('0') << std::right << " (0x" \
74  << std::setw (16) << hi << " " \
75  << std::setw (16) << lo \
76  << std::dec << std::setfill (' ') << std::left << ")"
77 
78 
79  NS_LOG_LOGIC (std::endl
80  << (floatfield ? " f" : " ")
81  << "[" << precision << "] " << hi << ". "
82  << HEXHILOW (hi, low.GetLow ())
83  );
84 
85  int64_t digit;
86  do
87  {
88  low *= 10;
89  digit = low.GetHigh ();
90  NS_ASSERT_MSG ( (0 <= digit) && (digit <= 9),
91  "digit " << digit << " out of range [0,9] "
92  << " streaming out "
93  << HEXHILOW (value.GetHigh (), value.GetLow ()) );
94  low -= digit;
95 
96  oss << std::setw (1) << digit;
97 
98  ++places;
99  if (floatfield)
100  {
101  more = places < precision;
102  }
103  else // default
104  {
105  // Full resolution is 20 decimal digits
106  more = low.GetLow () && (places < 20);
107  }
108 
109  NS_LOG_LOGIC ((more ? "+" : " ")
110  << (floatfield ? "f" : " ")
111  << "[" << places << "] " << digit
112  << HEXHILOW (low.GetHigh (), low.GetLow ())
113  << std::dec << std::setfill (' ' ) << std::left);
114 
115  } while (more);
116 
117  // Check if we need to round the last printed digit,
118  // based on the first unprinted digit
119  std::string digits = oss.str ();
120  low *= 10;
121  int64_t nextDigit = low.GetHigh ();
122  if ( (nextDigit > 5) || ((nextDigit == 5) && (digit % 2 == 1)) )
123  {
124  // Walk backwards with the carry
125  bool carry = true;
126  for (std::string::reverse_iterator rit = digits.rbegin ();
127  rit != digits.rend ();
128  ++rit)
129  {
130  if (*rit == '.') // Skip over the decimal point
131  {
132  continue ;
133  }
134 
135  ++(*rit); // Add the carry
136  if (*rit <= '9') // Relies on character order...
137  {
138  carry = false;
139  break ; // Carry complete
140  }
141  else
142  {
143  *rit = '0'; // Continue carry to next higher digit
144  }
145  }
146  if (carry) // If we still have a carry...
147  {
148  digits.insert (digits.begin (), '1');
149  }
150  }
151  os << digits;
152 
153  os.flags (ff); // Restore stream flags
154  return os;
155 }
156 
166 static uint64_t ReadHiDigits (std::string str)
167 {
168  const char *buf = str.c_str ();
169  uint64_t retval = 0;
170  while (*buf != 0)
171  {
172  retval *= 10;
173  retval += *buf - '0';
174  buf++;
175  }
176  return retval;
177 }
178 
189 static uint64_t ReadLoDigits (std::string str)
190 {
191  int64x64_t low;
192  const int64x64_t round (0, 5); // Round last place in division
193 
194  for (std::string::const_reverse_iterator rit = str.rbegin ();
195  rit != str.rend ();
196  ++rit)
197  {
198  int digit = *rit - '0';
199  NS_ASSERT_MSG ( (0 <= digit) && (digit <= 9),
200  "digit " << digit << " out of range [0,9]"
201  << " streaming in low digits \"" << str << "\"");
202  low = (low + digit + round) / 10;
203  }
204 
205  return low.GetLow ();
206 }
207 
208 std::istream &operator >> (std::istream &is, int64x64_t &value)
209 {
210  std::string str;
211 
212  is >> str;
213  bool negative;
214  // skip heading spaces
215  std::string::size_type cur;
216  cur = str.find_first_not_of (" ");
217  std::string::size_type next;
218  // first, remove the sign.
219  next = str.find ("-", cur);
220  if (next != std::string::npos)
221  {
222  negative = true;
223  next++;
224  }
225  else
226  {
227  next = str.find ("+", cur);
228  if (next != std::string::npos)
229  {
230  next++;
231  }
232  else
233  {
234  next = cur;
235  }
236  negative = false;
237  }
238  cur = next;
239  int64_t hi;
240  uint64_t lo;
241  next = str.find (".", cur);
242  if (next != std::string::npos)
243  {
244  hi = ReadHiDigits (str.substr (cur, next-cur));
245  lo = ReadLoDigits (str.substr (next+1, str.size ()-(next+1)));
246  }
247  else if (cur != std::string::npos)
248  {
249  hi = ReadHiDigits (str.substr (cur, str.size ()-cur));
250  lo = 0;
251  }
252  else
253  {
254  hi = 0;
255  lo = 0;
256  }
257 
258  value = int64x64_t (hi, lo);
259  value = negative ? -value : value;
260 
261  return is;
262 }
263 
264 } // 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:223
High precision numerical type, implementing Q64.64 fixed precision.
Definition: int64x64-128.h:39
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
#define HEXHILOW(hi, lo)
#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:166
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:189
#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:213
Debug message logging.