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