1 // posit_64_3.cpp: test suite runner for fast specialized posit<64,3>
2 //
3 // Copyright (C) 2017-2021 Stillwater Supercomputing, Inc.
4 //
5 // This file is part of the universal numbers project, which is released under an MIT Open Source license.
6 #if defined(_MSC_VER)
7 #pragma warning(disable : 5045) // Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
8 #pragma warning(disable : 4514) // unreferenced inline function has been removed
9 #pragma warning(disable : 4820) // bytes padding added after data member
10 #pragma warning(disable : 4710) // function not inlined
11 #endif
12 // Configure the posit template environment
13 // first: enable fast specialized posit<64,3>
14 #define POSIT_FAST_POSIT_64_3 1 // TODO: fast posit<64,3> not implemented yet
15 // second: enable posit arithmetic exceptions
16 #define POSIT_THROW_ARITHMETIC_EXCEPTION 1
17 #include <universal/number/posit/posit.hpp>
18 #include <universal/verification/posit_test_suite.hpp>
19 #include <universal/verification/posit_test_randoms.hpp>
20
21 // Standard posit with nbits = 64 have es = 3 exponent bits.
22
23 // Regression testing guards: typically set by the cmake configuration, but MANUAL_TESTING is an override
24 #define MANUAL_TESTING 0
25 // REGRESSION_LEVEL_OVERRIDE is set by the cmake file to drive a specific regression intensity
26 // It is the responsibility of the regression test to organize the tests in a quartile progression.
27 //#undef REGRESSION_LEVEL_OVERRIDE
28 #ifndef REGRESSION_LEVEL_OVERRIDE
29 #define REGRESSION_LEVEL_1 1
30 #define REGRESSION_LEVEL_2 1
31 #define REGRESSION_LEVEL_3 1
32 #define REGRESSION_LEVEL_4 1
33 #endif
34
main()35 int main()
36 try {
37 using namespace sw::universal;
38
39 // configure a posit<64,3>
40 constexpr size_t nbits = 64;
41 constexpr size_t es = 3;
42
43 int nrOfFailedTestCases = 0;
44 bool bReportIndividualTestCases = false;
45 size_t RND_TEST_CASES = 1000;
46
47 #if POSIT_FAST_POSIT_64_3
48 std::cout << "Fast specialization posit<64,3> configuration tests\n";
49 #else
50 std::cout << "Standard posit<64,3> configuration tests\n";
51 #endif
52
53 using Scalar = posit<nbits, es>;
54 Scalar p;
55 std::cout << dynamic_range(p) << "\n\n";
56 std::string tag = type_tag(p);
57
58 #if MANUAL_TESTING
59
60 #else
61
62 #if REGRESSION_LEVEL_1
63 // special cases
64 std::cout << "Special case tests\n";
65 std::string test = "Initialize to zero: ";
66 p = 0;
67 nrOfFailedTestCases += ReportCheck(tag, test, p.iszero());
68 test = "Initialize to NAN";
69 p = NAN;
70 nrOfFailedTestCases += ReportCheck(tag, test, p.isnar());
71 test = "Initialize to INFINITY";
72 p = INFINITY;
73 nrOfFailedTestCases += ReportCheck(tag, test, p.isnar());
74 test = "sign is true";
75 p = -1.0f;
76 nrOfFailedTestCases += ReportCheck(tag, test, p.sign());
77 test = "is negative";
78 nrOfFailedTestCases += ReportCheck(tag, test, p.isneg());
79 test = "sign is false";
80 p = +1.0f;
81 nrOfFailedTestCases += ReportCheck(tag, test, !p.sign());
82 test = "is positive";
83 nrOfFailedTestCases += ReportCheck(tag, test, p.ispos());
84
85 RND_TEST_CASES = 1024;
86 nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_ADD, RND_TEST_CASES), tag, "addition ");
87 nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_SUB, RND_TEST_CASES), tag, "subtraction ");
88 nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_MUL, RND_TEST_CASES), tag, "multiplication");
89 nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_DIV, RND_TEST_CASES), tag, "division ");
90
91 #endif
92
93 #if REGRESSION_LEVEL_2
94 // logic tests
95 std::cout << "Logic operator tests\n";
96 nrOfFailedTestCases += ReportTestResult( VerifyPositLogicEqual <nbits, es>(), tag, " == (native) ");
97 nrOfFailedTestCases += ReportTestResult( VerifyPositLogicNotEqual <nbits, es>(), tag, " != (native) ");
98 nrOfFailedTestCases += ReportTestResult( VerifyPositLogicLessThan <nbits, es>(), tag, " < (native) ");
99 nrOfFailedTestCases += ReportTestResult( VerifyPositLogicLessOrEqualThan <nbits, es>(), tag, " <= (native) ");
100 nrOfFailedTestCases += ReportTestResult( VerifyPositLogicGreaterThan <nbits, es>(), tag, " > (native) ");
101 nrOfFailedTestCases += ReportTestResult( VerifyPositLogicGreaterOrEqualThan<nbits, es>(), tag, " >= (native) ");
102
103 // conversion tests
104 // internally this generators are clamped as the state space 2^33 is too big
105 std::cout << "Assignment/conversion tests\n";
106 nrOfFailedTestCases += ReportTestResult( VerifyIntegerConversion <nbits, es>(bReportIndividualTestCases), tag, "sint32 assign (native) ");
107 nrOfFailedTestCases += ReportTestResult( VerifyUintConversion <nbits, es>(bReportIndividualTestCases), tag, "uint32 assign (native) ");
108 nrOfFailedTestCases += ReportTestResult( VerifyConversion <nbits, es>(bReportIndividualTestCases), tag, "float assign (native) ");
109 // nrOfFailedTestCases += ReportTestResult( VerifyConversionThroughRandoms <nbits, es>(tag, true, 100), tag, "float assign ");
110 #endif
111
112 #if REGRESSION_LEVEL_3
113 // arithmetic tests
114 std::cout << "Arithmetic tests " << RND_TEST_CASES << " randoms each\n";
115 nrOfFailedTestCases += ReportTestResult( VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_ADD, RND_TEST_CASES), tag, "addition (native) ");
116 nrOfFailedTestCases += ReportTestResult( VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_SUB, RND_TEST_CASES), tag, "subtraction (native) ");
117 nrOfFailedTestCases += ReportTestResult( VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_MUL, RND_TEST_CASES), tag, "multiplication (native) ");
118 nrOfFailedTestCases += ReportTestResult( VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_DIV, RND_TEST_CASES), tag, "division (native) ");
119 nrOfFailedTestCases += ReportTestResult( VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_ADD, RND_TEST_CASES), tag, "+= (native) ");
120 nrOfFailedTestCases += ReportTestResult( VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_SUB, RND_TEST_CASES), tag, "-= (native) ");
121 nrOfFailedTestCases += ReportTestResult( VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_MUL, RND_TEST_CASES), tag, "*= (native) ");
122 nrOfFailedTestCases += ReportTestResult( VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_DIV, RND_TEST_CASES), tag, "/= (native) ");
123
124 #endif
125
126 #if REGRESSION_LEVEL_4
127 // elementary function tests
128 std::cout << "Elementary function tests\n";
129 p.minpos();
130 double dminpos = double(p);
131 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_SQRT, RND_TEST_CASES, dminpos), tag, "sqrt (native) ");
132 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_EXP, RND_TEST_CASES, dminpos), tag, "exp ");
133 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_EXP2, RND_TEST_CASES, dminpos), tag, "exp2 ");
134 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_LOG, RND_TEST_CASES, dminpos), tag, "log ");
135 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_LOG2, RND_TEST_CASES, dminpos), tag, "log2 ");
136 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_LOG10, RND_TEST_CASES, dminpos), tag, "log10 ");
137 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_SIN, RND_TEST_CASES, dminpos), tag, "sin ");
138 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_COS, RND_TEST_CASES, dminpos), tag, "cos ");
139 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_TAN, RND_TEST_CASES, dminpos), tag, "tan ");
140 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_ASIN, RND_TEST_CASES, dminpos), tag, "asin ");
141 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_ACOS, RND_TEST_CASES, dminpos), tag, "acos ");
142 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_ATAN, RND_TEST_CASES, dminpos), tag, "atan ");
143 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_SINH, RND_TEST_CASES, dminpos), tag, "sinh ");
144 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_COSH, RND_TEST_CASES, dminpos), tag, "cosh ");
145 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_TANH, RND_TEST_CASES, dminpos), tag, "tanh ");
146 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_ASINH, RND_TEST_CASES, dminpos), tag, "asinh ");
147 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_ACOSH, RND_TEST_CASES, dminpos), tag, "acosh ");
148 nrOfFailedTestCases += ReportTestResult( VerifyUnaryOperatorThroughRandoms<Scalar>(bReportIndividualTestCases, OPCODE_ATANH, RND_TEST_CASES, dminpos), tag, "atanh ");
149 // elementary functions with two operands
150 nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_POW, RND_TEST_CASES), tag, "pow ");
151 #endif
152
153 #endif // !MANUAL_TESTING
154
155 // TODO: as we don't have a reference floating point implementation to Verify
156 // the arithmetic operations we are going to ignore the failures
157 nrOfFailedTestCases = 0;
158 return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
159 }
160 catch (char const* msg) {
161 std::cerr << msg << std::endl;
162 return EXIT_FAILURE;
163 }
164 catch (const sw::universal::posit_arithmetic_exception& err) {
165 std::cerr << "Uncaught posit arithmetic exception: " << err.what() << std::endl;
166 return EXIT_FAILURE;
167 }
168 catch (const sw::universal::quire_exception& err) {
169 std::cerr << "Uncaught quire exception: " << err.what() << std::endl;
170 return EXIT_FAILURE;
171 }
172 catch (const sw::universal::posit_internal_exception& err) {
173 std::cerr << "Uncaught posit internal exception: " << err.what() << std::endl;
174 return EXIT_FAILURE;
175 }
176 catch (const std::runtime_error& err) {
177 std::cerr << "Uncaught runtime exception: " << err.what() << std::endl;
178 return EXIT_FAILURE;
179 }
180 catch (...) {
181 std::cerr << "Caught unknown exception" << std::endl;
182 return EXIT_FAILURE;
183 }
184