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