A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
int64x64-double.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#ifndef INT64X64_DOUBLE_H
8#define INT64X64_DOUBLE_H
9
10#include "ns3/core-config.h"
11
12#if defined(INT64X64_USE_DOUBLE) || defined(PYTHON_SCAN)
13/** Using the ns3::int64x64_t based on double values. */
14
15#include <cmath> // pow
16#include <stdint.h>
17#include <utility> // pair
18
19/**
20 * \file
21 * \ingroup highprec
22 * Declaration and implementation of the ns3::int64x64_t type
23 * using the double type.
24 */
25
26namespace ns3
27{
28
29/**
30 * \internal
31 * The implementation documented here uses native long double.
32 */
34{
35 /// Mask for fraction part
36 static const uint64_t HP_MASK_LO = 0xffffffffffffffffULL;
37
38 public:
39 /// Floating point value of HP_MASK_LO + 1
40 static constexpr long double HP_MAX_64 = (static_cast<uint64_t>(1) << 63) * 2.0L;
41
42 /**
43 * Type tag for the underlying implementation.
44 *
45 * A few testcases are are sensitive to implementation,
46 * specifically the double implementation. To handle this,
47 * we expose the underlying implementation type here.
48 */
50 {
51 int128_impl, //!< Native int128_t implementation.
52 cairo_impl, //!< cairo wideint implementation
53 ld_impl, //!< long double implementation
54 };
55
56 /// Type tag for this implementation.
57 static const enum impl_type implementation = ld_impl;
58
59 /// Default constructor
60 inline int64x64_t()
61 : _v(0)
62 {
63 }
64
65 /**
66 * \name Construct from a floating point value.
67 */
68 /**
69 * @{
70 * Constructor from a floating point.
71 *
72 * \param [in] value Floating value to represent.
73 */
74 inline int64x64_t(double value)
75 : _v(value)
76 {
77 }
78
79 inline int64x64_t(long double value)
80 : _v(value)
81 {
82 }
83
84 /**@}*/
85
86 /**
87 * \name Construct from an integral type.
88 */
89 /**@{*/
90 /**
91 * Construct from an integral type.
92 *
93 * \param [in] v Integer value to represent
94 */
95 inline int64x64_t(int v)
96 : _v(v)
97 {
98 }
99
100 inline int64x64_t(long int v)
101 : _v(v)
102 {
103 }
104
105 inline int64x64_t(long long int v)
106 : _v(static_cast<long double>(v))
107 {
108 }
109
110 inline int64x64_t(unsigned int v)
111 : _v(v)
112 {
113 }
114
115 inline int64x64_t(unsigned long int v)
116 : _v(v)
117 {
118 }
119
120 inline int64x64_t(unsigned long long int v)
121 : _v(static_cast<long double>(v))
122 {
123 }
124
125 /**@}*/
126 /**
127 * Construct from explicit high and low values.
128 *
129 * \param [in] hi Integer portion.
130 * \param [in] lo Fractional portion, already scaled to HP_MAX_64.
131 */
132 explicit inline int64x64_t(int64_t hi, uint64_t lo)
133 {
134 const bool negative = hi < 0;
135 const long double hild = static_cast<long double>(hi);
136 const long double fhi = negative ? -hild : hild;
137 const long double flo = lo / HP_MAX_64;
138 _v = negative ? -fhi : fhi;
139 _v += flo;
140 // _v = negative ? -_v : _v;
141 }
142
143 /**
144 * Copy constructor.
145 *
146 * \param [in] o Value to copy.
147 */
148 inline int64x64_t(const int64x64_t& o)
149 : _v(o._v)
150 {
151 }
152
153 /**
154 * Assignment.
155 *
156 * \param [in] o Value to assign to this int64x64_t.
157 * \returns a copy of \pname{o}
158 */
160 {
161 _v = o._v;
162 return *this;
163 }
164
165 /** Explicit bool conversion. */
166 inline explicit operator bool() const
167 {
168 return (_v != 0);
169 }
170
171 /**
172 * Get this value as a double.
173 *
174 * \return This value in floating form.
175 */
176 inline double GetDouble() const
177 {
178 return (double)_v;
179 }
180
181 private:
182 /**
183 * Get the high and low portions of this value.
184 *
185 * \return A pair of the high and low words
186 */
187 std::pair<int64_t, uint64_t> GetHighLow() const
188 {
189 const bool negative = _v < 0;
190 const long double v = negative ? -_v : _v;
191
192 long double fhi;
193 long double flo = std::modf(v, &fhi);
194 // Add 0.5 to round, which improves the last count
195 // This breaks these tests:
196 // TestSuite devices-mesh-dot11s-regression
197 // TestSuite devices-mesh-flame-regression
198 // TestSuite routing-aodv-regression
199 // TestSuite routing-olsr-regression
200 // Setting round = 0; breaks:
201 // TestSuite int64x64
202 const long double round = 0.5;
203 flo = flo * HP_MAX_64 + round;
204 int64_t hi = static_cast<int64_t>(fhi);
205 uint64_t lo = static_cast<uint64_t>(flo);
206 if (flo >= HP_MAX_64)
207 {
208 // conversion to uint64 rolled over
209 ++hi;
210 }
211 if (negative)
212 {
213 lo = ~lo;
214 hi = ~hi;
215 if (++lo == 0)
216 {
217 ++hi;
218 }
219 }
220 return std::make_pair(hi, lo);
221 }
222
223 public:
224 /**
225 * Get the integer portion.
226 *
227 * \return The integer portion of this value.
228 */
229 inline int64_t GetHigh() const
230 {
231 return GetHighLow().first;
232 }
233
234 /**
235 * Get the fractional portion of this value, unscaled.
236 *
237 * \return The fractional portion, unscaled, as an integer.
238 */
239 inline uint64_t GetLow() const
240 {
241 return GetHighLow().second;
242 }
243
244 /**
245 * Truncate to an integer.
246 * Truncation is always toward zero,
247 * \return The value truncated toward zero.
248 */
249 int64_t GetInt() const
250 {
251 int64_t retval = static_cast<int64_t>(_v);
252 return retval;
253 }
254
255 /**
256 * Round to the nearest int.
257 * Similar to std::round this rounds halfway cases away from zero,
258 * regardless of the current (floating) rounding mode.
259 * \return The value rounded to the nearest int.
260 */
261 int64_t Round() const
262 {
263 int64_t retval = std::round(_v);
264 return retval;
265 }
266
267 /**
268 * Multiply this value by a Q0.128 value, presumably representing an inverse,
269 * completing a division operation.
270 *
271 * \param [in] o The inverse operand.
272 *
273 * \note There is no difference between Q64.64 and Q0.128 in this implementation,
274 * so this function is a simple multiply.
275 */
276 inline void MulByInvert(const int64x64_t& o)
277 {
278 _v *= o._v;
279 }
280
281 /**
282 * Compute the inverse of an integer value.
283 *
284 * \param [in] v The value to compute the inverse of.
285 * \return The inverse.
286 */
287 static inline int64x64_t Invert(uint64_t v)
288 {
289 int64x64_t tmp((long double)1 / v);
290 return tmp;
291 }
292
293 private:
294 /**
295 * \name Arithmetic Operators
296 * Arithmetic operators for int64x64_t.
297 */
298 /**
299 * @{
300 * Arithmetic operator.
301 * \param [in] lhs Left hand argument
302 * \param [in] rhs Right hand argument
303 * \return The result of the operator.
304 */
305
306 friend inline bool operator==(const int64x64_t& lhs, const int64x64_t& rhs)
307 {
308 return lhs._v == rhs._v;
309 }
310
311 friend inline bool operator<(const int64x64_t& lhs, const int64x64_t& rhs)
312 {
313 return lhs._v < rhs._v;
314 }
315
316 friend inline bool operator>(const int64x64_t& lhs, const int64x64_t& rhs)
317 {
318 return lhs._v > rhs._v;
319 }
320
321 friend inline int64x64_t& operator+=(int64x64_t& lhs, const int64x64_t& rhs)
322 {
323 lhs._v += rhs._v;
324 return lhs;
325 }
326
327 friend inline int64x64_t& operator-=(int64x64_t& lhs, const int64x64_t& rhs)
328 {
329 lhs._v -= rhs._v;
330 return lhs;
331 }
332
333 friend inline int64x64_t& operator*=(int64x64_t& lhs, const int64x64_t& rhs)
334 {
335 lhs._v *= rhs._v;
336 return lhs;
337 }
338
339 friend inline int64x64_t& operator/=(int64x64_t& lhs, const int64x64_t& rhs)
340 {
341 lhs._v /= rhs._v;
342 return lhs;
343 }
344
345 /**@}*/
346
347 /**
348 * \name Unary Operators
349 * Unary operators for int64x64_t.
350 */
351 /**
352 * @{
353 * Unary operator.
354 * \param [in] lhs Left hand argument
355 * \return The result of the operator.
356 */
357 friend inline int64x64_t operator+(const int64x64_t& lhs)
358 {
359 return lhs;
360 }
361
362 friend inline int64x64_t operator-(const int64x64_t& lhs)
363 {
364 return int64x64_t(-lhs._v);
365 }
366
367 friend inline int64x64_t operator!(const int64x64_t& lhs)
368 {
369 return int64x64_t(!lhs._v);
370 }
371
372 /**@}*/
373
374 long double _v; //!< The Q64.64 value.
375
376}; // class int64x64_t
377
378} // namespace ns3
379
380#endif /* defined(INT64X64_USE_DOUBLE) || defined(PYTHON_SCAN) */
381#endif /* INT64X64_DOUBLE_H */
High precision numerical type, implementing Q64.64 fixed precision.
int64_t GetHigh() const
Get the integer portion.
int64x64_t(unsigned long int v)
Construct from an integral type.
int64x64_t(int v)
Construct from an integral type.
friend bool operator==(const int64x64_t &lhs, const int64x64_t &rhs)
Arithmetic operator.
static const uint64_t HP_MASK_LO
Mask for fraction part.
impl_type
Type tag for the underlying implementation.
@ int128_impl
Native int128_t implementation.
@ ld_impl
long double implementation.
@ cairo_impl
Cairo wideint implementation.
static int64x64_t Invert(uint64_t v)
Compute the inverse of an integer value.
friend int64x64_t & operator-=(int64x64_t &lhs, const int64x64_t &rhs)
Arithmetic operator.
friend int64x64_t operator+(const int64x64_t &lhs)
Unary operator.
static constexpr long double HP_MAX_64
Floating point value of HP_MASK_LO + 1.
int64x64_t(long double value)
Constructor from a floating point.
int64x64_t(unsigned int v)
Construct from an integral type.
int64_t Round() const
Round to the nearest int.
void MulByInvert(const int64x64_t &o)
Multiply this value by a Q0.128 value, presumably representing an inverse, completing a division oper...
friend bool operator<(const int64x64_t &lhs, const int64x64_t &rhs)
Arithmetic operator.
static enum impl_type implementation
Type tag for this implementation.
friend int64x64_t operator!(const int64x64_t &lhs)
Unary operator.
int128_t _v
The Q64.64 value.
int64x64_t(unsigned long long int v)
Construct from an integral type.
friend int64x64_t & operator*=(int64x64_t &lhs, const int64x64_t &rhs)
Arithmetic operator.
int64x64_t(long long int v)
Construct from an integral type.
int64x64_t(int64_t hi, uint64_t lo)
Construct from explicit high and low values.
double GetDouble() const
Get this value as a double.
friend int64x64_t & operator+=(int64x64_t &lhs, const int64x64_t &rhs)
Arithmetic operator.
int64_t GetInt() const
Truncate to an integer.
int64x64_t & operator=(const int64x64_t &o)
Assignment.
friend bool operator>(const int64x64_t &lhs, const int64x64_t &rhs)
Arithmetic operator.
long double _v
The Q64.64 value.
std::pair< int64_t, uint64_t > GetHighLow() const
Get the high and low portions of this value.
uint64_t GetLow() const
Get the fractional portion of this value, unscaled.
int64x64_t(double value)
Constructor from a floating point.
friend int64x64_t operator-(const int64x64_t &lhs)
Unary operator.
int64x64_t(const int64x64_t &o)
Copy constructor.
friend int64x64_t & operator/=(int64x64_t &lhs, const int64x64_t &rhs)
Arithmetic operator.
int64x64_t()
Default constructor.
int64x64_t(long int v)
Construct from an integral type.
Every class exported by the ns3 library is enclosed in the ns3 namespace.