A Discrete-Event Network Simulator
API
int64x64-test-suite.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 INRIA
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  */
18 
19 #include "ns3/int64x64.h"
20 #include "ns3/test.h"
21 #include "ns3/valgrind.h" // Bug 1882
22 
23 #include <cfloat> // FLT_RADIX,...
24 #include <cmath> // fabs, round
25 #include <iomanip>
26 #include <limits> // numeric_limits<>::epsilon ()
27 
28 #ifdef __WIN32__
32 #define RUNNING_WITH_LIMITED_PRECISION 1
33 #else
37 #define RUNNING_WITH_LIMITED_PRECISION RUNNING_ON_VALGRIND
38 #endif
39 
40 using namespace ns3;
41 
42 namespace ns3
43 {
44 
45 namespace int64x64
46 {
47 
48 namespace test
49 {
50 
67 class Printer
68 {
69  public:
76  Printer(const int64_t high, const uint64_t low)
77  : m_haveInt(false),
78  m_value(0),
79  m_high(high),
80  m_low(low)
81  {
82  }
83 
89  Printer(const int64x64_t value)
90  : m_haveInt(true),
91  m_value(value),
92  m_high(value.GetHigh()),
93  m_low(value.GetLow())
94  {
95  }
96 
97  private:
105  friend std::ostream& operator<<(std::ostream& os, const Printer& p);
106 
107  bool m_haveInt;
109  int64_t m_high;
110  uint64_t m_low;
111 };
112 
113 std::ostream&
114 operator<<(std::ostream& os, const Printer& p)
115 {
116  if (p.m_haveInt)
117  {
118  os << std::fixed << std::setprecision(22) << p.m_value;
119  }
120 
121  os << std::hex << std::setfill('0') << " (0x" << std::setw(16) << p.m_high << " 0x"
122  << std::setw(16) << p.m_low << ")" << std::dec << std::setfill(' ');
123  return os;
124 }
125 
132 {
133  public:
135  void DoRun() override;
141  void Check(const int64_t hi, const uint64_t lo);
142 };
143 
145  : TestCase("Manipulate the high and low part of every number")
146 {
147 }
148 
149 void
150 Int64x64HiLoTestCase::Check(const int64_t hi, const uint64_t lo)
151 {
152  uint64_t tolerance = 0;
154  {
155  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
156  tolerance = 1;
157  }
158 
159  int64x64_t value = int64x64_t(hi, lo);
160  uint64_t vLow = value.GetLow();
161  bool pass = ((value.GetHigh() == hi) && ((Max(vLow, lo) - Min(vLow, lo)) <= tolerance));
162 
163  std::cout << GetParent()->GetName() << " Check: " << (pass ? "pass " : "FAIL ")
164  << Printer(value) << " from" << Printer(hi, lo) << std::endl;
165 
166  NS_TEST_EXPECT_MSG_EQ(value.GetHigh(),
167  hi,
168  "High part does not match for hi:" << hi << " lo: " << lo);
169  NS_TEST_EXPECT_MSG_EQ_TOL((int64_t)vLow,
170  (int64_t)lo,
171  (int64_t)tolerance,
172  "Low part does not match for hi: " << hi << " lo: " << lo);
173 }
174 
175 void
177 {
178  std::cout << std::endl;
179  std::cout << GetParent()->GetName() << " Check: " << GetName() << std::endl;
180 
181  uint64_t low = 1;
183  {
184  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
185  low = static_cast<uint64_t>(HP_MAX_64 * std::numeric_limits<long double>::epsilon());
186  }
187 
188  Check(0, 0);
189  Check(0, low);
190  Check(0, 0xffffffffffffffffULL - low);
191 
192  Check(1, 0);
193  Check(1, low);
194  Check(1, 0xffffffffffffffffULL - low);
195 
196  Check(-1, 0);
197  Check(-1, low);
198  Check(-1, 0xffffffffffffffffULL - low);
199 }
200 
207 {
208  public:
210  void DoRun() override;
217  void Check(const int64x64_t value, const int64_t expectInt, const int64_t expectRnd);
218 };
219 
221  : TestCase("Check GetInt and Round")
222 {
223 }
224 
225 void
227  const int64_t expectInt,
228  const int64_t expectRnd)
229 {
230  int64_t vInt = value.GetInt();
231  int64_t vRnd = value.Round();
232 
233  bool pass = (vInt == expectInt) && (vRnd == expectRnd);
234  std::cout << GetParent()->GetName() << " Check: " << (pass ? "pass " : "FAIL ") << value
235  << " (int)-> " << std::setw(2) << vInt << " (expected: " << std::setw(2) << expectInt
236  << "), (rnd)-> " << std::setw(2) << vRnd << " (expected " << std::setw(2) << expectRnd
237  << ")" << std::endl;
238 
239  NS_TEST_EXPECT_MSG_EQ(vInt, expectInt, "Truncation to int failed");
240  NS_TEST_EXPECT_MSG_EQ(vRnd, expectRnd, "Rounding to int failed.");
241 }
242 
243 void
245 {
246  std::cout << std::endl;
247  std::cout << GetParent()->GetName() << " Check: " << GetName() << std::endl;
248 
249  // Trivial cases
250  Check(0, 0, 0);
251  Check(1, 1, 1);
252  Check(-1, -1, -1);
253 
254  // Both should move toward zero
255  Check(2.4, 2, 2);
256  Check(-2.4, -2, -2);
257 
258  // GetInt should move toward zero; Round should move away
259  Check(3.6, 3, 4);
260  Check(-3.6, -3, -4);
261  // Boundary case
262  Check(4.5, 4, 5);
263  Check(-4.5, -4, -5);
264 }
265 
272 {
273  public:
275  void DoRun() override;
283  void Check(const std::string& str,
284  const int64_t hi,
285  const uint64_t lo,
286  const int64_t tolerance = 0);
287 };
288 
290  : TestCase("Parse int64x64_t numbers as strings")
291 {
292 }
293 
294 void
295 Int64x64InputTestCase::Check(const std::string& str,
296  const int64_t hi,
297  const uint64_t lo,
298  const int64_t tolerance /* = 0 */)
299 
300 {
301  std::istringstream iss;
302  iss.str(str);
303  int64x64_t value;
304  iss >> value;
305 
306  std::string input = "\"" + str + "\"";
307  uint64_t vLow = value.GetLow();
308  bool pass = ((value.GetHigh() == hi) && (Max(vLow, lo) - Min(vLow, lo) <= tolerance));
309 
310  std::cout << GetParent()->GetName() << " Input: " << (pass ? "pass " : "FAIL ") << std::left
311  << std::setw(28) << input << std::right << Printer(value)
312  << " expected: " << Printer(hi, lo) << " +/- " << tolerance << std::endl;
313 
314  NS_TEST_EXPECT_MSG_EQ(value.GetHigh(),
315  hi,
316  "High parts do not match for input string \"" << str << "\"");
317  NS_TEST_EXPECT_MSG_EQ_TOL((int64_t)value.GetLow(),
318  (int64_t)lo,
319  tolerance,
320  "Low parts do not match for input string \"" << str << "\"");
321 }
322 
323 void
325 {
326  std::cout << std::endl;
327  std::cout << GetParent()->GetName() << " Input: " << GetName() << std::endl;
328 
329  int64_t tolerance = 0;
331  {
332  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
333  tolerance = 2;
334  }
335 
336  Check("1", 1, 0);
337  Check("+1", 1, 0);
338  Check("-1", -1, 0);
339  Check("1.0", 1, 0);
340  Check("+1.0", 1, 0);
341  Check("001.0", 1, 0);
342  Check("+001.0", 1, 0);
343  Check("020.0", 20, 0);
344  Check("+020.0", 20, 0);
345  Check("1.0000000", 1, 0);
346  Check("-1.0", -1, 0, tolerance);
347  Check("-1.0000", -1, 0, tolerance);
348  Check(" 1.000000000000000000054", 1, 1, tolerance);
349  Check("-1.000000000000000000054", (int64_t)-2, (uint64_t)-1, tolerance);
350 }
351 
360 {
361  public:
363  void DoRun() override;
369  void Check(const std::string& str, const int64_t tolerance = 0);
370 };
371 
373  : TestCase("Roundtrip int64x64_t numbers as strings")
374 {
375 }
376 
377 void
378 Int64x64InputOutputTestCase::Check(const std::string& str, const int64_t tolerance /* = 0 */)
379 {
380  std::stringstream iss(str);
381  int64x64_t expect;
382  iss >> expect;
383 
384  std::stringstream oss;
385  oss << std::scientific << std::setprecision(21) << expect;
386  int64x64_t value;
387  oss >> value;
388 
389  bool pass = Abs(value - expect) <= int64x64_t(0, tolerance + 1);
390 
391  std::string input = "\"" + str + "\"";
392  std::string output = "\"" + oss.str() + "\"";
393 
394  if (pass)
395  {
396  std::cout << GetParent()->GetName() << " InputOutput: " << (pass ? "pass " : "FAIL ")
397  << " in: " << std::left << std::setw(28) << input << " out: " << std::left
398  << std::setw(28) << output << std::right << std::endl;
399  }
400  else
401  {
402  std::cout << GetParent()->GetName() << " InputOutput: " << (pass ? "pass " : "FAIL ")
403  << " in: " << std::left << std::setw(28) << input << std::right
404  << Printer(expect) << std::endl;
405  std::cout << GetParent()->GetName() << std::setw(19) << " "
406  << " out: " << std::left << std::setw(28) << output << std::right
407  << Printer(value) << std::endl;
408  }
409 
411  expect,
412  int64x64_t(0, tolerance),
413  "Converted string does not match expected string");
414 }
415 
416 void
418 {
419  std::cout << std::endl;
420  std::cout << GetParent()->GetName() << " InputOutput: " << GetName() << std::endl;
421 
422  int64_t tolerance = 0;
424  {
425  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
426  tolerance = 1;
427  }
428 
429  Check("+1.000000000000000000000");
430  Check("+20.000000000000000000000");
431  Check("+0.000000000000000000000", tolerance);
432  Check("-1.000000000000000000000", tolerance);
433  Check("+1.084467440737095516158", tolerance);
434  Check("-2.084467440737095516158", tolerance);
435  Check("+3.184467440737095516179", tolerance);
436  Check("-4.184467440737095516179", tolerance);
437 }
438 
445 {
446  public:
448  void DoRun() override;
456  void Check(const int test,
457  const int64x64_t value,
458  const int64x64_t expect,
459  const int64x64_t tolerance = int64x64_t(0, 0));
460 };
461 
463  : TestCase("Basic arithmetic operations")
464 {
465 }
466 
467 void
469  const int64x64_t value,
470  const int64x64_t expect,
471  const int64x64_t tolerance)
472 {
473  bool pass = Abs(value - expect) <= tolerance;
474 
475  std::cout << GetParent()->GetName() << " Arithmetic: " << (pass ? "pass " : "FAIL ") << test
476  << ": " << value << " == " << expect << " (+/- " << tolerance << ")" << std::endl;
477 
478  NS_TEST_ASSERT_MSG_EQ_TOL(value, expect, tolerance, "Arithmetic failure in test case " << test);
479 }
480 
481 void
483 {
484  const int64x64_t tol1(0, 1);
485  const int64x64_t zero(0, 0);
486  const int64x64_t one(1, 0);
487  const int64x64_t two(2, 0);
488  const int64x64_t three(3, 0);
489 
490  std::cout << std::endl;
491  std::cout << GetParent()->GetName() << " Arithmetic: " << GetName() << std::endl;
492 
493  // NOLINTBEGIN(misc-redundant-expression)
494  Check(0, zero - zero, zero);
495  Check(1, zero - one, -one);
496  Check(2, one - one, zero);
497  Check(3, one - two, -one);
498  Check(4, one - (-one), two);
499  Check(5, (-one) - (-two), one);
500  Check(6, (-one) - two, -three);
501 
502  Check(7, zero + zero, zero);
503  Check(8, zero + one, one);
504  Check(9, one + one, two);
505  Check(10, one + two, three);
506  Check(11, one + (-one), zero);
507  Check(12, (-one) + (-two), -three);
508  Check(13, (-one) + two, one);
509 
510  Check(14, zero * zero, zero);
511  Check(15, zero * one, zero);
512  Check(16, zero * (-one), zero);
513  Check(17, one * one, one);
514  Check(18, one * (-one), -one);
515  Check(19, (-one) * (-one), one);
516 
517  Check(20, (two * three) / three, two);
518  // NOLINTEND(misc-redundant-expression)
519 
520  const int64x64_t frac = int64x64_t(0, 0xc000000000000000ULL); // 0.75
521  const int64x64_t fplf2 = frac + frac * frac; // 1.3125
522 
523  Check(21, frac, 0.75);
524  Check(22, fplf2, 1.3125);
525 
526  const int64x64_t zerof = zero + frac;
527  const int64x64_t onef = one + frac;
528  const int64x64_t twof = two + frac;
529  const int64x64_t thref = three + frac;
530 
531  // NOLINTBEGIN(misc-redundant-expression)
532  Check(23, zerof, frac);
533 
534  Check(24, zerof - zerof, zero);
535  Check(25, zerof - onef, -one);
536  Check(26, onef - onef, zero);
537  Check(27, onef - twof, -one);
538  Check(28, onef - (-onef), twof + frac);
539  Check(29, (-onef) - (-twof), one);
540  Check(30, (-onef) - twof, -thref - frac);
541 
542  Check(31, zerof + zerof, zerof + frac);
543  Check(32, zerof + onef, onef + frac);
544  Check(33, onef + onef, twof + frac);
545  Check(34, onef + twof, thref + frac);
546  Check(35, onef + (-onef), zero);
547  Check(36, (-onef) + (-twof), -thref - frac);
548  Check(37, (-onef) + twof, one);
549 
550  Check(38, zerof * zerof, frac * frac);
551  Check(39, zero * onef, zero);
552  Check(40, zerof * one, frac);
553 
554  Check(41, zerof * onef, fplf2);
555  Check(42, zerof * (-onef), -fplf2);
556  Check(43, onef * onef, onef + fplf2);
557  Check(44, onef * (-onef), -onef - fplf2);
558  Check(45, (-onef) * (-onef), onef + fplf2);
559  // NOLINTEND(misc-redundant-expression)
560 
561  // Multiplication followed by division is exact:
562  Check(46, (two * three) / three, two);
563  Check(47, (twof * thref) / thref, twof);
564 
565  // Division followed by multiplication loses a bit or two:
566  Check(48, (two / three) * three, two, 2 * tol1);
567  Check(49, (twof / thref) * thref, twof, 3 * tol1);
568 
569  // The example below shows that we really do not lose
570  // much precision internally: it is almost always the
571  // final conversion which loses precision.
572  Check(50,
573  (int64x64_t(2000000000) / int64x64_t(3)) * int64x64_t(3),
574  int64x64_t(1999999999, 0xfffffffffffffffeULL));
575 
576  // Check special values
577  Check(51, int64x64_t(0, 0x159fa87f8aeaad21ULL) * 10, int64x64_t(0, 0xd83c94fb6d2ac34aULL));
578 }
579 
588 {
589  public:
591  void DoRun() override;
598  void Check(const double result, const double expect, const std::string& msg);
599 };
600 
602  : TestCase("Test case for bug 455")
603 {
604 }
605 
606 void
607 Int64x64Bug455TestCase::Check(const double result, const double expect, const std::string& msg)
608 {
609  bool pass = result == expect;
610 
611  std::cout << GetParent()->GetName() << " Bug 455: " << (pass ? "pass " : "FAIL ")
612  << "res: " << result << " exp: " << expect << ": " << msg << std::endl;
613 
614  NS_TEST_ASSERT_MSG_EQ(result, expect, msg);
615 }
616 
617 void
619 {
620  std::cout << std::endl;
621  std::cout << GetParent()->GetName() << " Bug 455: " << GetName() << std::endl;
622 
623  int64x64_t a(0.1);
624  a /= int64x64_t(1.25);
625  Check(a.GetDouble(), 0.08, "The original testcase");
626 
627  a = int64x64_t(0.5);
628  a *= int64x64_t(5);
629  Check(a.GetDouble(), 2.5, "Simple test for multiplication");
630 
631  a = int64x64_t(-0.5);
632  a *= int64x64_t(5);
633  Check(a.GetDouble(), -2.5, "Test sign, first operation negative");
634 
635  a = int64x64_t(-0.5);
636  a *= int64x64_t(-5);
637  Check(a.GetDouble(), 2.5, "both operands negative");
638 
639  a = int64x64_t(0.5);
640  a *= int64x64_t(-5);
641  Check(a.GetDouble(), -2.5, "only second operand negative");
642 }
643 
652 {
653  public:
655  void DoRun() override;
662  void Check(const double result, const double expect, const std::string& msg);
663 };
664 
666  : TestCase("Test case for bug 863")
667 {
668 }
669 
670 void
671 Int64x64Bug863TestCase::Check(const double result, const double expect, const std::string& msg)
672 {
673  bool pass = result == expect;
674 
675  std::cout << GetParent()->GetName() << " Bug 863: " << (pass ? "pass " : "FAIL ")
676  << "res: " << result << " exp: " << expect << ": " << msg << std::endl;
677 
678  NS_TEST_ASSERT_MSG_EQ(result, expect, msg);
679 }
680 
681 void
683 {
684  std::cout << std::endl;
685  std::cout << GetParent()->GetName() << " Bug 863: " << GetName() << std::endl;
686 
687  int64x64_t a(0.9);
688  a /= int64x64_t(1);
689  Check(a.GetDouble(), 0.9, "The original testcase");
690 
691  a = int64x64_t(0.5);
692  a /= int64x64_t(0.5);
693  Check(a.GetDouble(), 1.0, "Simple test for division");
694 
695  a = int64x64_t(-0.5);
696  Check(a.GetDouble(), -0.5, "Check that we actually convert doubles correctly");
697 
698  a /= int64x64_t(0.5);
699  Check(a.GetDouble(), -1.0, "first argument negative");
700 
701  a = int64x64_t(0.5);
702  a /= int64x64_t(-0.5);
703  Check(a.GetDouble(), -1.0, "second argument negative");
704 
705  a = int64x64_t(-0.5);
706  a /= int64x64_t(-0.5);
707  Check(a.GetDouble(), 1.0, "both arguments negative");
708 }
709 
718 {
719  public:
721  void DoRun() override;
728  void Check(const uint64_t low, const std::string& value, const int64_t tolerance = 0);
729 };
730 
732  : TestCase("Test case for bug 1786")
733 {
734 }
735 
736 void
738  const std::string& str,
739  const int64_t tolerance /* = 0 */)
740 {
741  int64x64_t value(0, low);
742  std::ostringstream oss;
743  oss << std::scientific << std::setprecision(22) << value;
744 
745  if (tolerance == 0)
746  {
747  bool pass = oss.str() == str;
748 
749  std::cout << GetParent()->GetName() << " Bug 1786: " << (pass ? "pass " : "FAIL ")
750  << " 0x" << std::hex << std::setw(16) << low << std::dec << " = " << oss.str();
751  if (!pass)
752  {
753  std::cout << ", expected " << str;
754  }
755  std::cout << std::endl;
756 
757  NS_TEST_EXPECT_MSG_EQ(oss.str(), str, "Fraction string not correct");
758  }
759  else
760  {
761  // No obvious way to implement a tolerance on the strings
762 
763  std::cout << GetParent()->GetName() << " Bug 1786: "
764  << "skip "
765  << " 0x" << std::hex << std::setw(16) << low << std::dec << " = " << oss.str()
766  << ", expected " << str << std::endl;
767  }
768 }
769 
770 void
772 {
773  std::cout << std::endl;
774  std::cout << GetParent()->GetName() << " But 1786: " << GetName() << std::endl;
775 
776  int64_t tolerance = 0;
778  {
779  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
780  tolerance = 1;
781  }
782 
783  // Some of these values differ from the DoubleTestCase
784  // by one count in the last place
785  // because operator<< truncates the last output digit,
786  // instead of rounding.
787 
788  // NOLINTBEGIN(misc-redundant-expression)
789  // clang-format off
790  Check( 1ULL, "+0.0000000000000000000542");
791  Check( 2ULL, "+0.0000000000000000001084");
792  Check( 3ULL, "+0.0000000000000000001626");
793  Check( 4ULL, "+0.0000000000000000002168");
794  Check( 5ULL, "+0.0000000000000000002710");
795  Check( 6ULL, "+0.0000000000000000003253");
796  Check( 7ULL, "+0.0000000000000000003795");
797  Check( 8ULL, "+0.0000000000000000004337");
798  Check( 9ULL, "+0.0000000000000000004879");
799  Check( 0xAULL, "+0.0000000000000000005421");
800  Check( 0xFULL, "+0.0000000000000000008132");
801  Check( 0xF0ULL, "+0.0000000000000000130104");
802  Check( 0xF00ULL, "+0.0000000000000002081668");
803  Check( 0xF000ULL, "+0.0000000000000033306691");
804  Check( 0xF0000ULL, "+0.0000000000000532907052");
805  Check( 0xF00000ULL, "+0.0000000000008526512829");
806  Check( 0xF000000ULL, "+0.0000000000136424205266");
807  Check( 0xF0000000ULL, "+0.0000000002182787284255");
808  Check( 0xF00000000ULL, "+0.0000000034924596548080");
809  Check( 0xF000000000ULL, "+0.0000000558793544769287");
810  Check( 0xF0000000000ULL, "+0.0000008940696716308594");
811  Check( 0xF00000000000ULL, "+0.0000143051147460937500");
812  Check( 0xF000000000000ULL, "+0.0002288818359375000000");
813  Check( 0xF0000000000000ULL, "+0.0036621093750000000000");
814  Check( 0xF00000000000000ULL, "+0.0585937500000000000000");
815  std::cout << std::endl;
816  Check(0x7FFFFFFFFFFFFFFDULL, "+0.4999999999999999998374", tolerance);
817  Check(0x7FFFFFFFFFFFFFFEULL, "+0.4999999999999999998916", tolerance);
818  Check(0x7FFFFFFFFFFFFFFFULL, "+0.4999999999999999999458", tolerance);
819  Check(0x8000000000000000ULL, "+0.5000000000000000000000");
820  Check(0x8000000000000001ULL, "+0.5000000000000000000542", tolerance);
821  Check(0x8000000000000002ULL, "+0.5000000000000000001084", tolerance);
822  Check(0x8000000000000003ULL, "+0.5000000000000000001626", tolerance);
823  std::cout << std::endl;
824  Check(0xF000000000000000ULL, "+0.9375000000000000000000");
825  Check(0xFF00000000000000ULL, "+0.9960937500000000000000");
826  Check(0xFFF0000000000000ULL, "+0.9997558593750000000000");
827  Check(0xFFFF000000000000ULL, "+0.9999847412109375000000");
828  Check(0xFFFFF00000000000ULL, "+0.9999990463256835937500");
829  Check(0xFFFFFF0000000000ULL, "+0.9999999403953552246094");
830  Check(0xFFFFFFF000000000ULL, "+0.9999999962747097015381");
831  Check(0xFFFFFFFF00000000ULL, "+0.9999999997671693563461");
832  Check(0xFFFFFFFFF0000000ULL, "+0.9999999999854480847716");
833  Check(0xFFFFFFFFFF000000ULL, "+0.9999999999990905052982");
834  Check(0xFFFFFFFFFFF00000ULL, "+0.9999999999999431565811");
835  Check(0xFFFFFFFFFFFF0000ULL, "+0.9999999999999964472863");
836  Check(0xFFFFFFFFFFFFF000ULL, "+0.9999999999999997779554");
837  Check(0xFFFFFFFFFFFFFF00ULL, "+0.9999999999999999861222");
838  Check(0xFFFFFFFFFFFFFFF0ULL, "+0.9999999999999999991326");
839  Check(0xFFFFFFFFFFFFFFF5ULL, "+0.9999999999999999994037", tolerance);
840  Check(0xFFFFFFFFFFFFFFF6ULL, "+0.9999999999999999994579", tolerance);
841  Check(0xFFFFFFFFFFFFFFF7ULL, "+0.9999999999999999995121", tolerance);
842  Check(0xFFFFFFFFFFFFFFF8ULL, "+0.9999999999999999995663", tolerance);
843  Check(0xFFFFFFFFFFFFFFF9ULL, "+0.9999999999999999996205", tolerance);
844  Check(0xFFFFFFFFFFFFFFFAULL, "+0.9999999999999999996747", tolerance);
845  Check(0xFFFFFFFFFFFFFFFBULL, "+0.9999999999999999997289", tolerance);
846  Check(0xFFFFFFFFFFFFFFFCULL, "+0.9999999999999999997832", tolerance);
847  Check(0xFFFFFFFFFFFFFFFDULL, "+0.9999999999999999998374", tolerance);
848  Check(0xFFFFFFFFFFFFFFFEULL, "+0.9999999999999999998916", tolerance);
849  Check(0xFFFFFFFFFFFFFFFFULL, "+0.9999999999999999999458", tolerance);
850  // clang-format on
851  // NOLINTEND(misc-redundant-expression)
852 }
853 
860 {
861  public:
863  void DoRun() override;
864 
871  void Check(const bool result, const bool expect, const std::string& msg);
872 };
873 
875  : TestCase("Basic compare operations")
876 {
877 }
878 
879 void
880 Int64x64CompareTestCase::Check(const bool result, const bool expect, const std::string& msg)
881 {
882  bool pass = result == expect;
883 
884  std::cout << GetParent()->GetName() << " Compare: " << (pass ? "pass " : "FAIL ") << msg
885  << std::endl;
886 
887  NS_TEST_ASSERT_MSG_EQ(result, expect, msg);
888 }
889 
890 void
892 {
893  std::cout << std::endl;
894  std::cout << GetParent()->GetName() << " Compare: " << GetName() << std::endl;
895 
896  const int64x64_t zero(0, 0);
897  const int64x64_t one(1, 0);
898  const int64x64_t two(2, 0);
899  const int64x64_t mone(-1, 0);
900  const int64x64_t mtwo(-2, 0);
901  const int64x64_t frac = int64x64_t(0, 0xc000000000000000ULL); // 0.75
902  const int64x64_t zerof = zero + frac;
903  const int64x64_t onef = one + frac;
904  const int64x64_t monef = mone - frac;
905  const int64x64_t mtwof = mtwo - frac;
906 
907  // NOLINTBEGIN(misc-redundant-expression)
908  Check(zerof == zerof, true, "equality, zero");
909  Check(onef == onef, true, "equality, positive");
910  Check(mtwof == mtwof, true, "equality, negative");
911  Check(zero == one, false, "equality false, zero");
912  Check(one == two, false, "equality false, unsigned");
913  Check(one == mone, false, "equality false, signed");
914  Check(onef == one, false, "equality false, fraction");
915  std::cout << std::endl;
916 
917  Check(zerof != zerof, false, "inequality, zero");
918  Check(onef != onef, false, "inequality, positive");
919  Check(mtwof != mtwof, false, "inequality, negative");
920  Check(zero != one, true, "inequality true, zero");
921  Check(one != two, true, "inequality true, unsigned");
922  Check(one != mone, true, "inequality true, signed");
923  Check(onef != one, true, "inequality true, fraction");
924  std::cout << std::endl;
925 
926  Check(zerof < onef, true, "less, zerof");
927  Check(zero < zerof, true, "less, zero");
928  Check(one < onef, true, "less, positive");
929  Check(monef < mone, true, "less, negative");
930  Check(onef < one, false, "less, false, positive");
931  Check(mtwo < mtwof, false, "less, false, negative");
932  std::cout << std::endl;
933 
934  Check(zerof <= zerof, true, "less equal, equal, zerof");
935  Check(zero <= zerof, true, "less equal, less, zero");
936  Check(onef <= onef, true, "less equal, equal, positive");
937  Check(monef <= mone, true, "less equal, less, negative");
938  Check(onef <= one, false, "less equal, false, positive");
939  Check(mtwo <= mtwof, false, "less equal, false, negative");
940  std::cout << std::endl;
941 
942  Check(onef > zerof, true, "greater, zerof");
943  Check(zerof > zero, true, "greater, zero");
944  Check(onef > one, true, "greater, positive");
945  Check(mone > monef, true, "greater, negative");
946  Check(one > onef, false, "greater, false, positive");
947  Check(mtwof > mtwo, false, "greater, false, negative");
948  std::cout << std::endl;
949 
950  Check(zerof >= zerof, true, "greater equal, equal, zerof");
951  Check(zerof >= zero, true, "greater equal, greater, zero");
952  Check(onef >= onef, true, "greater equal, equal, positive");
953  Check(mone >= monef, true, "greater equal, greater, negative");
954  Check(one >= onef, false, "greater equal, false, positive");
955  Check(mtwof >= mtwo, false, "greater equal, false, negative");
956  std::cout << std::endl;
957 
958  Check(zero == false, true, "zero == false");
959  Check(one == true, true, "one == true");
960  Check(zerof != false, true, "zerof != false");
961  Check((!zero) == true, true, "!zero == true");
962  Check((!zerof) == false, true, "!zerof == false");
963  Check((!one) == false, true, "!one == false");
964  Check((+onef) == onef, true, "unary positive");
965  Check((-onef) == monef, true, "unary negative");
966  // NOLINTEND(misc-redundant-expression)
967 }
968 
975 {
976  public:
978  void DoRun() override;
983  void Check(const int64_t factor);
992  void CheckCase(const uint64_t factor,
993  const int64x64_t result,
994  const int64x64_t expect,
995  const std::string& msg,
996  const double tolerance = 0);
997 };
998 
1000  : TestCase("Invert and MulByInvert")
1001 {
1002 }
1003 
1004 void
1006  const int64x64_t result,
1007  const int64x64_t expect,
1008  const std::string& msg,
1009  const double tolerance /* = 0 */)
1010 {
1011  bool pass = Abs(result - expect) <= tolerance;
1012 
1013  std::cout << GetParent()->GetName() << " Invert: ";
1014 
1015  if (pass)
1016  {
1017  std::cout << "pass: " << factor << ": ";
1018  }
1019  else
1020  {
1021  std::cout << "FAIL: " << factor << ": "
1022  << "(res: " << result << " exp: " << expect << " tol: " << tolerance << ") ";
1023  }
1024  std::cout << msg << std::endl;
1025 
1026  NS_TEST_ASSERT_MSG_EQ_TOL(result, expect, int64x64_t(tolerance), msg);
1027 }
1028 
1029 void
1030 Int64x64InvertTestCase::Check(const int64_t factor)
1031 {
1032  const int64x64_t one(1, 0);
1033  const int64x64_t factorI = one / int64x64_t(factor);
1034 
1035  const int64x64_t a = int64x64_t::Invert(factor);
1036  int64x64_t b(factor);
1037 
1038  double tolerance = 0;
1040  {
1041  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
1042  tolerance = 0.000000000000000001L;
1043  }
1044 
1045  b.MulByInvert(a);
1046  CheckCase(factor, b, one, "x * x^-1 == 1", tolerance);
1047 
1048  int64x64_t c(1);
1049  c.MulByInvert(a);
1050  CheckCase(factor, c, factorI, "1 * x^-1 == 1 / x");
1051 
1052  int64x64_t d(1);
1053  d /= (int64x64_t(factor));
1054  CheckCase(factor, d, c, "1/x == x^-1");
1055 
1056  int64x64_t e(-factor);
1057  e.MulByInvert(a);
1058  CheckCase(factor, e, -one, "-x * x^-1 == -1", tolerance);
1059 }
1060 
1061 void
1063 {
1064  std::cout << std::endl;
1065  std::cout << GetParent()->GetName() << " Invert: " << GetName() << std::endl;
1066 
1067  Check(2);
1068  Check(3);
1069  Check(4);
1070  Check(5);
1071  Check(6);
1072  Check(10);
1073  Check(99);
1074  Check(100);
1075  Check(1000);
1076  Check(10000);
1077  Check(100000);
1078  Check(100000);
1079  Check(1000000);
1080  Check(10000000);
1081  Check(100000000);
1082  Check(1000000000);
1083  Check(10000000000LL);
1084  Check(100000000000LL);
1085  Check(1000000000000LL);
1086  Check(10000000000000LL);
1087  Check(100000000000000LL);
1088  Check(1000000000000000LL);
1089 }
1090 
1097 {
1098  public:
1100  void DoRun() override;
1101 
1106  void Check(const int64_t intPart);
1114  void Check(const long double dec,
1115  const long double frac,
1116  const int64_t intPart,
1117  const uint64_t lo);
1118 
1119  private:
1137  static constexpr int MISS_MANT_DIG = std::max(0, 64 - LDBL_MANT_DIG);
1138 
1146  static constexpr long double MIN_LOW = 1 << MISS_MANT_DIG;
1147 
1162  static const long double MIN_MANT;
1163 
1164  // Member variables
1165  long double m_last;
1166  int64x64_t
1169 };
1170 
1171 /* static */
1172 const long double Int64x64DoubleTestCase::MIN_MANT =
1173  std::round(1e22 / std::pow(2.0L, std::min(64, LDBL_MANT_DIG))) / 1e22;
1174 
1176  : TestCase("Construct from floating point."),
1177  m_last{0},
1178  m_deltaMax{0},
1179  m_deltaCount{0}
1180 {
1181 }
1182 
1183 void
1184 Int64x64DoubleTestCase::Check(const long double dec,
1185  const long double frac,
1186  const int64_t intPart,
1187  const uint64_t lo)
1188 {
1189  // 1. The double value we're going to convert
1190  long double value = dec + frac;
1191 
1192  // 2. The expected value of the conversion
1193  int64x64_t expect(intPart, lo);
1194 
1195  // 1a, 2a. Handle lower-precision architectures by scaling up the fractional part
1196  // We assume MISS_MANT_DIG is much less than 64, MIN_MANT much less than 0.5
1197  // Could check lo < MIN_LOW instead...
1198 
1199  /*
1200  This approach works for real values with mantissa very near zero,
1201  but isn't ideal. For values near 0.5, say, the low order bits
1202  are completely lost, since they exceed the precision of the
1203  double representation. This shows up on M1 and ARM architectures
1204  as the x.5... values all skipped, because they are indistinguishable
1205  from x.5 exactly.
1206 
1207  A more involved alternative would be to separate the
1208  "frac" and "low" values in the caller. Then the underflow
1209  rescaling could be applied to the low bits only,
1210  before adding to the frac part.
1211 
1212  To do this the signature of this function would have to be
1213  Check (cld dec, cld frac, int64_t intPart, int64_t low);
1214  ^- Note this signed
1215  The caller Check (intPart) would look like
1216 
1217  Check (v, 0.0L, intPart, 0x0LL);
1218  Check (v, 0.0L, intPart, 0x1LL);
1219  Check (v, 0.0L, intPart, 0x2LL);
1220  ...
1221  Check (v, 0.5L, intPart, -0xFLL);
1222  Check (v, 0.5L, intPart, -0xELL);
1223  ...
1224  Check (v, 0.5L, intPart, 0x0LL);
1225  Check (v, 0.5L, intPart, 0x1LL);
1226 
1227  Here we would construct value as
1228  long double lowLd = (double)low / std::pow(2.0L, 64);
1229  value = dec + frac + lowLd;
1230 
1231  For underflow cases:
1232  value = dec + frac + std::max::(lowLd, MIN_MANT);
1233  */
1234 
1235  bool under = false;
1236  if (frac && (frac < MIN_MANT))
1237  {
1238  under = true;
1239  value = dec + std::max(frac * MIN_LOW, MIN_MANT);
1240  expect = int64x64_t(intPart, lo * MIN_LOW);
1241  }
1242 
1243  // 3. The actual value of the conversion
1244  const int64x64_t result = int64x64_t(value);
1245 
1246  // 4. Absolute error in the conversion
1247  const int64x64_t delta = Abs(result - expect);
1248 
1249  // Mark repeats (no change in input floating value) as "skip" (but not integers)
1250  const bool skip = (frac && (value == m_last));
1251  // Save the value to detect unchanged values next time
1252  m_last = value;
1253 
1254  // 5. Tolerance for the test, scaled to the magnitude of value
1255  // Tolerance will be computed from the value, epsilon and margin
1256  int64x64_t tolerance;
1257 
1258  // Default epsilon
1260 
1261  // A few cases need extra tolerance
1262  // If you add cases please thoroughly document the configuration
1263  long double margin = 0;
1264 
1266  {
1267  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
1268  margin = 1.0;
1269  }
1271  {
1272  // Valgrind and Windows use 64-bit doubles for long doubles
1273  // See ns-3 bug 1882
1274  // Need non-zero margin to ensure final tolerance is non-zero
1275  margin = 1.0;
1277  }
1278 
1279  // Final tolerance amount
1280  tolerance = std::max(1.0L, std::fabs(value)) * epsilon + margin * epsilon;
1281 
1282  // 6. Is the conversion acceptably close to the expected value?
1283  const bool pass = delta <= tolerance;
1284 
1285  // 7. Show the result of this check
1286 
1287  // Save stream format flags
1288  std::ios_base::fmtflags ff = std::cout.flags();
1289  std::cout << std::fixed << std::setprecision(22);
1290 
1291  std::cout << GetParent()->GetName()
1292  << " Double: " << (skip ? "skip " : (pass ? "pass " : "FAIL ")) << std::showpos
1293  << value << " == " << Printer(result) << (under ? " (underflow)" : "") << std::endl;
1294 
1295  if (delta)
1296  {
1297  // There was a difference, show the expected value
1298  std::cout << GetParent()->GetName() << std::left << std::setw(43) << " expected"
1299  << std::right << Printer(expect) << std::endl;
1300 
1301  if (delta == tolerance)
1302  {
1303  // Short form: show the delta, and note it equals the tolerance
1304  std::cout << GetParent()->GetName() << std::left << std::setw(43)
1305  << " delta = tolerance" << std::right << Printer(delta) << std::endl;
1306  }
1307  else
1308  {
1309  // Long form, show both delta and tolerance
1310  std::cout << GetParent()->GetName() << std::left << std::setw(43) << " delta"
1311  << std::right << Printer(delta) << std::endl;
1312  std::cout << GetParent()->GetName() << std::left << std::setw(43)
1313  << " tolerance" << std::right << Printer(tolerance)
1314  << " eps: " << epsilon << ", margin: " << margin << std::endl;
1315  }
1316 
1317  // Record number and max delta
1318  ++m_deltaCount;
1319 
1320  if (delta > m_deltaMax)
1321  {
1322  m_deltaMax = delta;
1323  }
1324  }
1325 
1326  // Report pass/fail
1327  NS_TEST_ASSERT_MSG_EQ_TOL(result, expect, tolerance, "int64x64_t (long double) failed");
1328  std::cout.flags(ff);
1329 }
1330 
1331 void
1332 Int64x64DoubleTestCase::Check(const int64_t intPart)
1333 {
1334  std::cout << std::endl;
1335  std::cout << GetParent()->GetName() << " Double: "
1336  << "integer: " << intPart << std::endl;
1337  // Reset last value for new intPart
1338  m_last = intPart;
1339  // Save current number and max delta, so we can report max from just this intPart
1340  int64x64_t deltaMaxPrior = m_deltaMax;
1341  m_deltaMax = 0;
1342  int deltaCountPrior = m_deltaCount;
1343  m_deltaCount = 0;
1344 
1345  // Nudging the integer part eliminates deltas around 0
1346  long double v = intPart;
1347 
1348  Check(v, 0.0L, intPart, 0x0ULL);
1349  Check(v, 0.0000000000000000000542L, intPart, 0x1ULL);
1350  Check(v, 0.0000000000000000001084L, intPart, 0x2ULL);
1351  Check(v, 0.0000000000000000001626L, intPart, 0x3ULL);
1352  Check(v, 0.0000000000000000002168L, intPart, 0x4ULL);
1353  Check(v, 0.0000000000000000002711L, intPart, 0x5ULL);
1354  Check(v, 0.0000000000000000003253L, intPart, 0x6ULL);
1355  Check(v, 0.0000000000000000003795L, intPart, 0x7ULL);
1356  Check(v, 0.0000000000000000004337L, intPart, 0x8ULL);
1357  Check(v, 0.0000000000000000004879L, intPart, 0x9ULL);
1358  Check(v, 0.0000000000000000005421L, intPart, 0xAULL);
1359  Check(v, 0.0000000000000000005963L, intPart, 0xBULL);
1360  Check(v, 0.0000000000000000006505L, intPart, 0xCULL);
1361  Check(v, 0.0000000000000000007047L, intPart, 0xDULL);
1362  Check(v, 0.0000000000000000007589L, intPart, 0xEULL);
1363  Check(v, 0.0000000000000000008132L, intPart, 0xFULL);
1364  Check(v, 0.0000000000000000130104L, intPart, 0xF0ULL);
1365  Check(v, 0.0000000000000002081668L, intPart, 0xF00ULL);
1366  Check(v, 0.0000000000000033306691L, intPart, 0xF000ULL);
1367  Check(v, 0.0000000000000532907052L, intPart, 0xF0000ULL);
1368  Check(v, 0.0000000000008526512829L, intPart, 0xF00000ULL);
1369  Check(v, 0.0000000000136424205266L, intPart, 0xF000000ULL);
1370  Check(v, 0.0000000002182787284255L, intPart, 0xF0000000ULL);
1371  Check(v, 0.0000000034924596548080L, intPart, 0xF00000000ULL);
1372  Check(v, 0.0000000558793544769287L, intPart, 0xF000000000ULL);
1373  Check(v, 0.0000008940696716308594L, intPart, 0xF0000000000ULL);
1374  Check(v, 0.0000143051147460937500L, intPart, 0xF00000000000ULL);
1375  Check(v, 0.0002288818359375000000L, intPart, 0xF000000000000ULL);
1376  Check(v, 0.0036621093750000000000L, intPart, 0xF0000000000000ULL);
1377  Check(v, 0.0585937500000000000000L, intPart, 0xF00000000000000ULL);
1378  std::cout << std::endl;
1379  Check(v, 0.4999999999999999991326L, intPart, 0x7FFFFFFFFFFFFFF0ULL);
1380  Check(v, 0.4999999999999999991868L, intPart, 0x7FFFFFFFFFFFFFF1ULL);
1381  Check(v, 0.4999999999999999992411L, intPart, 0x7FFFFFFFFFFFFFF2ULL);
1382  Check(v, 0.4999999999999999992953L, intPart, 0x7FFFFFFFFFFFFFF3ULL);
1383  Check(v, 0.4999999999999999993495L, intPart, 0x7FFFFFFFFFFFFFF4ULL);
1384  Check(v, 0.4999999999999999994037L, intPart, 0x7FFFFFFFFFFFFFF5ULL);
1385  Check(v, 0.4999999999999999994579L, intPart, 0x7FFFFFFFFFFFFFF6ULL);
1386  Check(v, 0.4999999999999999995121L, intPart, 0x7FFFFFFFFFFFFFF7ULL);
1387  Check(v, 0.4999999999999999995663L, intPart, 0x7FFFFFFFFFFFFFF8ULL);
1388  Check(v, 0.4999999999999999996205L, intPart, 0x7FFFFFFFFFFFFFF9ULL);
1389  Check(v, 0.4999999999999999996747L, intPart, 0x7FFFFFFFFFFFFFFAULL);
1390  Check(v, 0.4999999999999999997289L, intPart, 0x7FFFFFFFFFFFFFFBULL);
1391  Check(v, 0.4999999999999999997832L, intPart, 0x7FFFFFFFFFFFFFFCULL);
1392  Check(v, 0.4999999999999999998374L, intPart, 0x7FFFFFFFFFFFFFFDULL);
1393  Check(v, 0.4999999999999999998916L, intPart, 0x7FFFFFFFFFFFFFFEULL);
1394  Check(v, 0.4999999999999999999458L, intPart, 0x7FFFFFFFFFFFFFFFULL);
1395  Check(v, 0.5000000000000000000000L, intPart, 0x8000000000000000ULL);
1396  Check(v, 0.5000000000000000000542L, intPart, 0x8000000000000001ULL);
1397  Check(v, 0.5000000000000000001084L, intPart, 0x8000000000000002ULL);
1398  Check(v, 0.5000000000000000001626L, intPart, 0x8000000000000003ULL);
1399  Check(v, 0.5000000000000000002168L, intPart, 0x8000000000000004ULL);
1400  Check(v, 0.5000000000000000002711L, intPart, 0x8000000000000005ULL);
1401  Check(v, 0.5000000000000000003253L, intPart, 0x8000000000000006ULL);
1402  Check(v, 0.5000000000000000003795L, intPart, 0x8000000000000007ULL);
1403  Check(v, 0.5000000000000000004337L, intPart, 0x8000000000000008ULL);
1404  Check(v, 0.5000000000000000004879L, intPart, 0x8000000000000009ULL);
1405  Check(v, 0.5000000000000000005421L, intPart, 0x800000000000000AULL);
1406  Check(v, 0.5000000000000000005963L, intPart, 0x800000000000000BULL);
1407  Check(v, 0.5000000000000000006505L, intPart, 0x800000000000000CULL);
1408  Check(v, 0.5000000000000000007047L, intPart, 0x800000000000000DULL);
1409  Check(v, 0.5000000000000000007589L, intPart, 0x800000000000000EULL);
1410  Check(v, 0.5000000000000000008132L, intPart, 0x800000000000000FULL);
1411  std::cout << std::endl;
1412  Check(v, 0.9375000000000000000000L, intPart, 0xF000000000000000ULL);
1413  Check(v, 0.9960937500000000000000L, intPart, 0xFF00000000000000ULL);
1414  Check(v, 0.9997558593750000000000L, intPart, 0xFFF0000000000000ULL);
1415  Check(v, 0.9999847412109375000000L, intPart, 0xFFFF000000000000ULL);
1416  Check(v, 0.9999990463256835937500L, intPart, 0xFFFFF00000000000ULL);
1417  Check(v, 0.9999999403953552246094L, intPart, 0xFFFFFF0000000000ULL);
1418  Check(v, 0.9999999962747097015381L, intPart, 0xFFFFFFF000000000ULL);
1419  Check(v, 0.9999999997671693563461L, intPart, 0xFFFFFFFF00000000ULL);
1420  Check(v, 0.9999999999854480847716L, intPart, 0xFFFFFFFFF0000000ULL);
1421  Check(v, 0.9999999999990905052982L, intPart, 0xFFFFFFFFFF000000ULL);
1422  Check(v, 0.9999999999999431565811L, intPart, 0xFFFFFFFFFFF00000ULL);
1423  Check(v, 0.9999999999999964472863L, intPart, 0xFFFFFFFFFFFF0000ULL);
1424  Check(v, 0.9999999999999997779554L, intPart, 0xFFFFFFFFFFFFF000ULL);
1425  Check(v, 0.9999999999999999861222L, intPart, 0xFFFFFFFFFFFFFF00ULL);
1426  Check(v, 0.9999999999999999991326L, intPart, 0xFFFFFFFFFFFFFFF0ULL);
1427  Check(v, 0.9999999999999999991868L, intPart, 0xFFFFFFFFFFFFFFF1ULL);
1428  Check(v, 0.9999999999999999992411L, intPart, 0xFFFFFFFFFFFFFFF2ULL);
1429  Check(v, 0.9999999999999999992943L, intPart, 0xFFFFFFFFFFFFFFF3ULL);
1430  Check(v, 0.9999999999999999993495L, intPart, 0xFFFFFFFFFFFFFFF4ULL);
1431  Check(v, 0.9999999999999999994037L, intPart, 0xFFFFFFFFFFFFFFF5ULL);
1432  Check(v, 0.9999999999999999994579L, intPart, 0xFFFFFFFFFFFFFFF6ULL);
1433  Check(v, 0.9999999999999999995121L, intPart, 0xFFFFFFFFFFFFFFF7ULL);
1434  Check(v, 0.9999999999999999995663L, intPart, 0xFFFFFFFFFFFFFFF8ULL);
1435  Check(v, 0.9999999999999999996205L, intPart, 0xFFFFFFFFFFFFFFF9ULL);
1436  Check(v, 0.9999999999999999996747L, intPart, 0xFFFFFFFFFFFFFFFAULL);
1437  Check(v, 0.9999999999999999997289L, intPart, 0xFFFFFFFFFFFFFFFBULL);
1438  Check(v, 0.9999999999999999997832L, intPart, 0xFFFFFFFFFFFFFFFCULL);
1439  Check(v, 0.9999999999999999998374L, intPart, 0xFFFFFFFFFFFFFFFDULL);
1440  Check(v, 0.9999999999999999998916L, intPart, 0xFFFFFFFFFFFFFFFEULL);
1441  Check(v, 0.9999999999999999999458L, intPart, 0xFFFFFFFFFFFFFFFFULL);
1442 
1443  std::cout << GetParent()->GetName() << " Double: "
1444  << "integer:" << std::setw(4) << intPart << ": deltas:" << std::setw(4)
1445  << m_deltaCount << ", max: " << Printer(m_deltaMax) << std::endl;
1446 
1447  // Add the count, max from this intPart to the grand totals
1448  m_deltaCount += deltaCountPrior;
1449  m_deltaMax = Max(m_deltaMax, deltaMaxPrior);
1450 }
1451 
1452 void
1454 {
1455  std::cout << std::endl;
1456  std::cout << GetParent()->GetName() << " Double: " << GetName() << std::endl;
1457 
1458  // Save stream format flags
1459  std::ios_base::fmtflags ff = std::cout.flags();
1460 
1461  std::cout << GetParent()->GetName() << " Double: "
1462  << "FLT_RADIX: " << FLT_RADIX
1463  << "\n LDBL_MANT_DIG: " << LDBL_MANT_DIG
1464  << "\n MISS_MANT_DIG: " << MISS_MANT_DIG
1465  << "\n MIN_LOW: " << Printer(MIN_LOW) << " (" << std::hexfloat
1466  << MIN_LOW << ")" << std::defaultfloat
1467  << "\n MIN_MANT: " << Printer(MIN_MANT) << std::endl;
1468 
1469  std::cout << std::scientific << std::setprecision(21);
1470 
1471  Check(-2);
1472  Check(-1);
1473  Check(0);
1474  Check(1);
1475  Check(2);
1476 
1477  std::cout << GetParent()->GetName() << " Double: "
1478  << "Total deltas:" << std::setw(7) << m_deltaCount
1479  << ", max delta: " << Printer(m_deltaMax) << std::endl;
1480 
1481  std::cout.flags(ff);
1482 }
1483 
1490 {
1491  public:
1493  void DoRun() override;
1494 };
1495 
1497  : TestCase("Print the implementation")
1498 {
1499 }
1500 
1501 void
1503 {
1504  std::cout << std::endl;
1505  std::cout << GetParent()->GetName() << " Impl: " << GetName() << std::endl;
1506 
1507  std::cout << "int64x64_t::implementation: ";
1509  {
1510  case (int64x64_t::int128_impl):
1511  std::cout << "int128_impl";
1512  break;
1513  case (int64x64_t::cairo_impl):
1514  std::cout << "cairo_impl";
1515  break;
1516  case (int64x64_t::ld_impl):
1517  std::cout << "ld_impl";
1518  break;
1519  default:
1520  std::cout << "unknown!";
1521  }
1522  std::cout << std::endl;
1523 
1524 #if defined(INT64X64_USE_CAIRO) && !defined(PYTHON_SCAN)
1525  std::cout << "cairo_impl64: " << cairo_impl64 << std::endl;
1526  std::cout << "cairo_impl128: " << cairo_impl128 << std::endl;
1527 #endif
1528 
1530  {
1531  std::cout << "Running with 64-bit long doubles" << std::endl;
1532  }
1533 }
1534 
1557 {
1558  public:
1560  : TestSuite("int64x64", UNIT)
1561  {
1574  }
1575 };
1576 
1578 
1579 } // namespace test
1580 
1581 } // namespace int64x64
1582 
1583 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:41
#define max(a, b)
Definition: 80211b.c:42
const char * cairo_impl64
Definition: cairo-wideint.c:48
const char * cairo_impl128
encapsulates test code
Definition: test.h:1060
@ QUICK
Fast test.
Definition: test.h:1065
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
TestCase * GetParent() const
Get the parent of this TestCase.
Definition: test.cc:380
std::string GetName() const
Definition: test.cc:373
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
void DoRun() override
Implementation to actually run this TestCase.
void Check(const int test, const int64x64_t value, const int64x64_t expect, const int64x64_t tolerance=int64x64_t(0, 0))
Check the int64x64 for correctness.
void Check(const uint64_t low, const std::string &value, const int64_t tolerance=0)
Check the int64x64 for correctness.
void DoRun() override
Implementation to actually run this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void Check(const double result, const double expect, const std::string &msg)
Check the int64x64 for correctness.
void Check(const double result, const double expect, const std::string &msg)
Check the int64x64 for correctness.
void DoRun() override
Implementation to actually run this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void Check(const bool result, const bool expect, const std::string &msg)
Check the int64x64 for correctness.
Test: construct from floating point.
static constexpr long double MIN_LOW
The smallest low word we expect to get from a conversion.
static constexpr int MISS_MANT_DIG
Compute a multiplier to match the mantissa size on this platform.
void DoRun() override
Implementation to actually run this TestCase.
void Check(const int64_t intPart)
Check the int64x64 for correctness.
int m_deltaCount
The number of times a delta was recorded.
long double m_last
The last value tested.
static const long double MIN_MANT
Smallest mantissa we expect to convert to a non-zero low word.
int64x64_t m_deltaMax
The maximum observed difference between expected and computed values.
Test: manipulate the high and low part of every number.
void DoRun() override
Implementation to actually run this TestCase.
void Check(const int64_t hi, const uint64_t lo)
Check the high and low parts for correctness.
void DoRun() override
Implementation to actually run this TestCase.
Test: roundtrip int64x64_t numbers as strings.
void Check(const std::string &str, const int64_t tolerance=0)
Check the iont64x64 for correctness.
void DoRun() override
Implementation to actually run this TestCase.
Test: parse int64x64_t numbers as strings.
void Check(const std::string &str, const int64_t hi, const uint64_t lo, const int64_t tolerance=0)
Check the iont64x64 for correctness.
void DoRun() override
Implementation to actually run this TestCase.
void Check(const int64x64_t value, const int64_t expectInt, const int64_t expectRnd)
Check the int64x64 value for correctness.
void DoRun() override
Implementation to actually run this TestCase.
void CheckCase(const uint64_t factor, const int64x64_t result, const int64x64_t expect, const std::string &msg, const double tolerance=0)
Check the int64x64 for correctness.
void DoRun() override
Implementation to actually run this TestCase.
void Check(const int64_t factor)
Check the int64x64 for correctness.
Pretty printer for test cases.
int64x64_t m_value
The int64x64_t value.
bool m_haveInt
Do we have a full int64x64_t value?
int64_t m_high
The high (integer) word.
Printer(const int64x64_t value)
Construct from an int64x64_t Q64.64 value.
Printer(const int64_t high, const uint64_t low)
Construct from high and low words of Q64.64 representation.
uint64_t m_low
The low (fractional) word.
friend std::ostream & operator<<(std::ostream &os, const Printer &p)
Output streamer, the main reason for this class.
High precision numerical type, implementing Q64.64 fixed precision.
@ int128_impl
Native int128_t implementation.
@ ld_impl
long double implementation
@ cairo_impl
cairo wideint implementation
void MulByInvert(const int64x64_t &o)
Multiply this value by a Q0.128 value, presumably representing an inverse, completing a division oper...
static enum impl_type implementation
Type tag for this implementation.
double GetDouble() const
Get this value as a double.
static int64x64_t Invert(const uint64_t v)
Compute the inverse of an integer value.
static double zero
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
Definition: int64x64.h:243
int64x64_t Abs(const int64x64_t &value)
Absolute value.
Definition: int64x64.h:215
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:229
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:144
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:251
#define NS_TEST_EXPECT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report if ...
Definition: test.h:510
#define NS_TEST_ASSERT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report and...
Definition: test.h:337
#define HP_MAX_64
Floating point value of HP_MASK_LO + 1 We really want:
#define RUNNING_WITH_LIMITED_PRECISION
Checks if running on Valgrind, which assumes long doubles are 64-bit doubles.
static Int64x64TestSuite g_int64x64TestSuite
Static variable for test initialization.
std::ostream & operator<<(std::ostream &os, const Printer &p)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
-ray-to-three-gpp-ch-calibration