A Discrete-Event Network Simulator
API
int64x64-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 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 "ns3/int64x64.h"
21 #include "ns3/test.h"
22 #include "ns3/valgrind.h" // Bug 1882
23 
24 #include <cfloat> // FLT_RADIX,...
25 #include <cmath> // fabs, round
26 #include <iomanip>
27 #include <limits> // numeric_limits<>::epsilon ()
28 
29 using namespace ns3;
30 
31 namespace ns3 {
32 
33 namespace int64x64 {
34 
35 namespace test {
36 
54 class Printer
55 {
56 public:
63  Printer (const int64_t high, const uint64_t low)
64  : m_haveInt (false),
65  m_value (0),
66  m_high (high),
67  m_low (low)
68  { }
69 
75  Printer (const int64x64_t value)
76  : m_haveInt (true),
77  m_value (value),
78  m_high (value.GetHigh ()),
79  m_low (value.GetLow ())
80  { }
81 
82 private:
90  friend std::ostream & operator << (std::ostream & os, const Printer & p);
91 
92  bool m_haveInt;
94  int64_t m_high;
95  uint64_t m_low;
96 };
97 
98 std::ostream & operator << (std::ostream & os, const Printer & p)
99 {
100  if (p.m_haveInt)
101  {
102  os << std::fixed << std::setprecision (22)
103  << p.m_value;
104 
105  }
106 
107  os << std::hex << std::setfill ('0')
108  << " (0x" << std::setw (16) << p.m_high
109  << " 0x" << std::setw (16) << p.m_low << ")"
110  << std::dec << std::setfill (' ');
111  return os;
112 }
113 
120 {
121 public:
123  virtual void DoRun (void);
129  void Check (const int64_t hi, const uint64_t lo);
130 };
131 
133  : TestCase ("Manipulate the high and low part of every number")
134 {}
135 
136 void
137 Int64x64HiLoTestCase::Check (const int64_t hi, const uint64_t lo)
138 {
139  uint64_t tolerance = 0;
141  {
142  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
143  tolerance = 1;
144  }
145 
146  int64x64_t value = int64x64_t (hi,lo);
147  uint64_t vLow = value.GetLow ();
148  bool pass = ( (value.GetHigh () == hi)
149  && ( (Max (vLow, lo) - Min (vLow, lo)) <= tolerance)
150  );
151 
152  std::cout << GetParent ()->GetName () << " Check: "
153  << (pass ? "pass " : "FAIL ")
154  << Printer (value) << " from" << Printer (hi, lo)
155  << std::endl;
156 
157  NS_TEST_EXPECT_MSG_EQ (value.GetHigh (), hi,
158  "High part does not match for hi:" << hi
159  << " lo: " << lo);
160  NS_TEST_EXPECT_MSG_EQ_TOL ((int64_t)vLow, (int64_t)lo, (int64_t)tolerance,
161  "Low part does not match for hi: " << hi
162  << " lo: " << lo);
163 }
164 
165 void
167 {
168  std::cout << std::endl;
169  std::cout << GetParent ()->GetName () << " Check: " << GetName ()
170  << std::endl;
171 
172  uint64_t low = 1;
174  {
175  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
176  low = static_cast<uint64_t> (HP_MAX_64 * std::numeric_limits<long double>::epsilon ());
177  }
178 
179  Check ( 0, 0);
180  Check ( 0, low);
181  Check ( 0, 0xffffffffffffffffULL - low);
182 
183  Check ( 1, 0);
184  Check ( 1, low);
185  Check ( 1, 0xffffffffffffffffULL - low);
186 
187  Check (-1, 0);
188  Check (-1, low);
189  Check (-1, 0xffffffffffffffffULL - low);
190 }
191 
192 
199 {
200 public:
202  virtual void DoRun (void);
209  void Check (const int64x64_t value,
210  const int64_t expectInt,
211  const int64_t expectRnd);
212 };
213 
215  : TestCase ("Check GetInt and Round")
216 {}
217 
218 void
220  const int64_t expectInt,
221  const int64_t expectRnd)
222 {
223  int64_t vInt = value.GetInt ();
224  int64_t vRnd = value.Round ();
225 
226  bool pass = (vInt == expectInt) && (vRnd == expectRnd);
227  std::cout << GetParent ()->GetName () << " Check: "
228  << (pass ? "pass " : "FAIL ")
229  << value
230  << " (int)-> " << std::setw (2) << vInt << " (expected: " << std::setw (2) << expectInt
231  << "), (rnd)-> " << std::setw (2) << vRnd << " (expected " << std::setw (2) << expectRnd
232  << ")"
233  << std::endl;
234 
235  NS_TEST_EXPECT_MSG_EQ (vInt, expectInt,
236  "Truncation to int failed");
237  NS_TEST_EXPECT_MSG_EQ (vRnd, expectRnd,
238  "Rounding to int failed.");
239 }
240 
241 void
243 {
244  std::cout << std::endl;
245  std::cout << GetParent ()->GetName () << " Check: " << GetName ()
246  << std::endl;
247 
248  // Trivial cases
249  Check ( 0, 0, 0);
250  Check ( 1, 1, 1);
251  Check (-1, -1, -1);
252 
253  // Both should move toward zero
254  Check ( 2.4, 2, 2);
255  Check (-2.4, -2, -2);
256 
257  // GetInt should move toward zero; Round should move away
258  Check ( 3.6, 3, 4);
259  Check (-3.6, -3, -4);
260  // Boundary case
261  Check ( 4.5, 4, 5);
262  Check (-4.5, -4, -5);
263 }
264 
265 
272 {
273 public:
275  virtual void DoRun (void);
283  void Check (const std::string & str,
284  const int64_t hi, const uint64_t lo,
285  const int64_t tolerance = 0);
286 };
288  : TestCase ("Parse int64x64_t numbers as strings")
289 {}
290 void
291 Int64x64InputTestCase::Check (const std::string & str,
292  const int64_t hi, const uint64_t lo,
293  const int64_t tolerance /* = 0 */)
294 
295 {
296  std::istringstream iss;
297  iss.str (str);
298  int64x64_t value;
299  iss >> value;
300 
301  std::string input = "\"" + str + "\"";
302  uint64_t vLow = value.GetLow ();
303  bool pass = ( (value.GetHigh () == hi)
304  && ( Max (vLow, lo) - Min (vLow, lo) <= tolerance)
305  );
306 
307  std::cout << GetParent ()->GetName () << " Input: "
308  << (pass ? "pass " : "FAIL ")
309  << std::left << std::setw (28) << input << std::right
310  << Printer (value)
311  << " expected: " << Printer (hi, lo) << " +/- " << tolerance
312  << std::endl;
313 
314  NS_TEST_EXPECT_MSG_EQ (value.GetHigh (), hi,
315  "High parts do not match for input string \""
316  << str << "\"");
317  NS_TEST_EXPECT_MSG_EQ_TOL ((int64_t)value.GetLow (), (int64_t)lo, tolerance,
318  "Low parts do not match for input string \""
319  << str << "\"");
320 }
321 void
323 {
324  std::cout << std::endl;
325  std::cout << GetParent ()->GetName () << " Input: " << GetName ()
326  << std::endl;
327 
328  int64_t tolerance = 0;
330  {
331  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
332  tolerance = 2;
333  }
334 
335  Check ("1", 1, 0);
336  Check ("+1", 1, 0);
337  Check ("-1", -1, 0);
338  Check ("1.0", 1, 0);
339  Check ("+1.0", 1, 0);
340  Check ("001.0", 1, 0);
341  Check ("+001.0", 1, 0);
342  Check ("020.0", 20, 0);
343  Check ("+020.0", 20, 0);
344  Check ("1.0000000", 1, 0);
345  Check ("-1.0", -1, 0, tolerance);
346  Check ("-1.0000", -1, 0, tolerance);
347  Check (" 1.000000000000000000054", 1, 1, tolerance);
348  Check ("-1.000000000000000000054", (int64_t)-2, (uint64_t)-1, tolerance);
349 }
350 
351 
360 {
361 public:
363  virtual void DoRun (void);
369  void Check (const std::string & str,
370  const int64_t tolerance = 0);
371 };
373  : TestCase ("Roundtrip int64x64_t numbers as strings")
374 {}
375 void
376 Int64x64InputOutputTestCase::Check (const std::string & str,
377  const int64_t tolerance /* = 0 */)
378 {
379  std::stringstream iss (str);
380  int64x64_t expect;
381  iss >> expect;
382 
383  std::stringstream oss;
384  oss << std::scientific << std::setprecision (21) << expect;
385  int64x64_t value;
386  oss >> value;
387 
388  bool pass = Abs (value - expect) <= int64x64_t (0, tolerance + 1);
389 
390  std::string input = "\"" + str + "\"";
391  std::string output = "\"" + oss.str () + "\"";
392 
393  if (pass)
394  {
395  std::cout << GetParent ()->GetName () << " InputOutput: "
396  << (pass ? "pass " : "FAIL ")
397  << " in: " << std::left << std::setw (28) << input
398  << " out: " << std::left << std::setw (28) << output
399  << std::right
400  << std::endl;
401  }
402  else
403  {
404  std::cout << GetParent ()->GetName () << " InputOutput: "
405  << (pass ? "pass " : "FAIL ")
406  << " in: " << std::left << std::setw (28) << input
407  << std::right << Printer (expect)
408  << std::endl;
409  std::cout << GetParent ()->GetName ()
410  << std::setw (19) << " "
411  << " out: " << std::left << std::setw (28) << output
412  << std::right << Printer (value)
413  << std::endl;
414  }
415 
416  NS_TEST_EXPECT_MSG_EQ_TOL (value, expect, int64x64_t (0, tolerance),
417  "Converted string does not match expected string");
418 }
419 
420 void
422 {
423  std::cout << std::endl;
424  std::cout << GetParent ()->GetName () << " InputOutput: " << GetName ()
425  << std::endl;
426 
427  int64_t tolerance = 0;
429  {
430  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
431  tolerance = 1;
432  }
433 
434  Check ("+1.000000000000000000000");
435  Check ("+20.000000000000000000000");
436  Check ("+0.000000000000000000000", tolerance);
437  Check ("-1.000000000000000000000", tolerance);
438  Check ("+1.084467440737095516158", tolerance);
439  Check ("-2.084467440737095516158", tolerance);
440  Check ("+3.184467440737095516179", tolerance);
441  Check ("-4.184467440737095516179", tolerance);
442 }
443 
444 
451 {
452 public:
454  virtual void DoRun (void);
462  void Check (const int test,
463  const int64x64_t value, const int64x64_t expect,
464  const int64x64_t tolerance = int64x64_t (0,0));
465 };
466 
468  : TestCase ("Basic arithmetic operations")
469 {}
470 void
472  const int64x64_t value,
473  const int64x64_t expect,
474  const int64x64_t tolerance)
475 {
476  bool pass = Abs (value - expect) <= tolerance;
477 
478  std::cout << GetParent ()->GetName () << " Arithmetic: "
479  << (pass ? "pass " : "FAIL ")
480  << test << ": " << value << " == " << expect
481  << " (+/- " << tolerance << ")"
482  << std::endl;
483 
484  NS_TEST_ASSERT_MSG_EQ_TOL ( value, expect, tolerance,
485  "Arithmetic failure in test case " << test);
486 }
487 
488 void
490 {
491  const int64x64_t tol1 (0, 1);
492  const int64x64_t zero (0, 0);
493  const int64x64_t one (1, 0);
494  const int64x64_t two (2, 0);
495  const int64x64_t thre (3, 0);
496 
497  std::cout << std::endl;
498  std::cout << GetParent ()->GetName () << " Arithmetic: " << GetName ()
499  << std::endl;
500 
501  Check ( 0, zero - zero, zero );
502  Check ( 1, zero - one, -one );
503  Check ( 2, one - one, zero );
504  Check ( 3, one - two, -one );
505  Check ( 4, one - (-one ), two );
506  Check ( 5, (-one ) - (-two ), one );
507  Check ( 6, (-one ) - two, -thre );
508 
509  Check ( 7, zero + zero, zero );
510  Check ( 8, zero + one, one );
511  Check ( 9, one + one, two );
512  Check (10, one + two, thre );
513  Check (11, one + (-one ), zero );
514  Check (12, (-one ) + (-two ), -thre );
515  Check (13, (-one ) + two, one );
516 
517  Check (14, zero * zero, zero );
518  Check (15, zero * one, zero );
519  Check (16, zero * (-one ), zero );
520  Check (17, one * one, one );
521  Check (18, one * (-one ), -one );
522  Check (19, (-one ) * (-one ), one );
523 
524  Check (20, (two * thre ) / thre, two );
525 
526  const int64x64_t frac = int64x64_t (0, 0xc000000000000000ULL); // 0.75
527  const int64x64_t fplf2 = frac + frac * frac; // 1.3125
528 
529  Check (21, frac, 0.75);
530  Check (22, fplf2, 1.3125);
531 
532  const int64x64_t zerof = zero + frac;
533  const int64x64_t onef = one + frac;
534  const int64x64_t twof = two + frac;
535  const int64x64_t thref = thre + frac;
536 
537  Check (23, zerof, frac);
538 
539 
540  Check (24, zerof - zerof, zero );
541  Check (25, zerof - onef, -one );
542  Check (26, onef - onef, zero );
543  Check (27, onef - twof, -one );
544  Check (28, onef - (-onef), twof + frac );
545  Check (29, (-onef) - (-twof), one );
546  Check (30, (-onef) - twof, -thref - frac );
547 
548  Check (31, zerof + zerof, zerof + frac );
549  Check (32, zerof + onef, onef + frac );
550  Check (33, onef + onef, twof + frac );
551  Check (34, onef + twof, thref + frac );
552  Check (35, onef + (-onef), zero );
553  Check (36, (-onef) + (-twof), -thref - frac );
554  Check (37, (-onef) + twof, one );
555 
556  Check (38, zerof * zerof, frac * frac );
557  Check (39, zero * onef, zero );
558  Check (40, zerof * one, frac );
559 
560  Check (41, zerof * onef, fplf2 );
561  Check (42, zerof * (-onef), -fplf2 );
562  Check (43, onef * onef, onef + fplf2 );
563  Check (44, onef * (-onef), -onef - fplf2 );
564  Check (45, (-onef) * (-onef), onef + fplf2 );
565 
566 
567  // Multiplication followed by division is exact:
568  Check (46, (two * thre ) / thre, two );
569  Check (47, (twof * thref) / thref, twof );
570 
571  // Division followed by multiplication loses a bit or two:
572  Check (48, (two / thre) * thre, two, 2 * tol1 );
573  Check (49, (twof / thref) * thref, twof, 3 * tol1 );
574 
575  // The example below shows that we really do not lose
576  // much precision internally: it is almost always the
577  // final conversion which loses precision.
578  Check (50, (int64x64_t (2000000000) / int64x64_t (3)) * int64x64_t (3),
579  int64x64_t (1999999999, 0xfffffffffffffffeULL));
580 
581  // Check special values
582  Check (51, int64x64_t (0, 0x159fa87f8aeaad21ULL) * 10,
583  int64x64_t (0, 0xd83c94fb6d2ac34aULL));
584 
585 }
586 
587 
588 
597 {
598 public:
600  virtual void DoRun (void);
607  void Check (const double result, const double expect,
608  const std::string & msg);
609 };
610 
612  : TestCase ("Test case for bug 455")
613 {}
614 void
615 Int64x64Bug455TestCase::Check (const double result, const double expect,
616  const std::string & msg)
617 {
618  bool pass = result == expect;
619 
620  std::cout << GetParent ()->GetName () << " Bug 455: "
621  << (pass ? "pass " : "FAIL ")
622  << "res: " << result
623  << " exp: " << expect
624  << ": " << msg
625  << std::endl;
626 
627  NS_TEST_ASSERT_MSG_EQ (result, expect, msg);
628 }
629 
630 void
632 {
633  std::cout << std::endl;
634  std::cout << GetParent ()->GetName () << " Bug 455: " << GetName ()
635  << std::endl;
636 
637  int64x64_t a = int64x64_t (0.1);
638  a /= int64x64_t (1.25);
639  Check (a.GetDouble (), 0.08, "The original testcase");
640 
641  a = int64x64_t (0.5);
642  a *= int64x64_t (5);
643  Check (a.GetDouble (), 2.5, "Simple test for multiplication");
644 
645  a = int64x64_t (-0.5);
646  a *= int64x64_t (5);
647  Check (a.GetDouble (), -2.5, "Test sign, first operation negative");
648 
649  a = int64x64_t (-0.5);
650  a *= int64x64_t (-5);
651  Check (a.GetDouble (), 2.5, "both operands negative");
652 
653  a = int64x64_t (0.5);
654  a *= int64x64_t (-5);
655  Check (a.GetDouble (), -2.5, "only second operand negative");
656 }
657 
658 
659 
668 {
669 public:
671  virtual void DoRun (void);
678  void Check (const double result, const double expect,
679  const std::string & msg);
680 };
681 
683  : TestCase ("Test case for bug 863")
684 {}
685 void
686 Int64x64Bug863TestCase::Check (const double result, const double expect,
687  const std::string & msg)
688 {
689  bool pass = result == expect;
690 
691  std::cout << GetParent ()->GetName () << " Bug 863: "
692  << (pass ? "pass " : "FAIL ")
693  << "res: " << result
694  << " exp: " << expect
695  << ": " << msg
696  << std::endl;
697 
698  NS_TEST_ASSERT_MSG_EQ (result, expect, msg);
699 }
700 
701 void
703 {
704  std::cout << std::endl;
705  std::cout << GetParent ()->GetName () << " Bug 863: " << GetName ()
706  << std::endl;
707 
708  int64x64_t a = int64x64_t (0.9);
709  a /= int64x64_t (1);
710  Check (a.GetDouble (), 0.9, "The original testcase");
711 
712  a = int64x64_t (0.5);
713  a /= int64x64_t (0.5);
714  Check (a.GetDouble (), 1.0, "Simple test for division");
715 
716  a = int64x64_t (-0.5);
717  Check (a.GetDouble (), -0.5, "Check that we actually convert doubles correctly");
718 
719  a /= int64x64_t (0.5);
720  Check (a.GetDouble (), -1.0, "first argument negative");
721 
722  a = int64x64_t (0.5);
723  a /= int64x64_t (-0.5);
724  Check (a.GetDouble (), -1.0, "second argument negative");
725 
726  a = int64x64_t (-0.5);
727  a /= int64x64_t (-0.5);
728  Check (a.GetDouble (), 1.0, "both arguments negative");
729 }
730 
731 
740 {
741 public:
743  virtual void DoRun (void);
750  void Check (const uint64_t low, const std::string & value,
751  const int64_t tolerance = 0);
752 };
753 
755  : TestCase ("Test case for bug 1786")
756 {}
757 void
758 Int64x64Bug1786TestCase::Check (const uint64_t low,
759  const std::string & str,
760  const int64_t tolerance /* = 0 */)
761 {
762  int64x64_t value (0, low);
763  std::ostringstream oss;
764  oss << std::scientific << std::setprecision (22) << value;
765 
766  if (tolerance == 0)
767  {
768  bool pass = oss.str () == str;
769 
770  std::cout << GetParent ()->GetName () << " Bug 1786: "
771  << (pass ? "pass " : "FAIL ")
772  << " 0x" << std::hex << std::setw (16) << low << std::dec
773  << " = " << oss.str ();
774  if (!pass)
775  {
776  std::cout << ", expected " << str;
777  }
778  std::cout << std::endl;
779 
780  NS_TEST_EXPECT_MSG_EQ (oss.str (), str,
781  "Fraction string not correct");
782  }
783  else
784  {
785  // No obvious way to implement a tolerance on the strings
786 
787  std::cout << GetParent ()->GetName () << " Bug 1786: "
788  << "skip "
789  << " 0x" << std::hex << std::setw (16) << low << std::dec
790  << " = " << oss.str ()
791  << ", expected " << str
792  << std::endl;
793 
794  }
795 }
796 void
798 {
799  std::cout << std::endl;
800  std::cout << GetParent ()->GetName () << " But 1786: " << GetName ()
801  << std::endl;
802 
803  int64_t tolerance = 0;
805  {
806  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
807  tolerance = 1;
808  }
809 
810  // Some of these values differ from the DoubleTestCase
811  // by one count in the last place
812  // because operator<< truncates the last output digit,
813  // instead of rounding.
814  Check ( 1ULL, "+0.0000000000000000000542");
815  Check ( 2ULL, "+0.0000000000000000001084");
816  Check ( 3ULL, "+0.0000000000000000001626");
817  Check ( 4ULL, "+0.0000000000000000002168");
818  Check ( 5ULL, "+0.0000000000000000002710");
819  Check ( 6ULL, "+0.0000000000000000003253");
820  Check ( 7ULL, "+0.0000000000000000003795");
821  Check ( 8ULL, "+0.0000000000000000004337");
822  Check ( 9ULL, "+0.0000000000000000004879");
823  Check ( 0xAULL, "+0.0000000000000000005421");
824  Check ( 0xFULL, "+0.0000000000000000008132");
825  Check ( 0xF0ULL, "+0.0000000000000000130104");
826  Check ( 0xF00ULL, "+0.0000000000000002081668");
827  Check ( 0xF000ULL, "+0.0000000000000033306691");
828  Check ( 0xF0000ULL, "+0.0000000000000532907052");
829  Check ( 0xF00000ULL, "+0.0000000000008526512829");
830  Check ( 0xF000000ULL, "+0.0000000000136424205266");
831  Check ( 0xF0000000ULL, "+0.0000000002182787284255");
832  Check ( 0xF00000000ULL, "+0.0000000034924596548080");
833  Check ( 0xF000000000ULL, "+0.0000000558793544769287");
834  Check ( 0xF0000000000ULL, "+0.0000008940696716308594");
835  Check ( 0xF00000000000ULL, "+0.0000143051147460937500");
836  Check ( 0xF000000000000ULL, "+0.0002288818359375000000");
837  Check ( 0xF0000000000000ULL, "+0.0036621093750000000000");
838  Check ( 0xF00000000000000ULL, "+0.0585937500000000000000");
839  std::cout << std::endl;
840  Check (0x7FFFFFFFFFFFFFFDULL, "+0.4999999999999999998374", tolerance);
841  Check (0x7FFFFFFFFFFFFFFEULL, "+0.4999999999999999998916", tolerance);
842  Check (0x7FFFFFFFFFFFFFFFULL, "+0.4999999999999999999458", tolerance);
843  Check (0x8000000000000000ULL, "+0.5000000000000000000000");
844  Check (0x8000000000000001ULL, "+0.5000000000000000000542", tolerance);
845  Check (0x8000000000000002ULL, "+0.5000000000000000001084", tolerance);
846  Check (0x8000000000000003ULL, "+0.5000000000000000001626", tolerance);
847  std::cout << std::endl;
848  Check (0xF000000000000000ULL, "+0.9375000000000000000000");
849  Check (0xFF00000000000000ULL, "+0.9960937500000000000000");
850  Check (0xFFF0000000000000ULL, "+0.9997558593750000000000");
851  Check (0xFFFF000000000000ULL, "+0.9999847412109375000000");
852  Check (0xFFFFF00000000000ULL, "+0.9999990463256835937500");
853  Check (0xFFFFFF0000000000ULL, "+0.9999999403953552246094");
854  Check (0xFFFFFFF000000000ULL, "+0.9999999962747097015381");
855  Check (0xFFFFFFFF00000000ULL, "+0.9999999997671693563461");
856  Check (0xFFFFFFFFF0000000ULL, "+0.9999999999854480847716");
857  Check (0xFFFFFFFFFF000000ULL, "+0.9999999999990905052982");
858  Check (0xFFFFFFFFFFF00000ULL, "+0.9999999999999431565811");
859  Check (0xFFFFFFFFFFFF0000ULL, "+0.9999999999999964472863");
860  Check (0xFFFFFFFFFFFFF000ULL, "+0.9999999999999997779554");
861  Check (0xFFFFFFFFFFFFFF00ULL, "+0.9999999999999999861222");
862  Check (0xFFFFFFFFFFFFFFF0ULL, "+0.9999999999999999991326");
863  Check (0xFFFFFFFFFFFFFFF5ULL, "+0.9999999999999999994037", tolerance);
864  Check (0xFFFFFFFFFFFFFFF6ULL, "+0.9999999999999999994579", tolerance);
865  Check (0xFFFFFFFFFFFFFFF7ULL, "+0.9999999999999999995121", tolerance);
866  Check (0xFFFFFFFFFFFFFFF8ULL, "+0.9999999999999999995663", tolerance);
867  Check (0xFFFFFFFFFFFFFFF9ULL, "+0.9999999999999999996205", tolerance);
868  Check (0xFFFFFFFFFFFFFFFAULL, "+0.9999999999999999996747", tolerance);
869  Check (0xFFFFFFFFFFFFFFFBULL, "+0.9999999999999999997289", tolerance);
870  Check (0xFFFFFFFFFFFFFFFCULL, "+0.9999999999999999997832", tolerance);
871  Check (0xFFFFFFFFFFFFFFFDULL, "+0.9999999999999999998374", tolerance);
872  Check (0xFFFFFFFFFFFFFFFEULL, "+0.9999999999999999998916", tolerance);
873  Check (0xFFFFFFFFFFFFFFFFULL, "+0.9999999999999999999458", tolerance);
874 }
875 
876 
883 {
884 public:
886  virtual void DoRun (void);
887 
894  void Check (const bool result, const bool expect,
895  const std::string & msg);
896 };
898  : TestCase ("Basic compare operations")
899 {}
900 void
901 Int64x64CompareTestCase::Check (const bool result, const bool expect,
902  const std::string & msg)
903 {
904  bool pass = result == expect;
905 
906  std::cout << GetParent ()->GetName () << " Compare: "
907  << (pass ? "pass " : "FAIL ")
908  << msg
909  << std::endl;
910 
911  NS_TEST_ASSERT_MSG_EQ (result, expect, msg);
912 }
913 
914 void
916 {
917  std::cout << std::endl;
918  std::cout << GetParent ()->GetName () << " Compare: " << GetName ()
919  << std::endl;
920 
921  const int64x64_t zero ( 0, 0);
922  const int64x64_t one ( 1, 0);
923  const int64x64_t two ( 2, 0);
924  const int64x64_t mone (-1, 0);
925  const int64x64_t mtwo (-2, 0);
926  const int64x64_t frac = int64x64_t (0, 0xc000000000000000ULL); // 0.75
927  const int64x64_t zerof = zero + frac;
928  const int64x64_t onef = one + frac;
929  const int64x64_t monef = mone - frac;
930  const int64x64_t mtwof = mtwo - frac;
931 
932  Check ( zerof == zerof, true, "equality, zero");
933  Check ( onef == onef, true, "equality, positive");
934  Check ( mtwof == mtwof, true, "equality, negative");
935  Check ( zero == one, false, "equality false, zero");
936  Check ( one == two, false, "equality false, unsigned");
937  Check ( one == mone, false, "equality false, signed");
938  Check ( onef == one, false, "equality false, fraction");
939  std::cout << std::endl;
940 
941  Check ( zerof != zerof, false, "inequality, zero");
942  Check ( onef != onef, false, "inequality, positive");
943  Check ( mtwof != mtwof, false, "inequality, negative");
944  Check ( zero != one, true, "inequality true, zero");
945  Check ( one != two, true, "inequality true, unsigned");
946  Check ( one != mone, true, "inequality true, signed");
947  Check ( onef != one, true, "inequality true, fraction");
948  std::cout << std::endl;
949 
950  Check ( zerof < onef, true, "less, zerof");
951  Check ( zero < zerof, true, "less, zero");
952  Check ( one < onef, true, "less, positive");
953  Check ( monef < mone, true, "less, negative");
954  Check ( onef < one, false, "less, false, positive");
955  Check ( mtwo < mtwof, false, "less, false, negative");
956  std::cout << std::endl;
957 
958  Check ( zerof <= zerof, true, "less equal, equal, zerof");
959  Check ( zero <= zerof, true, "less equal, less, zero");
960  Check ( onef <= onef, true, "less equal, equal, positive");
961  Check ( monef <= mone, true, "less equal, less, negative");
962  Check ( onef <= one, false, "less equal, false, positive");
963  Check ( mtwo <= mtwof, false, "less equal, false, negative");
964  std::cout << std::endl;
965 
966  Check ( onef > zerof, true, "greater, zerof");
967  Check ( zerof > zero, true, "greater, zero");
968  Check ( onef > one, true, "greater, positive");
969  Check ( mone > monef, true, "greater, negative");
970  Check ( one > onef, false, "greater, false, positive");
971  Check ( mtwof > mtwo, false, "greater, false, negative");
972  std::cout << std::endl;
973 
974  Check ( zerof >= zerof, true, "greater equal, equal, zerof");
975  Check ( zerof >= zero, true, "greater equal, greater, zero");
976  Check ( onef >= onef, true, "greater equal, equal, positive");
977  Check ( mone >= monef, true, "greater equal, greater, negative");
978  Check ( one >= onef, false, "greater equal, false, positive");
979  Check ( mtwof >= mtwo, false, "greater equal, false, negative");
980  std::cout << std::endl;
981 
982  Check ( zero == false, true, "zero == false");
983  Check ( one == true, true, "one == true");
984  Check ( zerof != false, true, "zerof != false");
985  Check ( (!zero) == true, true, "!zero == true");
986  Check ( (!zerof) == false, true, "!zerof == false");
987  Check ( (!one) == false, true, "!one == false");
988  Check ( (+onef) == onef, true, "unary positive");
989  Check ( (-onef) == monef, true, "unary negative");
990 }
991 
992 
999 {
1000 public:
1002  virtual void DoRun (void);
1007  void Check (const int64_t factor);
1016  void CheckCase (const uint64_t factor,
1017  const int64x64_t result, const int64x64_t expect,
1018  const std::string & msg,
1019  const double tolerance = 0);
1020 };
1021 
1023  : TestCase ("Invert and MulByInvert")
1024 {}
1025 void
1026 Int64x64InvertTestCase::CheckCase (const uint64_t factor,
1027  const int64x64_t result,
1028  const int64x64_t expect,
1029  const std::string & msg,
1030  const double tolerance /* = 0 */)
1031 {
1032  bool pass = Abs (result - expect) <= tolerance;
1033 
1034  std::cout << GetParent ()->GetName () << " Invert: ";
1035 
1036  if (pass)
1037  {
1038  std::cout << "pass: " << factor << ": ";
1039 
1040  }
1041  else
1042  {
1043  std::cout << "FAIL: " << factor << ": "
1044  << "(res: " << result
1045  << " exp: " << expect
1046  << " tol: " << tolerance << ") ";
1047  }
1048  std::cout << msg
1049  << std::endl;
1050 
1051  NS_TEST_ASSERT_MSG_EQ_TOL (result, expect, int64x64_t (tolerance), msg);
1052 }
1053 
1054 void
1055 Int64x64InvertTestCase::Check (const int64_t factor)
1056 {
1057  const int64x64_t one (1, 0);
1058  const int64x64_t factorI = one / int64x64_t (factor);
1059 
1060  const int64x64_t a = int64x64_t::Invert (factor);
1061  int64x64_t b = int64x64_t (factor);
1062 
1063  double tolerance = 0;
1065  {
1066  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
1067  tolerance = 0.000000000000000001L;
1068  }
1069 
1070  b.MulByInvert (a);
1071  CheckCase (factor, b, one, "x * x^-1 == 1", tolerance);
1072 
1073  int64x64_t c = int64x64_t (1);
1074  c.MulByInvert (a);
1075  CheckCase (factor, c, factorI, "1 * x^-1 == 1 / x");
1076 
1077  int64x64_t d = int64x64_t (1);
1078  d /= (int64x64_t (factor));
1079  CheckCase (factor, d, c, "1/x == x^-1");
1080 
1081  int64x64_t e = int64x64_t (-factor);
1082  e.MulByInvert (a);
1083  CheckCase (factor, e, -one, "-x * x^-1 == -1", tolerance);
1084 }
1085 
1086 void
1088 {
1089  std::cout << std::endl;
1090  std::cout << GetParent ()->GetName () << " Invert: " << GetName ()
1091  << std::endl;
1092 
1093  Check (2);
1094  Check (3);
1095  Check (4);
1096  Check (5);
1097  Check (6);
1098  Check (10);
1099  Check (99);
1100  Check (100);
1101  Check (1000);
1102  Check (10000);
1103  Check (100000);
1104  Check (100000);
1105  Check (1000000);
1106  Check (10000000);
1107  Check (100000000);
1108  Check (1000000000);
1109  Check (10000000000LL);
1110  Check (100000000000LL);
1111  Check (1000000000000LL);
1112  Check (10000000000000LL);
1113  Check (100000000000000LL);
1114  Check (1000000000000000LL);
1115 }
1116 
1117 
1124 {
1125 public:
1127  virtual void DoRun (void);
1128 
1133  void Check (const int64_t intPart);
1141  void Check (const long double dec,
1142  const long double frac,
1143  const int64_t intPart,
1144  const uint64_t lo);
1145 
1146 private:
1147 
1165  static constexpr int MISS_MANT_DIG = std::max (0, 64 - LDBL_MANT_DIG);
1166 
1174  static constexpr long double MIN_LOW = 1 << MISS_MANT_DIG;
1175 
1190  static const long double MIN_MANT;
1191 
1192 
1193  // Member variables
1194  long double m_last;
1197 };
1198 
1199 
1200 /* static */
1201 const long double
1203  std::round ( 1e22 / std::pow (2.0L, std::min (64, LDBL_MANT_DIG))) / 1e22;
1204 
1206  : TestCase ("Construct from floating point."),
1207  m_last {0},
1208  m_deltaMax {0},
1209  m_deltaCount {0}
1210 {}
1211 
1212 void
1213 Int64x64DoubleTestCase::Check (const long double dec,
1214  const long double frac,
1215  const int64_t intPart,
1216  const uint64_t lo)
1217 {
1218  // 1. The double value we're going to convert
1219  long double value = dec + frac;
1220 
1221  // 2. The expected value of the conversion
1222  int64x64_t expect (intPart, lo);
1223 
1224  // 1a, 2a. Handle lower-precision architectures by scaling up the fractional part
1225  // We assume MISS_MANT_DIG is much less than 64, MIN_MANT much less than 0.5
1226  // Could check lo < MIN_LOW instead...
1227 
1228  /*
1229  This approach works for real values with mantissa very near zero,
1230  but isn't ideal. For values near 0.5, say, the low order bits
1231  are completely lost, since they exceed the precision of the
1232  double representation. This shows up on M1 and ARM architectures
1233  as the x.5... values all skipped, because they are indistinguishable
1234  from x.5 exactly.
1235 
1236  A more involved alternative would be to separate the
1237  "frac" and "low" values in the caller. Then the underflow
1238  rescaling could be applied to the low bits only,
1239  before adding to the frac part.
1240 
1241  To do this the signature of this function would have to be
1242  Check (cld dec, cld frac, int64_t intPart, int64_t low);
1243  ^- Note this signed
1244  The caller Check (intPart) would look like
1245 
1246  Check (v, 0.0L, intPart, 0x0LL);
1247  Check (v, 0.0L, intPart, 0x1LL);
1248  Check (v, 0.0L, intPart, 0x2LL);
1249  ...
1250  Check (v, 0.5L, intPart, -0xFLL);
1251  Check (v, 0.5L, intPart, -0xELL);
1252  ...
1253  Check (v, 0.5L, intPart, 0x0LL);
1254  Check (v, 0.5L, intPart, 0x1LL);
1255 
1256  Here we would construct value as
1257  long double lowLd = (double)low / std::pow(2.0L, 64);
1258  value = dec + frac + lowLd;
1259 
1260  For underflow cases:
1261  value = dec + frac + std::max::(lowLd, MIN_MANT);
1262  */
1263 
1264 
1265  bool under = false;
1266  if (frac && (frac < MIN_MANT))
1267  {
1268  under = true;
1269  value = dec + std::max(frac * MIN_LOW, MIN_MANT);
1270  expect = int64x64_t (intPart, lo * MIN_LOW);
1271  }
1272 
1273  // 3. The actual value of the conversion
1274  const int64x64_t result = int64x64_t (value);
1275 
1276  // 4. Absolute error in the conversion
1277  const int64x64_t delta = Abs (result - expect);
1278 
1279  // Mark repeats (no change in input floating value) as "skip" (but not integers)
1280  const bool skip = (frac && (value == m_last));
1281  // Save the value to detect unchanged values next time
1282  m_last = value;
1283 
1284  // 5. Tolerance for the test, scaled to the magnitude of value
1285  // Tolerance will be computed from the value, epsilon and margin
1286  int64x64_t tolerance;
1287 
1288  // Default epsilon
1290 
1291  // A few cases need extra tolerance
1292  // If you add cases please thoroughly document the configuration
1293  long double margin = 0;
1294 
1296  {
1297  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
1298  margin = 1.0;
1299  }
1300  if (RUNNING_ON_VALGRIND)
1301  {
1302  // Valgrind uses 64-bit doubles for long doubles
1303  // See ns-3 bug 1882
1304  // Need non-zero margin to ensure final tolerance is non-zero
1305  margin = 1.0;
1307  }
1308 
1309  // Final tolerance amount
1310  tolerance = std::max (1.0L, std::fabs (value)) * epsilon + margin * epsilon;
1311 
1312  // 6. Is the conversion acceptably close to the expected value?
1313  const bool pass = delta <= tolerance;
1314 
1315  // 7. Show the result of this check
1316 
1317  // Save stream format flags
1318  std::ios_base::fmtflags ff = std::cout.flags ();
1319  std::cout << std::fixed << std::setprecision (22);
1320 
1321  std::cout << GetParent ()->GetName () << " Double: "
1322  << (skip ? "skip " : (pass ? "pass " : "FAIL "))
1323  << std::showpos << value << " == "
1324  << Printer (result)
1325  << (under ? " (underflow)" : "")
1326  << std::endl;
1327 
1328  if ( delta )
1329  {
1330  // There was a difference, show the expected value
1331  std::cout << GetParent ()->GetName ()
1332  << std::left << std::setw (43) << " expected"
1333  << std::right << Printer (expect)
1334  << std::endl;
1335 
1336  if (delta == tolerance)
1337  {
1338  // Short form: show the delta, and note it equals the tolerance
1339  std::cout << GetParent ()->GetName ()
1340  << std::left << std::setw (43) << " delta = tolerance"
1341  << std::right << Printer (delta)
1342  << std::endl;
1343  }
1344  else
1345  {
1346  // Long form, show both delta and tolerance
1347  std::cout << GetParent ()->GetName ()
1348  << std::left << std::setw (43) << " delta"
1349  << std::right << Printer (delta)
1350  << std::endl;
1351  std::cout << GetParent ()->GetName ()
1352  << std::left << std::setw (43) << " tolerance"
1353  << std::right << Printer (tolerance)
1354  << " eps: " << epsilon << ", margin: " << margin
1355  << std::endl;
1356  }
1357 
1358  // Record number and max delta
1359  ++m_deltaCount;
1360 
1361  if ( delta > m_deltaMax )
1362  {
1363  m_deltaMax = delta;
1364  }
1365  }
1366 
1367  // Report pass/fail
1368  NS_TEST_ASSERT_MSG_EQ_TOL (result, expect, tolerance,
1369  "int64x64_t (long double) failed");
1370  std::cout.flags (ff);
1371 
1372 }
1373 
1374 void
1375 Int64x64DoubleTestCase::Check (const int64_t intPart)
1376 {
1377  std::cout << std::endl;
1378  std::cout << GetParent ()->GetName () << " Double: "
1379  << "integer: " << intPart
1380  << std::endl;
1381  // Reset last value for new intPart
1382  m_last = intPart;
1383  // Save current number and max delta, so we can report max from just this intPart
1384  int64x64_t deltaMaxPrior = m_deltaMax;
1385  m_deltaMax = 0;
1386  int deltaCountPrior = m_deltaCount;
1387  m_deltaCount = 0;
1388 
1389  // Nudging the integer part eliminates deltas around 0
1390  long double v = intPart;
1391 
1392  Check (v, 0.0L, intPart, 0x0ULL);
1393  Check (v, 0.0000000000000000000542L, intPart, 0x1ULL);
1394  Check (v, 0.0000000000000000001084L, intPart, 0x2ULL);
1395  Check (v, 0.0000000000000000001626L, intPart, 0x3ULL);
1396  Check (v, 0.0000000000000000002168L, intPart, 0x4ULL);
1397  Check (v, 0.0000000000000000002711L, intPart, 0x5ULL);
1398  Check (v, 0.0000000000000000003253L, intPart, 0x6ULL);
1399  Check (v, 0.0000000000000000003795L, intPart, 0x7ULL);
1400  Check (v, 0.0000000000000000004337L, intPart, 0x8ULL);
1401  Check (v, 0.0000000000000000004879L, intPart, 0x9ULL);
1402  Check (v, 0.0000000000000000005421L, intPart, 0xAULL);
1403  Check (v, 0.0000000000000000005963L, intPart, 0xBULL);
1404  Check (v, 0.0000000000000000006505L, intPart, 0xCULL);
1405  Check (v, 0.0000000000000000007047L, intPart, 0xDULL);
1406  Check (v, 0.0000000000000000007589L, intPart, 0xEULL);
1407  Check (v, 0.0000000000000000008132L, intPart, 0xFULL);
1408  Check (v, 0.0000000000000000130104L, intPart, 0xF0ULL);
1409  Check (v, 0.0000000000000002081668L, intPart, 0xF00ULL);
1410  Check (v, 0.0000000000000033306691L, intPart, 0xF000ULL);
1411  Check (v, 0.0000000000000532907052L, intPart, 0xF0000ULL);
1412  Check (v, 0.0000000000008526512829L, intPart, 0xF00000ULL);
1413  Check (v, 0.0000000000136424205266L, intPart, 0xF000000ULL);
1414  Check (v, 0.0000000002182787284255L, intPart, 0xF0000000ULL);
1415  Check (v, 0.0000000034924596548080L, intPart, 0xF00000000ULL);
1416  Check (v, 0.0000000558793544769287L, intPart, 0xF000000000ULL);
1417  Check (v, 0.0000008940696716308594L, intPart, 0xF0000000000ULL);
1418  Check (v, 0.0000143051147460937500L, intPart, 0xF00000000000ULL);
1419  Check (v, 0.0002288818359375000000L, intPart, 0xF000000000000ULL);
1420  Check (v, 0.0036621093750000000000L, intPart, 0xF0000000000000ULL);
1421  Check (v, 0.0585937500000000000000L, intPart, 0xF00000000000000ULL);
1422  std::cout << std::endl;
1423  Check (v, 0.4999999999999999991326L, intPart, 0x7FFFFFFFFFFFFFF0ULL);
1424  Check (v, 0.4999999999999999991868L, intPart, 0x7FFFFFFFFFFFFFF1ULL);
1425  Check (v, 0.4999999999999999992411L, intPart, 0x7FFFFFFFFFFFFFF2ULL);
1426  Check (v, 0.4999999999999999992953L, intPart, 0x7FFFFFFFFFFFFFF3ULL);
1427  Check (v, 0.4999999999999999993495L, intPart, 0x7FFFFFFFFFFFFFF4ULL);
1428  Check (v, 0.4999999999999999994037L, intPart, 0x7FFFFFFFFFFFFFF5ULL);
1429  Check (v, 0.4999999999999999994579L, intPart, 0x7FFFFFFFFFFFFFF6ULL);
1430  Check (v, 0.4999999999999999995121L, intPart, 0x7FFFFFFFFFFFFFF7ULL);
1431  Check (v, 0.4999999999999999995663L, intPart, 0x7FFFFFFFFFFFFFF8ULL);
1432  Check (v, 0.4999999999999999996205L, intPart, 0x7FFFFFFFFFFFFFF9ULL);
1433  Check (v, 0.4999999999999999996747L, intPart, 0x7FFFFFFFFFFFFFFAULL);
1434  Check (v, 0.4999999999999999997289L, intPart, 0x7FFFFFFFFFFFFFFBULL);
1435  Check (v, 0.4999999999999999997832L, intPart, 0x7FFFFFFFFFFFFFFCULL);
1436  Check (v, 0.4999999999999999998374L, intPart, 0x7FFFFFFFFFFFFFFDULL);
1437  Check (v, 0.4999999999999999998916L, intPart, 0x7FFFFFFFFFFFFFFEULL);
1438  Check (v, 0.4999999999999999999458L, intPart, 0x7FFFFFFFFFFFFFFFULL);
1439  Check (v, 0.5000000000000000000000L, intPart, 0x8000000000000000ULL);
1440  Check (v, 0.5000000000000000000542L, intPart, 0x8000000000000001ULL);
1441  Check (v, 0.5000000000000000001084L, intPart, 0x8000000000000002ULL);
1442  Check (v, 0.5000000000000000001626L, intPart, 0x8000000000000003ULL);
1443  Check (v, 0.5000000000000000002168L, intPart, 0x8000000000000004ULL);
1444  Check (v, 0.5000000000000000002711L, intPart, 0x8000000000000005ULL);
1445  Check (v, 0.5000000000000000003253L, intPart, 0x8000000000000006ULL);
1446  Check (v, 0.5000000000000000003795L, intPart, 0x8000000000000007ULL);
1447  Check (v, 0.5000000000000000004337L, intPart, 0x8000000000000008ULL);
1448  Check (v, 0.5000000000000000004879L, intPart, 0x8000000000000009ULL);
1449  Check (v, 0.5000000000000000005421L, intPart, 0x800000000000000AULL);
1450  Check (v, 0.5000000000000000005963L, intPart, 0x800000000000000BULL);
1451  Check (v, 0.5000000000000000006505L, intPart, 0x800000000000000CULL);
1452  Check (v, 0.5000000000000000007047L, intPart, 0x800000000000000DULL);
1453  Check (v, 0.5000000000000000007589L, intPart, 0x800000000000000EULL);
1454  Check (v, 0.5000000000000000008132L, intPart, 0x800000000000000FULL);
1455  std::cout << std::endl;
1456  Check (v, 0.9375000000000000000000L, intPart, 0xF000000000000000ULL);
1457  Check (v, 0.9960937500000000000000L, intPart, 0xFF00000000000000ULL);
1458  Check (v, 0.9997558593750000000000L, intPart, 0xFFF0000000000000ULL);
1459  Check (v, 0.9999847412109375000000L, intPart, 0xFFFF000000000000ULL);
1460  Check (v, 0.9999990463256835937500L, intPart, 0xFFFFF00000000000ULL);
1461  Check (v, 0.9999999403953552246094L, intPart, 0xFFFFFF0000000000ULL);
1462  Check (v, 0.9999999962747097015381L, intPart, 0xFFFFFFF000000000ULL);
1463  Check (v, 0.9999999997671693563461L, intPart, 0xFFFFFFFF00000000ULL);
1464  Check (v, 0.9999999999854480847716L, intPart, 0xFFFFFFFFF0000000ULL);
1465  Check (v, 0.9999999999990905052982L, intPart, 0xFFFFFFFFFF000000ULL);
1466  Check (v, 0.9999999999999431565811L, intPart, 0xFFFFFFFFFFF00000ULL);
1467  Check (v, 0.9999999999999964472863L, intPart, 0xFFFFFFFFFFFF0000ULL);
1468  Check (v, 0.9999999999999997779554L, intPart, 0xFFFFFFFFFFFFF000ULL);
1469  Check (v, 0.9999999999999999861222L, intPart, 0xFFFFFFFFFFFFFF00ULL);
1470  Check (v, 0.9999999999999999991326L, intPart, 0xFFFFFFFFFFFFFFF0ULL);
1471  Check (v, 0.9999999999999999991868L, intPart, 0xFFFFFFFFFFFFFFF1ULL);
1472  Check (v, 0.9999999999999999992411L, intPart, 0xFFFFFFFFFFFFFFF2ULL);
1473  Check (v, 0.9999999999999999992943L, intPart, 0xFFFFFFFFFFFFFFF3ULL);
1474  Check (v, 0.9999999999999999993495L, intPart, 0xFFFFFFFFFFFFFFF4ULL);
1475  Check (v, 0.9999999999999999994037L, intPart, 0xFFFFFFFFFFFFFFF5ULL);
1476  Check (v, 0.9999999999999999994579L, intPart, 0xFFFFFFFFFFFFFFF6ULL);
1477  Check (v, 0.9999999999999999995121L, intPart, 0xFFFFFFFFFFFFFFF7ULL);
1478  Check (v, 0.9999999999999999995663L, intPart, 0xFFFFFFFFFFFFFFF8ULL);
1479  Check (v, 0.9999999999999999996205L, intPart, 0xFFFFFFFFFFFFFFF9ULL);
1480  Check (v, 0.9999999999999999996747L, intPart, 0xFFFFFFFFFFFFFFFAULL);
1481  Check (v, 0.9999999999999999997289L, intPart, 0xFFFFFFFFFFFFFFFBULL);
1482  Check (v, 0.9999999999999999997832L, intPart, 0xFFFFFFFFFFFFFFFCULL);
1483  Check (v, 0.9999999999999999998374L, intPart, 0xFFFFFFFFFFFFFFFDULL);
1484  Check (v, 0.9999999999999999998916L, intPart, 0xFFFFFFFFFFFFFFFEULL);
1485  Check (v, 0.9999999999999999999458L, intPart, 0xFFFFFFFFFFFFFFFFULL);
1486 
1487  std::cout << GetParent ()->GetName () << " Double: "
1488  << "integer:" << std::setw (4) << intPart
1489  << ": deltas:" << std::setw (4) << m_deltaCount
1490  << ", max: " << Printer (m_deltaMax)
1491  << std::endl;
1492 
1493  // Add the count, max from this intPart to the grand totals
1494  m_deltaCount += deltaCountPrior;
1495  m_deltaMax = Max (m_deltaMax, deltaMaxPrior);
1496 }
1497 
1498 void
1500 {
1501  std::cout << std::endl;
1502  std::cout << GetParent ()->GetName () << " Double: " << GetName ()
1503  << std::endl;
1504 
1505  // Save stream format flags
1506  std::ios_base::fmtflags ff = std::cout.flags ();
1507 
1508  std::cout << GetParent ()->GetName () << " Double: "
1509  << "FLT_RADIX: " << FLT_RADIX
1510  << "\n LDBL_MANT_DIG: " << LDBL_MANT_DIG
1511  << "\n MISS_MANT_DIG: " << MISS_MANT_DIG
1512  << "\n MIN_LOW: " << Printer (MIN_LOW)
1513  << " (" << std::hexfloat << MIN_LOW << ")" << std::defaultfloat
1514  << "\n MIN_MANT: " << Printer (MIN_MANT)
1515  << std::endl;
1516 
1517  std::cout << std::scientific << std::setprecision (21);
1518 
1519  Check (-2);
1520  Check (-1);
1521  Check ( 0);
1522  Check ( 1);
1523  Check ( 2);
1524 
1525  std::cout << GetParent ()->GetName () << " Double: "
1526  << "Total deltas:" << std::setw (7) << m_deltaCount
1527  << ", max delta: " << Printer (m_deltaMax)
1528  << std::endl;
1529 
1530  std::cout.flags (ff);
1531 }
1532 
1533 
1540 {
1541 public:
1543  virtual void DoRun (void);
1544 };
1545 
1547  : TestCase ("Print the implementation")
1548 {}
1549 
1550 void
1552 {
1553  std::cout << std::endl;
1554  std::cout << GetParent ()->GetName () << " Impl: " << GetName ()
1555  << std::endl;
1556 
1557 
1558  std::cout << "int64x64_t::implementation: ";
1560  {
1561  /* *NS_CHECK_STYLE_OFF* */
1562  case (int64x64_t::int128_impl) : std::cout << "int128_impl"; break;
1563  case (int64x64_t::cairo_impl) : std::cout << "cairo_impl"; break;
1564  case (int64x64_t::ld_impl) : std::cout << "ld_impl"; break;
1565  default : std::cout << "unknown!";
1566  /* *NS_CHECK_STYLE_ON* */
1567  }
1568  std::cout << std::endl;
1569 
1570 #if defined (INT64X64_USE_CAIRO) && !defined (PYTHON_SCAN)
1571  std::cout << "cairo_impl64: " << cairo_impl64 << std::endl;
1572  std::cout << "cairo_impl128: " << cairo_impl128 << std::endl;
1573 #endif
1574 
1575  if (RUNNING_ON_VALGRIND != 0)
1576  {
1577  std::cout << "Running with valgrind" << std::endl;
1578  }
1579 
1580 }
1581 
1604 {
1605 public:
1607  : TestSuite ("int64x64", UNIT)
1608  {
1621  }
1622 };
1623 
1625 
1626 } // namespace test
1627 
1628 } // namespace int64x64
1629 
1630 } // namespace ns3
1631 
#define min(a, b)
Definition: 80211b.c:42
#define max(a, b)
Definition: 80211b.c:43
const char * cairo_impl64
Definition: cairo-wideint.c:47
const char * cairo_impl128
encapsulates test code
Definition: test.h:994
@ QUICK
Fast test.
Definition: test.h:999
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
TestCase * GetParent() const
Get the parent of this TestCsse.
Definition: test.cc:376
std::string GetName(void) const
Definition: test.cc:370
A suite of tests to run.
Definition: test.h:1188
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1197
virtual void DoRun(void)
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.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void Check(const double result, const double expect, const std::string &msg)
Check the int64x64 for correctness.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void Check(const double result, const double expect, const std::string &msg)
Check the int64x64 for correctness.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void Check(const bool result, const bool expect, const std::string &msg)
Check the int64x64 for correctness.
virtual void DoRun(void)
Implementation to actually run this TestCase.
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 Check(const int64_t intPart)
Check the int64x64 for correctness.
int m_deltaCount
The number of times a delta was recorded.
virtual void DoRun(void)
Implementation to actually run this TestCase.
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.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void Check(const int64_t hi, const uint64_t lo)
Check the high and low parts for correctness.
virtual void DoRun(void)
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.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Test: parse int64x64_t numbers as strings.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void Check(const std::string &str, const int64_t hi, const uint64_t lo, const int64_t tolerance=0)
Check the iont64x64 for correctness.
virtual void DoRun(void)
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 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.
virtual void DoRun(void)
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.
Definition: int64x64-128.h:56
@ int128_impl
Native int128_t implementation.
Definition: int64x64-128.h:88
@ ld_impl
long double implementation.
Definition: int64x64-128.h:90
@ cairo_impl
Cairo wideint implementation.
Definition: int64x64-128.h:89
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.
Definition: int64x64-128.h:94
double GetDouble(void) const
Get this value as a double.
Definition: int64x64-128.h:231
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:230
int64x64_t Abs(const int64x64_t &value)
Absolute value.
Definition: int64x64.h:205
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:218
#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:141
#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:240
#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:491
#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:323
#define HP_MAX_64
Floating point value of HP_MASK_LO + 1.
Definition: int64x64-128.h:76
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.
#define RUNNING_ON_VALGRIND
Definition: valgrind.h:5235