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