1 // posit_256_5.cpp: test suite runner for fast specialized 256-bit posit<256,5>
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<256,5>
14 //#define POSIT_FAST_SPECIALIZATION   // turns on all fast specializations
15 #define POSIT_FAST_POSIT_256_5 1      // TODO: fast posit<256,5> not implemented yet
16 // second: enable posit arithmetic exceptions
17 #define POSIT_THROW_ARITHMETIC_EXCEPTION 0
18 #include <universal/number/posit/posit.hpp>
19 #include <universal/verification/posit_test_suite.hpp>
20 #include <universal/verification/posit_test_randoms.hpp>
21 
22 // Standard posits with nbits = 256 have 5 exponent bits.
23 
24 // Regression testing guards: typically set by the cmake configuration, but MANUAL_TESTING is an override
25 #define MANUAL_TESTING 0
26 // REGRESSION_LEVEL_OVERRIDE is set by the cmake file to drive a specific regression intensity
27 // It is the responsibility of the regression test to organize the tests in a quartile progression.
28 //#undef REGRESSION_LEVEL_OVERRIDE
29 #ifndef REGRESSION_LEVEL_OVERRIDE
30 #define REGRESSION_LEVEL_1 1
31 #define REGRESSION_LEVEL_2 1
32 #define REGRESSION_LEVEL_3 1
33 #define REGRESSION_LEVEL_4 1
34 #endif
35 
main()36 int main()
37 try {
38 	using namespace sw::universal;
39 
40 	// configure posit<256,5>
41 	constexpr size_t nbits = 256;
42 	constexpr size_t es = 5;
43 
44 	int nrOfFailedTestCases = 0;
45 	bool bReportIndividualTestCases = false;
46 	size_t RND_TEST_CASES = 1000;
47 	std::string tag = " posit<256,5>";
48 
49 #if POSIT_FAST_POSIT_256_5
50 	std::cout << "Fast specialization posit<256,5> configuration tests\n";
51 #else
52 	std::cout << "Standard posit<256,5> configuration tests\n";
53 #endif
54 
55 #if MANUAL_TESTING
56 
57 
58 #else
59 	posit<nbits, es> p;
60 	std::cout << dynamic_range(p) << "\n\n";
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 	RND_TEST_CASES = 1024 * 16;
95 	nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_ADD, RND_TEST_CASES), tag, "addition      ");
96 	nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_SUB, RND_TEST_CASES), tag, "subtraction   ");
97 	nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_MUL, RND_TEST_CASES), tag, "multiplication");
98 	nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_DIV, RND_TEST_CASES), tag, "division      ");
99 
100 #endif
101 
102 #if REGRESSION_LEVEL_3
103 
104 #endif
105 
106 #if REGRESSION_LEVEL_4
107 	// TODO: as we don't have a reference floating point implementation to Verify
108 	// the arithmetic operations we are going to ignore the failures
109 
110 	RND_TEST_CASES = 1024 * 1024;
111 	std::cout << "Arithmetic tests " << RND_TEST_CASES << " randoms each\n";
112 	std::cout << "Without an arithmetic reference, test failures can be ignored\n";
113 	nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_ADD, RND_TEST_CASES), tag, "addition      ");
114 	nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_SUB, RND_TEST_CASES), tag, "subtraction   ");
115 	nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_MUL, RND_TEST_CASES), tag, "multiplication");
116 	nrOfFailedTestCases += ReportTestResult(VerifyBinaryOperatorThroughRandoms<nbits, es>(bReportIndividualTestCases, OPCODE_DIV, RND_TEST_CASES), tag, "division      ");
117 	nrOfFailedTestCases = 0;
118 #endif
119 
120 #endif // MANUAL_TESTING
121 
122 	return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
123 }
124 catch (char const* msg) {
125 	std::cerr << msg << std::endl;
126 	return EXIT_SUCCESS; //as we manually throwing the not supported yet it should not fall through the cracks     EXIT_FAILURE;
127 }
128 catch (const sw::universal::posit_arithmetic_exception& err) {
129 	std::cerr << "Uncaught posit arithmetic exception: " << err.what() << std::endl;
130 	return EXIT_FAILURE;
131 }
132 catch (const sw::universal::quire_exception& err) {
133 	std::cerr << "Uncaught quire exception: " << err.what() << std::endl;
134 	return EXIT_FAILURE;
135 }
136 catch (const sw::universal::posit_internal_exception& err) {
137 	std::cerr << "Uncaught posit internal exception: " << err.what() << std::endl;
138 	return EXIT_FAILURE;
139 }
140 catch (const std::runtime_error& err) {
141 	std::cerr << "Uncaught runtime exception: " << err.what() << std::endl;
142 	return EXIT_FAILURE;
143 }
144 catch (...) {
145 	std::cerr << "Caught unknown exception" << std::endl;
146 	return EXIT_FAILURE;
147 }
148