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