A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
int64x64-test-suite.cc
Go to the documentation of this file.
1 #include "ns3/int64x64.h"
2 #include "ns3/test.h"
3 #include "ns3/valgrind.h" // Bug 1882
4 
5 #include <cmath> // fabs
6 #include <iomanip>
7 #include <limits> // numeric_limits<>::epsilon ()
8 
9 using namespace ns3;
10 
11 namespace ns3 {
12 
13  namespace int64x64 {
14 
15  namespace test {
16 
38 class Printer
39 {
40 public:
41  Printer (const int64_t high, const uint64_t low)
42  : m_haveInt (false),
43  m_value (0),
44  m_high (high),
45  m_low (low)
46  { }
47 
48  Printer (const int64x64_t value)
49  : m_haveInt (true),
50  m_value (value),
51  m_high (value.GetHigh ()),
52  m_low (value.GetLow ())
53  { }
54 
55 private:
56  friend std::ostream & operator << (std::ostream & os, const Printer & p);
57 
58  bool m_haveInt;
60  int64_t m_high;
61  uint64_t m_low;
62 };
63 
64 std::ostream & operator << (std::ostream & os, const Printer & p)
65 {
66  if (p.m_haveInt)
67  {
68  os << std::fixed << std::setprecision (22)
69  << p.m_value;
70 
71  }
72 
73  os << std::hex << std::setfill ('0')
74  << " (0x" << std::setw (16) << p.m_high
75  << " 0x" << std::setw (16) << p.m_low << ")"
76  << std::dec << std::setfill (' ');
77  return os;
78 }
79 
80 
82 {
83 public:
85  virtual void DoRun (void);
86  void Check (const int64_t hi, const uint64_t lo);
87 };
88 
90  : TestCase ("Manipulate the high and low part of every number")
91 {
92 }
93 
94 void
95 Int64x64HiLoTestCase::Check (const int64_t hi, const uint64_t lo)
96 {
97  uint64_t tolerance = 0;
99  {
100  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
101  tolerance = 1;
102  }
103 
104  int64x64_t value = int64x64_t (hi,lo);
105  uint64_t vLow = value.GetLow ();
106  bool pass = ( (value.GetHigh () == hi)
107  && ( (Max (vLow, lo) - Min (vLow, lo)) <= tolerance)
108  );
109 
110  std::cout << GetParent ()->GetName () << " Check: "
111  << (pass ? "pass " : "FAIL ")
112  << Printer (value) << " from" << Printer (hi, lo)
113  << std::endl;
114 
115  NS_TEST_EXPECT_MSG_EQ (value.GetHigh (), hi,
116  "High part does not match for hi:" << hi
117  << " lo: " << lo);
118  NS_TEST_EXPECT_MSG_EQ_TOL ((int64_t)vLow, (int64_t)lo, (int64_t)tolerance,
119  "Low part does not match for hi: " << hi
120  << " lo: " << lo);
121 }
122 
123 void
125 {
126  std::cout << std::endl;
127  std::cout << GetParent ()->GetName () << " Check: " << GetName ()
128  << std::endl;
129 
130  uint64_t low = 1;
132  {
133  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
134  low = HP_MAX_64 * std::numeric_limits<long double>::epsilon ();
135  }
136 
137  Check ( 0, 0);
138  Check ( 0, low);
139  Check ( 0, 0xffffffffffffffffULL - low);
140 
141  Check ( 1, 0);
142  Check ( 1, low);
143  Check ( 1, 0xffffffffffffffffULL - low);
144 
145  Check (-1, 0);
146  Check (-1, low);
147  Check (-1, 0xffffffffffffffffULL - low);
148 }
149 
150 
152 {
153 public:
155  virtual void DoRun (void);
156  void Check (const std::string & str,
157  const int64_t hi, const uint64_t lo,
158  const int64_t tolerance = 0);
159 };
161  : TestCase ("Parse int64x64_t numbers as strings")
162 {
163 }
164 void
165 Int64x64InputTestCase::Check (const std::string & str,
166  const int64_t hi, const uint64_t lo,
167  const int64_t tolerance /* = 0 */)
168 
169 {
170  std::istringstream iss;
171  iss.str (str);
172  int64x64_t value;
173  iss >> value;
174 
175  std::string input = "\"" + str + "\"";
176  uint64_t vLow = value.GetLow ();
177  bool pass = ( (value.GetHigh () == hi) &&
178  ( Max (vLow, lo) - Min (vLow, lo) <= tolerance)
179  );
180 
181  std::cout << GetParent ()->GetName () << " Input: "
182  << (pass ? "pass " : "FAIL ")
183  << std::left << std::setw (28) << input << std::right
184  << Printer (value)
185  << " expected: " << Printer (hi, lo) << " +/- " << tolerance
186  << std::endl;
187 
188  NS_TEST_EXPECT_MSG_EQ (value.GetHigh (), hi,
189  "High parts do not match for input string \""
190  << str << "\"");
191  NS_TEST_EXPECT_MSG_EQ_TOL ((int64_t)value.GetLow (), (int64_t)lo, tolerance,
192  "Low parts do not match for input string \""
193  << str << "\"");
194 }
195 void
197 {
198  std::cout << std::endl;
199  std::cout << GetParent ()->GetName () << " Input: " << GetName ()
200  << std::endl;
201 
202  int64_t tolerance = 0;
204  {
205  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
206  tolerance = 2;
207  }
208 
209  Check ("1", 1, 0);
210  Check ("+1", 1, 0);
211  Check ("-1", -1, 0);
212  Check ("1.0", 1, 0);
213  Check ("+1.0", 1, 0);
214  Check ("001.0", 1, 0);
215  Check ("+001.0", 1, 0);
216  Check ("020.0", 20, 0);
217  Check ("+020.0", 20, 0);
218  Check ("1.0000000", 1, 0);
219  Check ("-1.0", -1, 0, tolerance);
220  Check ("-1.0000", -1, 0, tolerance);
221  Check (" 1.000000000000000000054", 1, 1, tolerance);
222  Check ("-1.000000000000000000054", -2, -1, tolerance);
223 }
224 
225 
227 {
228 public:
230  virtual void DoRun (void);
231  void Check (const std::string & str,
232  const int64_t tolerance = 0);
233 };
235  : TestCase ("Roundtrip int64x64_t numbers as strings")
236 {
237 }
238 void
239 Int64x64InputOutputTestCase::Check (const std::string & str,
240  const int64_t tolerance /* = 0 */)
241 {
242  std::stringstream iss (str);
243  int64x64_t expect;
244  iss >> expect;
245 
246  std::stringstream oss;
247  oss << std::scientific << std::setprecision (21) << expect;
248  int64x64_t value;
249  oss >> value;
250 
251  bool pass = Abs (value - expect) <= int64x64_t (0, tolerance + 1);
252 
253  std::string input = "\"" + str + "\"";
254  std::string output = "\"" + oss.str () + "\"";
255 
256  if (pass)
257  {
258  std::cout << GetParent ()->GetName () << " InputOutput: "
259  << (pass ? "pass " : "FAIL ")
260  << " in: " << std::left << std::setw (28) << input
261  << " out: " << std::left << std::setw (28) << output
262  << std::right
263  << std::endl;
264  }
265  else
266  {
267  std::cout << GetParent ()->GetName () << " InputOutput: "
268  << (pass ? "pass " : "FAIL ")
269  << " in: " << std::left << std::setw (28) << input
270  << std::right << Printer (expect)
271  << std::endl;
272  std::cout << GetParent ()->GetName ()
273  << std::setw (19) << " "
274  << " out: " << std::left << std::setw (28) << output
275  << std::right << Printer (value)
276  << std::endl;
277  }
278 
279  NS_TEST_EXPECT_MSG_EQ_TOL (value, expect, int64x64_t (0, tolerance),
280  "Converted string does not match expected string");
281 }
282 
283 void
285 {
286  std::cout << std::endl;
287  std::cout << GetParent ()->GetName () << " InputOutput: " << GetName ()
288  << std::endl;
289 
290  int64_t tolerance = 0;
292  {
293  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
294  tolerance = 1;
295  }
296 
297  Check ("+1.000000000000000000000");
298  Check ("+20.000000000000000000000");
299  Check ("+0.000000000000000000000", tolerance);
300  Check ("-1.000000000000000000000", tolerance);
301  Check ("+1.084467440737095516158", tolerance);
302  Check ("-2.084467440737095516158", tolerance);
303  Check ("+3.184467440737095516179", tolerance);
304  Check ("-4.184467440737095516179", tolerance);
305 }
306 
307 
309 {
310 public:
312  virtual void DoRun (void);
313  void Check (const int test,
314  const int64x64_t value, const int64x64_t expect);
315  void Check (const int test,
316  const int64x64_t value, const int64x64_t expect,
317  const int64x64_t tolerance);
318 };
319 
321  : TestCase ("Basic arithmetic operations")
322 {
323 }
324 void
326  const int64x64_t value,
327  const int64x64_t expect)
328 {
329  int64x64_t zero (0,0);
330  Check (test, value, expect, zero);
331 }
332 void
334  const int64x64_t value,
335  const int64x64_t expect,
336  const int64x64_t tolerance)
337 {
338  bool pass = Abs (value - expect) <= tolerance;
339 
340  std::cout << GetParent ()->GetName () << " Arithmetic: "
341  << (pass ? "pass " : "FAIL ")
342  << test << ": " << value << " == " << expect
343  << " (+/- " << tolerance << ")"
344  << std::endl;
345 
346  NS_TEST_ASSERT_MSG_EQ_TOL ( value, expect, tolerance,
347  "Arithmetic failure in test case " << test);
348 }
349 
350 void
352 {
353  const int64x64_t tol1 (0, 1);
354  const int64x64_t zero (0, 0);
355  const int64x64_t one (1, 0);
356  const int64x64_t two (2, 0);
357  const int64x64_t thre (3, 0);
358 
359  std::cout << std::endl;
360  std::cout << GetParent ()->GetName () << " Arithmetic: " << GetName ()
361  << std::endl;
362 
363  Check ( 0, zero - zero , zero );
364  Check ( 1, zero - one , -one );
365  Check ( 2, one - one , zero );
366  Check ( 3, one - two , -one );
367  Check ( 4, one - (-one ), two );
368  Check ( 5, (-one ) - (-two ), one );
369  Check ( 6, (-one ) - two , -thre );
370 
371  Check ( 7, zero + zero , zero );
372  Check ( 8, zero + one , one );
373  Check ( 9, one + one , two );
374  Check (10, one + two , thre );
375  Check (11, one + (-one ), zero );
376  Check (12, (-one ) + (-two ), -thre );
377  Check (13, (-one ) + two , one );
378 
379  Check (14, zero * zero , zero );
380  Check (15, zero * one , zero );
381  Check (16, zero * (-one ), zero );
382  Check (17, one * one , one );
383  Check (18, one * (-one ), -one );
384  Check (19, (-one ) * (-one ), one );
385 
386  Check (20, (two * thre ) / thre , two );
387 
388  const int64x64_t frac = int64x64_t (0, 0xc000000000000000ULL); // 0.75
389  const int64x64_t fplf2 = frac + frac * frac; // 1.3125
390 
391  Check (21, frac, 0.75);
392  Check (22, fplf2, 1.3125);
393 
394  const int64x64_t zerof = zero + frac;
395  const int64x64_t onef = one + frac;
396  const int64x64_t twof = two + frac;
397  const int64x64_t thref = thre + frac;
398 
399  Check (23, zerof, frac);
400 
401 
402  Check (24, zerof - zerof, zero );
403  Check (25, zerof - onef, -one );
404  Check (26, onef - onef, zero );
405  Check (27, onef - twof, -one );
406  Check (28, onef - (-onef), twof + frac );
407  Check (29 , (-onef) - (-twof), one );
408  Check (30 , (-onef) - twof, -thref - frac );
409 
410  Check (31, zerof + zerof, zerof + frac );
411  Check (32, zerof + onef, onef + frac );
412  Check (33, onef + onef, twof + frac );
413  Check (34, onef + twof, thref + frac );
414  Check (35, onef + (-onef), zero );
415  Check (36 , (-onef) + (-twof), -thref - frac );
416  Check (37, (-onef) + twof, one );
417 
418  Check (38, zerof * zerof, frac * frac );
419  Check (39 , zero * onef, zero );
420  Check (40 , zerof * one, frac );
421 
422  Check (41, zerof * onef, fplf2 );
423  Check (42, zerof * (-onef), -fplf2 );
424  Check (43, onef * onef, onef + fplf2 );
425  Check (44, onef * (-onef), -onef - fplf2 );
426  Check (45, (-onef) * (-onef), onef + fplf2 );
427 
428 
429  // Multiplication followed by division is exact:
430  Check (46, (two * thre ) / thre , two );
431  Check (47, (twof * thref) / thref, twof );
432 
433  // Division followed by multiplication loses a bit or two:
434  Check (48, (two / thre) * thre, two , 2 * tol1 );
435  Check (49, (twof / thref) * thref, twof, 3 * tol1 );
436 
437  // The example below shows that we really do not lose
438  // much precision internally: it is almost always the
439  // final conversion which loses precision.
440  Check (50, (int64x64_t (2000000000) / int64x64_t (3)) * int64x64_t (3),
441  int64x64_t (1999999999, 0xfffffffffffffffeULL));
442 
443  // Check special values
444  Check (51, int64x64_t (0, 0x159fa87f8aeaad21ULL) * 10,
445  int64x64_t (0, 0xd83c94fb6d2ac34aULL));
446 
447 }
448 
449 
450 
455 {
456 public:
458  virtual void DoRun (void);
459  void Check (const double result, const double expect,
460  const std::string & msg);
461 };
462 
464  : TestCase ("Test case for bug 455")
465 {
466 }
467 void
468 Int64x64Bug455TestCase::Check (const double result, const double expect,
469  const std::string & msg)
470 {
471  bool pass = result == expect;
472 
473  std::cout << GetParent ()->GetName () << " Bug 455: "
474  << (pass ? "pass " : "FAIL ")
475  << "res: " << result
476  << " exp: " << expect
477  << ": " << msg
478  << std::endl;
479 
480  NS_TEST_ASSERT_MSG_EQ (result, expect, msg);
481 }
482 
483 void
485 {
486  std::cout << std::endl;
487  std::cout << GetParent ()->GetName () << " Bug 455: " << GetName ()
488  << std::endl;
489 
490  int64x64_t a = int64x64_t (0.1);
491  a /= int64x64_t (1.25);
492  Check (a.GetDouble (), 0.08, "The original testcase");
493 
494  a = int64x64_t (0.5);
495  a *= int64x64_t (5);
496  Check (a.GetDouble (), 2.5, "Simple test for multiplication");
497 
498  a = int64x64_t (-0.5);
499  a *= int64x64_t (5);
500  Check (a.GetDouble (), -2.5, "Test sign, first operation negative");
501 
502  a = int64x64_t (-0.5);
503  a *=int64x64_t (-5);
504  Check (a.GetDouble (), 2.5, "both operands negative");
505 
506  a = int64x64_t (0.5);
507  a *= int64x64_t (-5);
508  Check (a.GetDouble (), -2.5, "only second operand negative");
509 }
510 
511 
512 
517 {
518 public:
520  virtual void DoRun (void);
521  void Check (const double result, const double expect,
522  const std::string & msg);
523 };
524 
526  : TestCase ("Test case for bug 863")
527 {
528 }
529 void
530 Int64x64Bug863TestCase::Check (const double result, const double expect,
531  const std::string & msg)
532 {
533  bool pass = result == expect;
534 
535  std::cout << GetParent ()->GetName () << " Bug 863: "
536  << (pass ? "pass " : "FAIL ")
537  << "res: " << result
538  << " exp: " << expect
539  << ": " << msg
540  << std::endl;
541 
542  NS_TEST_ASSERT_MSG_EQ (result, expect, msg);
543 }
544 
545 void
547 {
548  std::cout << std::endl;
549  std::cout << GetParent ()->GetName () << " Bug 863: " << GetName ()
550  << std::endl;
551 
552  int64x64_t a = int64x64_t (0.9);
553  a /= int64x64_t (1);
554  Check (a.GetDouble (), 0.9, "The original testcase");
555 
556  a = int64x64_t (0.5);
557  a /= int64x64_t (0.5);
558  Check (a.GetDouble (), 1.0, "Simple test for division");
559 
560  a = int64x64_t (-0.5);
561  Check (a.GetDouble (), -0.5, "Check that we actually convert doubles correctly");
562 
563  a /= int64x64_t (0.5);
564  Check (a.GetDouble (), -1.0, "first argument negative");
565 
566  a = int64x64_t (0.5);
567  a /= int64x64_t (-0.5);
568  Check (a.GetDouble (), -1.0, "second argument negative");
569 
570  a = int64x64_t (-0.5);
571  a /= int64x64_t (-0.5);
572  Check (a.GetDouble (), 1.0, "both arguments negative");
573 }
574 
575 
580 {
581 public:
583  virtual void DoRun (void);
584  void Check (const uint64_t low, const std::string & value,
585  const int64_t tolerance = 0);
586 };
587 
589  : TestCase ("Test case for bug 1786")
590 {
591 }
592 void
593 Int64x64Bug1786TestCase::Check (const uint64_t low,
594  const std::string & str,
595  const int64_t tolerance /* = 0 */)
596 {
597  int64x64_t value (0, low);
598  std::ostringstream oss;
599  oss << std::scientific << std::setprecision (22) << value;
600 
601  if (tolerance == 0)
602  {
603  bool pass = oss.str () == str;
604 
605  std::cout << GetParent ()->GetName () << " Bug 1786: "
606  << (pass ? "pass " : "FAIL ")
607  << " 0x" << std::hex << std::setw (16) << low << std::dec
608  << " = " << oss.str ();
609  if (!pass)
610  {
611  std::cout << ", expected " << str;
612  }
613  std::cout << std::endl;
614 
615  NS_TEST_EXPECT_MSG_EQ (oss.str (), str,
616  "Fraction string not correct");
617  }
618  else
619  {
620  // No obvious way to implement a tolerance on the strings
621 
622  std::cout << GetParent ()->GetName () << " Bug 1786: "
623  << "skip "
624  << " 0x" << std::hex << std::setw (16) << low << std::dec
625  << " = " << oss.str ()
626  << ", expected " << str
627  << std::endl;
628 
629  }
630 }
631 void
633 {
634  std::cout << std::endl;
635  std::cout << GetParent ()->GetName () << " But 1786: " << GetName ()
636  << std::endl;
637 
638  int64_t tolerance = 0;
640  {
641  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
642  tolerance = 1;
643  }
644 
645  // Some of these values differ from the DoubleTestCase
646  // by one count in the last place
647  // because operator<< truncates the last output digit,
648  // instead of rounding.
649  Check ( 1ULL, "+0.0000000000000000000542");
650  Check ( 2ULL, "+0.0000000000000000001084");
651  Check ( 3ULL, "+0.0000000000000000001626");
652  Check ( 4ULL, "+0.0000000000000000002168");
653  Check ( 5ULL, "+0.0000000000000000002710");
654  Check ( 6ULL, "+0.0000000000000000003253");
655  Check ( 7ULL, "+0.0000000000000000003795");
656  Check ( 8ULL, "+0.0000000000000000004337");
657  Check ( 9ULL, "+0.0000000000000000004879");
658  Check ( 0xAULL, "+0.0000000000000000005421");
659  Check ( 0xFULL, "+0.0000000000000000008132");
660  Check ( 0xF0ULL, "+0.0000000000000000130104");
661  Check ( 0xF00ULL, "+0.0000000000000002081668");
662  Check ( 0xF000ULL, "+0.0000000000000033306691");
663  Check ( 0xF0000ULL, "+0.0000000000000532907052");
664  Check ( 0xF00000ULL, "+0.0000000000008526512829");
665  Check ( 0xF000000ULL, "+0.0000000000136424205266");
666  Check ( 0xF0000000ULL, "+0.0000000002182787284255");
667  Check ( 0xF00000000ULL, "+0.0000000034924596548080");
668  Check ( 0xF000000000ULL, "+0.0000000558793544769287");
669  Check ( 0xF0000000000ULL, "+0.0000008940696716308594");
670  Check ( 0xF00000000000ULL, "+0.0000143051147460937500");
671  Check ( 0xF000000000000ULL, "+0.0002288818359375000000");
672  Check ( 0xF0000000000000ULL, "+0.0036621093750000000000");
673  Check ( 0xF00000000000000ULL, "+0.0585937500000000000000");
674  std::cout << std::endl;
675  Check (0x7FFFFFFFFFFFFFFDULL, "+0.4999999999999999998374", tolerance);
676  Check (0x7FFFFFFFFFFFFFFEULL, "+0.4999999999999999998916", tolerance);
677  Check (0x7FFFFFFFFFFFFFFFULL, "+0.4999999999999999999458", tolerance);
678  Check (0x8000000000000000ULL, "+0.5000000000000000000000");
679  Check (0x8000000000000001ULL, "+0.5000000000000000000542", tolerance);
680  Check (0x8000000000000002ULL, "+0.5000000000000000001084", tolerance);
681  Check (0x8000000000000003ULL, "+0.5000000000000000001626", tolerance);
682  std::cout << std::endl;
683  Check (0xF000000000000000ULL, "+0.9375000000000000000000");
684  Check (0xFF00000000000000ULL, "+0.9960937500000000000000");
685  Check (0xFFF0000000000000ULL, "+0.9997558593750000000000");
686  Check (0xFFFF000000000000ULL, "+0.9999847412109375000000");
687  Check (0xFFFFF00000000000ULL, "+0.9999990463256835937500");
688  Check (0xFFFFFF0000000000ULL, "+0.9999999403953552246094");
689  Check (0xFFFFFFF000000000ULL, "+0.9999999962747097015381");
690  Check (0xFFFFFFFF00000000ULL, "+0.9999999997671693563461");
691  Check (0xFFFFFFFFF0000000ULL, "+0.9999999999854480847716");
692  Check (0xFFFFFFFFFF000000ULL, "+0.9999999999990905052982");
693  Check (0xFFFFFFFFFFF00000ULL, "+0.9999999999999431565811");
694  Check (0xFFFFFFFFFFFF0000ULL, "+0.9999999999999964472863");
695  Check (0xFFFFFFFFFFFFF000ULL, "+0.9999999999999997779554");
696  Check (0xFFFFFFFFFFFFFF00ULL, "+0.9999999999999999861222");
697  Check (0xFFFFFFFFFFFFFFF0ULL, "+0.9999999999999999991326");
698  Check (0xFFFFFFFFFFFFFFF5ULL, "+0.9999999999999999994037", tolerance);
699  Check (0xFFFFFFFFFFFFFFF6ULL, "+0.9999999999999999994579", tolerance);
700  Check (0xFFFFFFFFFFFFFFF7ULL, "+0.9999999999999999995121", tolerance);
701  Check (0xFFFFFFFFFFFFFFF8ULL, "+0.9999999999999999995663", tolerance);
702  Check (0xFFFFFFFFFFFFFFF9ULL, "+0.9999999999999999996205", tolerance);
703  Check (0xFFFFFFFFFFFFFFFAULL, "+0.9999999999999999996747", tolerance);
704  Check (0xFFFFFFFFFFFFFFFBULL, "+0.9999999999999999997289", tolerance);
705  Check (0xFFFFFFFFFFFFFFFCULL, "+0.9999999999999999997832", tolerance);
706  Check (0xFFFFFFFFFFFFFFFDULL, "+0.9999999999999999998374", tolerance);
707  Check (0xFFFFFFFFFFFFFFFEULL, "+0.9999999999999999998916", tolerance);
708  Check (0xFFFFFFFFFFFFFFFFULL, "+0.9999999999999999999458", tolerance);
709 }
710 
711 
713 {
714 public:
716  virtual void DoRun (void);
717 
718  void Check (const bool result, const bool expect,
719  const std::string & msg);
720 };
722  : TestCase ("Basic compare operations")
723 {
724 }
725 void
726 Int64x64CompareTestCase::Check (const bool result, const bool expect,
727  const std::string & msg)
728 {
729  bool pass = result == expect;
730 
731  std::cout << GetParent ()->GetName () << " Compare: "
732  << (pass ? "pass " : "FAIL ")
733  << msg
734  << std::endl;
735 
736  NS_TEST_ASSERT_MSG_EQ (result, expect, msg);
737 }
738 
739 void
741 {
742  std::cout << std::endl;
743  std::cout << GetParent ()->GetName () << " Compare: " << GetName ()
744  << std::endl;
745 
746  const int64x64_t zero ( 0, 0);
747  const int64x64_t one ( 1, 0);
748  const int64x64_t two ( 2, 0);
749  const int64x64_t mone (-1, 0);
750  const int64x64_t mtwo (-2, 0);
751  const int64x64_t frac = int64x64_t (0, 0xc000000000000000ULL); // 0.75
752  const int64x64_t zerof = zero + frac;
753  const int64x64_t onef = one + frac;
754  const int64x64_t monef = mone - frac;
755  const int64x64_t mtwof = mtwo - frac;
756 
757  Check ( zerof == zerof, true, "equality, zero");
758  Check ( onef == onef, true, "equality, positive");
759  Check ( mtwof == mtwof, true, "equality, negative");
760  Check ( zero == one, false, "equality false, zero");
761  Check ( one == two, false, "equality false, unsigned");
762  Check ( one == mone, false, "equality false, signed");
763  Check ( onef == one, false, "equality false, fraction");
764  std::cout << std::endl;
765 
766  Check ( zerof != zerof, false, "inequality, zero");
767  Check ( onef != onef, false, "inequality, positive");
768  Check ( mtwof != mtwof, false, "inequality, negative");
769  Check ( zero != one, true, "inequality true, zero");
770  Check ( one != two, true, "inequality true, unsigned");
771  Check ( one != mone, true, "inequality true, signed");
772  Check ( onef != one, true, "inequality true, fraction");
773  std::cout << std::endl;
774 
775  Check ( zerof < onef, true, "less, zerof");
776  Check ( zero < zerof, true, "less, zero");
777  Check ( one < onef, true, "less, positive");
778  Check ( monef < mone, true, "less, negative");
779  Check ( onef < one, false, "less, false, positive");
780  Check ( mtwo < mtwof, false, "less, false, negative");
781  std::cout << std::endl;
782 
783  Check ( zerof <= zerof, true, "less equal, equal, zerof");
784  Check ( zero <= zerof, true, "less equal, less, zero");
785  Check ( onef <= onef, true, "less equal, equal, positive");
786  Check ( monef <= mone, true, "less equal, less, negative");
787  Check ( onef <= one, false, "less equal, false, positive");
788  Check ( mtwo <= mtwof, false, "less equal, false, negative");
789  std::cout << std::endl;
790 
791  Check ( onef > zerof, true, "greater, zerof");
792  Check ( zerof > zero, true, "greater, zero");
793  Check ( onef > one, true, "greater, positive");
794  Check ( mone > monef, true, "greater, negative");
795  Check ( one > onef, false, "greater, false, positive");
796  Check ( mtwof > mtwo, false, "greater, false, negative");
797  std::cout << std::endl;
798 
799  Check ( zerof >= zerof, true, "greater equal, equal, zerof");
800  Check ( zerof >= zero, true, "greater equal, greater, zero");
801  Check ( onef >= onef, true, "greater equal, equal, positive");
802  Check ( mone >= monef, true, "greater equal, greater, negative");
803  Check ( one >= onef, false, "greater equal, false, positive");
804  Check ( mtwof >= mtwo, false, "greater equal, false, negative");
805  std::cout << std::endl;
806 
807  Check ( zero == false, true, "zero == false");
808  Check ( one == true, true, "one == true");
809  Check ( zerof != false, true, "zerof != false");
810  Check ( (!zero) == true, true, "!zero == true");
811  Check ( (!zerof) == false, true, "!zerof == false");
812  Check ( (!one) == false, true, "!one == false");
813  Check ( (+onef) == onef, true, "unary positive");
814  Check ( (-onef) == monef, true, "unary negative");
815 }
816 
817 
819 {
820 public:
822  virtual void DoRun (void);
823  void Check (const int64_t factor);
824  void CheckCase (const uint64_t factor,
825  const int64x64_t result, const int64x64_t expect,
826  const std::string & msg,
827  const double tolerance = 0);
828 };
829 
831  : TestCase ("Invert and MulByInvert")
832 {
833 }
834 void
835 Int64x64InvertTestCase::CheckCase (const uint64_t factor,
836  const int64x64_t result,
837  const int64x64_t expect,
838  const std::string & msg,
839  const double tolerance /* = 0 */)
840 {
841  bool pass = Abs (result - expect) <= tolerance;
842 
843  std::cout << GetParent ()->GetName () << " Invert: ";
844 
845  if (pass)
846  {
847  std::cout << "pass: " << factor << ": ";
848 
849  }
850  else
851  {
852  std::cout << "FAIL: " << factor << ": "
853  << "(res: " << result
854  << " exp: " << expect
855  << " tol: " << tolerance << ") ";
856  }
857  std::cout << msg
858  << std::endl;
859 
860  NS_TEST_ASSERT_MSG_EQ_TOL (result, expect, int64x64_t(tolerance), msg);
861 }
862 
863 void
864 Int64x64InvertTestCase::Check (const int64_t factor)
865 {
866  const int64x64_t one (1, 0);
867  const int64x64_t factorI = one / int64x64_t (factor);
868 
869  const int64x64_t a = int64x64_t::Invert (factor);
870  int64x64_t b = int64x64_t (factor);
871 
872  double tolerance = 0;
874  {
875  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
876  tolerance = 0.000000000000000001L;
877  }
878 
879  b.MulByInvert (a);
880  CheckCase (factor, b, one, "x * x^-1 == 1", tolerance);
881 
882  int64x64_t c = int64x64_t (1);
883  c.MulByInvert (a);
884  CheckCase (factor, c, factorI, "1 * x^-1 == 1 / x");
885 
886  int64x64_t d = int64x64_t (1);
887  d /= (int64x64_t (factor));
888  CheckCase (factor, d, c, "1/x == x^-1");
889 
890  int64x64_t e = int64x64_t (-factor);
891  e.MulByInvert (a);
892  CheckCase (factor, e, -one, "-x * x^-1 == -1", tolerance);
893 }
894 
895 void
897 {
898  std::cout << std::endl;
899  std::cout << GetParent ()->GetName () << " Invert: " << GetName ()
900  << std::endl;
901 
902  Check (2);
903  Check (3);
904  Check (4);
905  Check (5);
906  Check (6);
907  Check (10);
908  Check (99);
909  Check (100);
910  Check (1000);
911  Check (10000);
912  Check (100000);
913  Check (100000);
914  Check (1000000);
915  Check (10000000);
916  Check (100000000);
917  Check (1000000000);
918  Check (10000000000LL);
919  Check (100000000000LL);
920  Check (1000000000000LL);
921  Check (10000000000000LL);
922  Check (100000000000000LL);
923  Check (1000000000000000LL);
924 }
925 
926 
928 {
929 public:
931  virtual void DoRun (void);
932  void Check (const int64_t intPart);
933  void Check (const long double value,
934  const int64_t intPart,
935  const uint64_t lo);
936 private:
937  long double m_last;
940 };
941 
943  : TestCase ("Construct from floating point.")
944 {
945 }
946 
947 void
948 Int64x64DoubleTestCase::Check (const long double value,
949  const int64_t intPart,
950  const uint64_t lo)
951 {
952  // Construct the expected value
953  int64x64_t expect = int64x64_t (0, lo);
954  expect += intPart;
955 
956  // Actual value of conversion from double
957  const int64x64_t result = int64x64_t (value);
958 
959  // Make tolerance depend on magnitude of value
960  long double epsilon = std::numeric_limits<long double>::epsilon ();
961  long double margin = 0;
963  {
964  // Darwin 12.5.0 (Mac 10.8.5) g++ 4.2.1
965  margin = 1.0;
966  }
968  {
969  // Valgrind uses 64-bit doubles for long doubles
970  // See ns-3 bug 1882
971  // Need non-zero margin to ensure final tolerance is non-zero
972  margin = 1.0;
973  epsilon = std::numeric_limits<double>::epsilon ();
974  }
975 
976  const int64x64_t tolerance = (margin + std::fabs (value)) * epsilon;
977 
978  const int64x64_t delta = Abs (result - expect);
979  const bool skip = value == m_last;
980  const bool pass = delta <= tolerance;
981 
982  // Save stream format flags
983  std::ios_base::fmtflags ff = std::cout.flags ();
984  std::cout << std::fixed << std::setprecision (22);
985 
986  std::cout << GetParent ()->GetName () << " Double: "
987  << (skip ? "skip " : (pass ? "pass " : "FAIL "))
988  << std::showpos << value << " == "
989  << Printer (result)
990  << std::endl;
991 
992  // Log non-zero delta
993  if ( delta > int64x64_t() )
994  {
995  std::cout << GetParent ()->GetName ()
996  << std::left << std::setw (43) << " expected"
997  << std::right << Printer (expect)
998  << std::endl;
999 
1000  if (delta == tolerance)
1001  {
1002  std::cout << GetParent ()->GetName ()
1003  << std::left << std::setw (43) << " delta = tolerance"
1004  << std::right << Printer (delta)
1005  << std::endl;
1006  }
1007  else
1008  {
1009  std::cout << GetParent ()->GetName ()
1010  << std::left << std::setw (43) << " delta"
1011  << std::right << Printer (delta)
1012  << std::endl;
1013  std::cout << GetParent ()->GetName ()
1014  << std::left << std::setw (43) << " +/-"
1015  << std::right << Printer (tolerance)
1016  << std::endl;
1017  }
1018 
1019  ++m_deltaCount;
1020 
1021  if ( delta > m_deltaMax )
1022  {
1023  m_deltaMax = delta;
1024  }
1025  }
1026 
1027  NS_TEST_ASSERT_MSG_EQ_TOL (result, expect, tolerance,
1028  "int64x64_t (long double) failed");
1029  m_last = value;
1030  std::cout.flags (ff);
1031 
1032 }
1033 
1034 void
1035 Int64x64DoubleTestCase::Check (const int64_t intPart)
1036 {
1037  std::cout << std::endl;
1038  std::cout << GetParent ()->GetName () << " Double: "
1039  << "integer: " << intPart
1040  << std::endl;
1041  m_last = intPart;
1042  m_deltaCount = 0;
1043 
1044  // Nudging the integer part eliminates deltas around 0
1045  long double v = intPart;
1046 
1047  Check (v +0.0000000000000000000542L, intPart, 0x1ULL);
1048  Check (v +0.0000000000000000001084L, intPart, 0x2ULL);
1049  Check (v +0.0000000000000000001626L, intPart, 0x3ULL);
1050  Check (v +0.0000000000000000002168L, intPart, 0x4ULL);
1051  Check (v +0.0000000000000000002710L, intPart, 0x5ULL);
1052  Check (v +0.0000000000000000003253L, intPart, 0x6ULL);
1053  Check (v +0.0000000000000000003795L, intPart, 0x7ULL);
1054  Check (v +0.0000000000000000004337L, intPart, 0x8ULL);
1055  Check (v +0.0000000000000000004879L, intPart, 0x9ULL);
1056  Check (v +0.0000000000000000005421L, intPart, 0xAULL);
1057  Check (v +0.0000000000000000008132L, intPart, 0xFULL);
1058  Check (v +0.0000000000000000130104L, intPart, 0xF0ULL);
1059  Check (v +0.0000000000000002081668L, intPart, 0xF00ULL);
1060  Check (v +0.0000000000000033306691L, intPart, 0xF000ULL);
1061  Check (v +0.0000000000000532907052L, intPart, 0xF0000ULL);
1062  Check (v +0.0000000000008526512829L, intPart, 0xF00000ULL);
1063  Check (v +0.0000000000136424205266L, intPart, 0xF000000ULL);
1064  Check (v +0.0000000002182787284255L, intPart, 0xF0000000ULL);
1065  Check (v +0.0000000034924596548080L, intPart, 0xF00000000ULL);
1066  Check (v +0.0000000558793544769287L, intPart, 0xF000000000ULL);
1067  Check (v +0.0000008940696716308594L, intPart, 0xF0000000000ULL);
1068  Check (v +0.0000143051147460937500L, intPart, 0xF00000000000ULL);
1069  Check (v +0.0002288818359375000000L, intPart, 0xF000000000000ULL);
1070  Check (v +0.0036621093750000000000L, intPart, 0xF0000000000000ULL);
1071  Check (v +0.0585937500000000000000L, intPart, 0xF00000000000000ULL);
1072  std::cout << std::endl;
1073  Check (v +0.4999999999999999998374L, intPart, 0x7FFFFFFFFFFFFFFDULL);
1074  Check (v +0.4999999999999999998916L, intPart, 0x7FFFFFFFFFFFFFFEULL);
1075  Check (v +0.4999999999999999999458L, intPart, 0x7FFFFFFFFFFFFFFFULL);
1076  Check (v +0.5000000000000000000000L, intPart, 0x8000000000000000ULL);
1077  Check (v +0.5000000000000000000542L, intPart, 0x8000000000000001ULL);
1078  Check (v +0.5000000000000000001084L, intPart, 0x8000000000000002ULL);
1079  Check (v +0.5000000000000000001626L, intPart, 0x8000000000000003ULL);
1080  std::cout << std::endl;
1081  Check (v +0.9375000000000000000000L, intPart, 0xF000000000000000ULL);
1082  Check (v +0.9960937500000000000000L, intPart, 0xFF00000000000000ULL);
1083  Check (v +0.9997558593750000000000L, intPart, 0xFFF0000000000000ULL);
1084  Check (v +0.9999847412109375000000L, intPart, 0xFFFF000000000000ULL);
1085  Check (v +0.9999990463256835937500L, intPart, 0xFFFFF00000000000ULL);
1086  Check (v +0.9999999403953552246094L, intPart, 0xFFFFFF0000000000ULL);
1087  Check (v +0.9999999962747097015381L, intPart, 0xFFFFFFF000000000ULL);
1088  Check (v +0.9999999997671693563461L, intPart, 0xFFFFFFFF00000000ULL);
1089  Check (v +0.9999999999854480847716L, intPart, 0xFFFFFFFFF0000000ULL);
1090  Check (v +0.9999999999990905052982L, intPart, 0xFFFFFFFFFF000000ULL);
1091  Check (v +0.9999999999999431565811L, intPart, 0xFFFFFFFFFFF00000ULL);
1092  Check (v +0.9999999999999964472863L, intPart, 0xFFFFFFFFFFFF0000ULL);
1093  Check (v +0.9999999999999997779554L, intPart, 0xFFFFFFFFFFFFF000ULL);
1094  Check (v +0.9999999999999999861222L, intPart, 0xFFFFFFFFFFFFFF00ULL);
1095  Check (v +0.9999999999999999991326L, intPart, 0xFFFFFFFFFFFFFFF0ULL);
1096  Check (v +0.9999999999999999994037L, intPart, 0xFFFFFFFFFFFFFFF5ULL);
1097  Check (v +0.9999999999999999994579L, intPart, 0xFFFFFFFFFFFFFFF6ULL);
1098  Check (v +0.9999999999999999995121L, intPart, 0xFFFFFFFFFFFFFFF7ULL);
1099  Check (v +0.9999999999999999995663L, intPart, 0xFFFFFFFFFFFFFFF8ULL);
1100  Check (v +0.9999999999999999996205L, intPart, 0xFFFFFFFFFFFFFFF9ULL);
1101  Check (v +0.9999999999999999996747L, intPart, 0xFFFFFFFFFFFFFFFAULL);
1102  Check (v +0.9999999999999999997289L, intPart, 0xFFFFFFFFFFFFFFFBULL);
1103  Check (v +0.9999999999999999997832L, intPart, 0xFFFFFFFFFFFFFFFCULL);
1104  Check (v +0.9999999999999999998374L, intPart, 0xFFFFFFFFFFFFFFFDULL);
1105  Check (v +0.9999999999999999998916L, intPart, 0xFFFFFFFFFFFFFFFEULL);
1106  Check (v +0.9999999999999999999458L, intPart, 0xFFFFFFFFFFFFFFFFULL);
1107 
1108  std::cout << GetParent ()->GetName () << " Double: "
1109  << "integer: " << intPart
1110  << ": delta count: " << m_deltaCount
1111  << ", max: " << Printer (m_deltaMax)
1112  << std::endl;
1113 }
1114 
1115 void
1117 {
1118  std::cout << std::endl;
1119  std::cout << GetParent ()->GetName () << " Double: " << GetName ()
1120  << std::endl;
1121 
1122  // Save stream format flags
1123  std::ios_base::fmtflags ff = std::cout.flags ();
1124  std::cout << std::scientific << std::setprecision (21);
1125 
1126  m_deltaMax = int64x64_t ();
1127 
1128  std::cout << GetParent ()->GetName () << " Double: "
1129  << std::endl;
1130 
1131  Check (-2);
1132  Check (-1);
1133  Check ( 0);
1134  Check ( 1);
1135  Check ( 2);
1136 
1137  std::cout << GetParent ()->GetName () << " Double: "
1138  << "max delta: " << Printer (m_deltaMax)
1139  << std::endl;
1140 
1141  std::cout.flags (ff);
1142 }
1143 
1144 
1146 {
1147 public:
1149  virtual void DoRun (void);
1150 };
1151 
1153  : TestCase ("Print the implementation")
1154 {
1155 }
1156 
1157 void
1159 {
1160  std::cout << std::endl;
1161  std::cout << GetParent ()->GetName () << " Impl: " << GetName ()
1162  << std::endl;
1163 
1164 
1165  std::cout << "int64x64_t::implementation: ";
1167  {
1168  case (int64x64_t::int128_impl) : std::cout << "int128_impl"; break;
1169  case (int64x64_t::cairo_impl) : std::cout << "cairo_impl"; break;
1170  case (int64x64_t::ld_impl) : std::cout << "ld_impl"; break;
1171  default : std::cout << "unknown!";
1172  }
1173  std::cout << std::endl;
1174 
1175 #if defined (INT64X64_USE_CAIRO) && !defined (PYTHON_SCAN)
1176  std::cout << "cairo_impl64: " << cairo_impl64 << std::endl;
1177  std::cout << "cairo_impl128: " << cairo_impl128 << std::endl;
1178 #endif
1179 
1180  if (RUNNING_ON_VALGRIND != 0)
1181  {
1182  std::cout << "Running with valgrind" << std::endl;
1183  }
1184 
1185 }
1186 
1187 static class Int64x64TestSuite : public TestSuite
1188 {
1189 public:
1191  : TestSuite ("int64x64", UNIT)
1192  {
1204  }
1206 
1207 } // namespace test
1208 
1209 } // namespace int64x64
1210 
1211 } // namespace ns3
1212 
long double implementation
Definition: int64x64-128.h:53
virtual void DoRun(void)
Implementation to actually run this TestCase.
ns3::int64x64::test::Int64x64TestSuite g_int64x64TestSuite
uint64_t GetLow(void) const
Get the fractional portion of this value, unscaled.
Definition: int64x64-128.h:201
std::ostream & operator<<(std::ostream &os, const Printer &p)
High precision numerical type, implementing Q64.64 fixed precision.
Definition: int64x64-128.h:20
A suite of tests to run.
Definition: test.h:1105
void CheckCase(const uint64_t factor, const int64x64_t result, const int64x64_t expect, const std::string &msg, const double tolerance=0)
void Check(const double result, const double expect, const std::string &msg)
virtual void DoRun(void)
Implementation to actually run this TestCase.
void Check(const bool result, const bool expect, const std::string &msg)
const char * cairo_impl128
static int64x64_t Invert(const uint64_t v)
Compute the inverse of an integer value.
#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:265
static enum impl_type implementation
Type tag for this implementation.
Definition: int64x64-128.h:57
#define RUNNING_ON_VALGRIND
Definition: valgrind.h:5235
void MulByInvert(const int64x64_t &o)
Multiply this value by a Q0.128 value, presumably representing an inverse, completing a division oper...
Printer(const int64x64_t value)
encapsulates test code
Definition: test.h:929
double GetDouble(void) const
Get this value as a double.
Definition: int64x64-128.h:175
static double zero
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:194
void Check(const int test, const int64x64_t value, const int64x64_t expect)
virtual void DoRun(void)
Implementation to actually run this TestCase.
friend std::ostream & operator<<(std::ostream &os, const Printer &p)
virtual void DoRun(void)
Implementation to actually run this TestCase.
#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:148
void Check(const int64_t hi, const uint64_t lo)
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
Definition: int64x64.h:204
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
#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:355
#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:530
int64x64_t Abs(const int64x64_t &value)
Absolute value.
Definition: int64x64.h:183
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)
void Check(const std::string &str, const int64_t tolerance=0)
virtual void DoRun(void)
Implementation to actually run this TestCase.
TestCase * GetParent() const
Definition: test.cc:259
void AddTestCase(TestCase *testCase) NS_DEPRECATED
Add an individual child TestCase case to this TestCase.
Definition: test.cc:184
virtual void DoRun(void)
Implementation to actually run this TestCase.
Native int128_t implementation.
Definition: int64x64-128.h:51
Fast test.
Definition: test.h:937
const char * cairo_impl64
Definition: cairo-wideint.c:35
#define HP_MAX_64
Floating point value of HP_MASK_LO + 1 We really want:
Definition: int64x64-128.h:40
Printer(const int64_t high, const uint64_t low)
virtual void DoRun(void)
Implementation to actually run this TestCase.
int64_t GetHigh(void) const
Get the integer portion.
Definition: int64x64-128.h:191
void Check(const double result, const double expect, const std::string &msg)
std::string GetName(void) const
Definition: test.cc:253
EventId output
cairo wideint implementation
Definition: int64x64-128.h:52
virtual void DoRun(void)
Implementation to actually run this TestCase.
This test suite implements a Unit Test.
Definition: test.h:1115
void Check(const uint64_t low, const std::string &value, const int64_t tolerance=0)
void test(void)