1 #pragma once
2 // test_reporters.hpp : test result reporters to guide verification
3 //
4 // Copyright (C) 2017-2021 Stillwater Supercomputing, Inc.
5 //
6 // This file is part of the universal numbers project, which is released under an MIT Open Source license.
7 #include <iostream>
8 #include <iomanip>
9 #include <typeinfo>
10 #include <limits>
11 #include <complex>
12 #include <universal/math/complex_manipulators.hpp>
13 
14 // NOTE: reporters write to cerr
15 
16 namespace sw::universal {
17 
18 #define NUMBER_COLUMN_WIDTH 20
19 
20 // ReportTestSuiteResult prints to std::cerr whether or not the test suite passed or failed
ReportTestSuiteResults(const std::string & test_suite,int nrOfFailedTestCases)21 void ReportTestSuiteResults(const std::string& test_suite, int nrOfFailedTestCases) {
22 	std::cerr << test_suite <<  (nrOfFailedTestCases == 0 ? ": PASS" : ": FAIL") << '\n';
23 }
24 
25 template<typename TestType>
ReportConversionError(const std::string & test_case,const std::string & op,double input,double reference,const TestType & result)26 void ReportConversionError(const std::string& test_case, const std::string& op, double input, double reference, const TestType& result) {
27 	constexpr size_t nbits = TestType::nbits;  // number system concept requires a static member indicating its size in bits
28 	auto old_precision = std::cerr.precision();
29 	std::cerr << std::setprecision(10);
30 	std::cerr << test_case
31 		<< " " << op << " "
32 		<< std::setw(NUMBER_COLUMN_WIDTH) << input
33 		<< " did not convert to "
34 		<< std::setw(NUMBER_COLUMN_WIDTH) << reference << " instead it yielded  "
35 		<< std::setw(NUMBER_COLUMN_WIDTH) << double(result)
36 		<< "  raw " << std::setw(nbits) << to_binary(result);
37 	std::cerr << '\n';
38 	std::cerr << std::setprecision(old_precision);
39 }
40 
41 template<typename TestType>
ReportConversionSuccess(const std::string & test_case,const std::string & op,double input,double reference,const TestType & result)42 void ReportConversionSuccess(const std::string& test_case, const std::string& op, double input, double reference, const TestType& result) {
43 	constexpr size_t nbits = TestType::nbits;  // number system concept requires a static member indicating its size in bits
44 	std::cerr << test_case
45 		<< " " << op << " "
46 		<< std::setw(NUMBER_COLUMN_WIDTH) << input
47 		<< " success            "
48 		<< std::setw(NUMBER_COLUMN_WIDTH) << result << " golden reference is "
49 		<< std::setw(NUMBER_COLUMN_WIDTH) << reference
50 		<< "  raw " << std::setw(nbits) << to_binary(result)
51 		<< '\n';
52 }
53 
54 template<typename TestType>
ReportUnaryArithmeticError(const std::string & test_case,const std::string & op,const TestType & argument,const TestType & result,const TestType & ref)55 void ReportUnaryArithmeticError(const std::string& test_case, const std::string& op, const TestType& argument, const TestType& result, const TestType& ref) {
56 	auto old_precision = std::cerr.precision();
57 	std::cerr << test_case << " "
58 		<< " " << op << " "
59 		<< std::setprecision(20)
60 		<< std::setw(NUMBER_COLUMN_WIDTH) << argument
61 		<< " != "
62 		<< std::setw(NUMBER_COLUMN_WIDTH) << ref << " instead it yielded "
63 		<< std::setw(NUMBER_COLUMN_WIDTH) << result
64 		<< " " << to_binary(ref) << " vs " << to_binary(result)
65 		<< std::setprecision(old_precision)
66 		<< '\n';
67 }
68 
69 template<typename TestType>
ReportUnaryArithmeticSucces(const std::string & test_case,const std::string & op,const TestType & argument,const TestType & result,const TestType & ref)70 void ReportUnaryArithmeticSucces(const std::string& test_case, const std::string& op, const TestType& argument, const TestType& result, const TestType& ref) {
71 	auto old_precision = std::cerr.precision();
72 	std::cerr << test_case << " "
73 		<< " " << op << " "
74 		<< std::setprecision(20)
75 		<< std::setw(NUMBER_COLUMN_WIDTH) << argument
76 		<< " == "
77 		<< std::setw(NUMBER_COLUMN_WIDTH) << result << " reference value is "
78 		<< std::setw(NUMBER_COLUMN_WIDTH) << ref
79 		<< std::setprecision(old_precision)
80 		<< '\n';
81 }
82 
83 template<typename InputType, typename ResultType, typename RefType>
ReportBinaryArithmeticError(const std::string & test_case,const std::string & op,const InputType & lhs,const InputType & rhs,const ResultType & result,const RefType & ref)84 void ReportBinaryArithmeticError(const std::string& test_case, const std::string& op,
85 	const InputType& lhs, const InputType& rhs, const ResultType& result, const RefType& ref) {
86 	using namespace sw::universal;
87 	auto old_precision = std::cerr.precision();
88 	std::cerr << test_case << " "
89 		<< std::setprecision(20)
90 		<< std::setw(NUMBER_COLUMN_WIDTH) << lhs
91 		<< " " << op << " "
92 		<< std::setw(NUMBER_COLUMN_WIDTH) << rhs
93 		<< " != "
94 		<< std::setw(NUMBER_COLUMN_WIDTH) << result << " golden reference is "
95 		<< std::setw(NUMBER_COLUMN_WIDTH) << ref
96 		<< '\n'
97 		<< " result " << to_binary(result)
98 		<< "\n vs ref " << to_binary(ref)
99 		<< '\n'
100 		<< to_binary(lhs)
101 		<< " " << op << " "
102 		<< to_binary(rhs)
103 		<< std::setprecision(old_precision)
104 		<< '\n';
105 }
106 
107 template<typename TestType, typename ResultType, typename RefType>
ReportBinaryArithmeticSuccess(const std::string & test_case,const std::string & op,const TestType & lhs,const TestType & rhs,const ResultType & result,const RefType & ref)108 void ReportBinaryArithmeticSuccess(const std::string& test_case, const std::string& op, const TestType& lhs, const TestType& rhs, const ResultType& result, const RefType& ref) {
109 	auto old_precision = std::cerr.precision();
110 	std::cerr << test_case << " "
111 		<< std::setprecision(20)
112 		<< std::setw(NUMBER_COLUMN_WIDTH) << lhs
113 		<< " " << op << " "
114 		<< std::setw(NUMBER_COLUMN_WIDTH) << rhs
115 		<< " == "
116 		<< std::setw(NUMBER_COLUMN_WIDTH) << result << " matches reference "
117 		<< std::setw(NUMBER_COLUMN_WIDTH) << ref
118 		<< " " << to_binary(result) << " vs " << to_binary(ref)
119 		<< std::setprecision(old_precision)
120 		<< '\n';
121 }
122 
123 /// <summary>
124 /// report an assignment error by comparing the input to the result and the golden reference
125 /// </summary>
126 /// <typeparam name="MarshallType"></typeparam>
127 /// <typeparam name="TestType"></typeparam>
128 /// <typeparam name="RefType"></typeparam>
129 /// <param name="test_case">string indicating the test</param>
130 /// <param name="op">string indicating the operator</param>
131 /// <param name="input">the input value to the assignment</param>
132 /// <param name="result">the result of the assignment operator</param>
133 /// <param name="ref">the golden reference for this assignment operator</param>
134 template<typename MarshallType, typename TestType, typename RefType>
ReportAssignmentError(const std::string & test_case,const std::string & op,const MarshallType & input,const TestType & result,const RefType & ref)135 void ReportAssignmentError(const std::string& test_case, const std::string& op, const MarshallType& input, const TestType& result, const RefType& ref) {
136 	std::cerr << test_case
137 		<< " " << op << " "
138 		<< std::setw(NUMBER_COLUMN_WIDTH) << input
139 		<< " != "
140 		<< std::setw(NUMBER_COLUMN_WIDTH) << result << " golden reference is "
141 		<< std::setw(NUMBER_COLUMN_WIDTH) << ref
142 		<< " " << to_binary(result) << " vs " << to_binary(ref) << '\n';
143 }
144 
145 /// <summary>
146 /// report an assignment success by comparing the input to the result and the golden reference
147 /// </summary>
148 /// <typeparam name="MarshallType"></typeparam>
149 /// <typeparam name="TestType"></typeparam>
150 /// <typeparam name="RefType"></typeparam>
151 /// <param name="test_case">string indicating the test</param>
152 /// <param name="op">string indicating the operator</param>
153 /// <param name="input">the input value to the assignment</param>
154 /// <param name="result">the result of the assignment operator</param>
155 /// <param name="ref">the golden reference for this assignment operator</param>
156 template<typename MarshallType, typename TestType, typename RefType>
ReportAssignmentSuccess(const std::string & test_case,const std::string & op,const MarshallType & input,const TestType & result,const RefType & ref)157 void ReportAssignmentSuccess(const std::string& test_case, const std::string& op, const MarshallType& input, const TestType& result, const RefType& ref) {
158 	std::cerr << test_case
159 		<< " " << op << " "
160 		<< std::setw(NUMBER_COLUMN_WIDTH) << input
161 		<< " == "
162 		<< std::setw(NUMBER_COLUMN_WIDTH) << result << " reference value is "
163 		<< std::setw(NUMBER_COLUMN_WIDTH) << ref
164 		<< "               bit pattern " << to_binary(result) << '\n';
165 }
166 
167 template<typename TestType>
ReportOneInputFunctionError(const std::string & test_case,const std::string & op,const TestType & rhs,const TestType & reference,const TestType & result)168 void ReportOneInputFunctionError(const std::string& test_case, const std::string& op, const TestType& rhs, const TestType& reference, const TestType& result) {
169 	std::cerr << test_case
170 		<< " " << op << " "
171 		<< std::setw(NUMBER_COLUMN_WIDTH) << rhs
172 		<< " != "
173 		<< std::setw(NUMBER_COLUMN_WIDTH) << reference << " instead it yielded "
174 		<< std::setw(NUMBER_COLUMN_WIDTH) << result
175 		<< " " << to_binary(reference) << " vs " << to_binary(result) << '\n';
176 }
177 
178 template<typename TestType>
ReportOneInputFunctionSuccess(const std::string & test_case,const std::string & op,const TestType & rhs,const TestType & reference,const TestType & result)179 void ReportOneInputFunctionSuccess(const std::string& test_case, const std::string& op, const TestType& rhs, const TestType& reference, const TestType& result) {
180 	std::cerr << test_case
181 		<< " " << op << " "
182 		<< std::setw(NUMBER_COLUMN_WIDTH) << rhs
183 		<< " == "
184 		<< std::setw(NUMBER_COLUMN_WIDTH) << result << " reference value is "
185 		<< std::setw(NUMBER_COLUMN_WIDTH) << reference
186 		<< " " << components_to_string(result) << '\n';
187 }
188 
189 template<typename TestType>
ReportTwoInputFunctionError(const std::string & test_case,const std::string & op,const TestType & a,const TestType & b,const TestType & reference,const TestType & result)190 void ReportTwoInputFunctionError(const std::string& test_case, const std::string& op, const TestType& a, const TestType& b, const TestType& reference, const TestType& result) {
191 	auto precision = std::cerr.precision();
192 	std::cerr << test_case << " " << op << "("
193 		<< std::setprecision(20)
194 		<< std::setw(NUMBER_COLUMN_WIDTH) << a
195 		<< ","
196 		<< std::setw(NUMBER_COLUMN_WIDTH) << b << ")"
197 		<< " != "
198 		<< std::setw(NUMBER_COLUMN_WIDTH) << reference << " instead it yielded "
199 		<< std::setw(NUMBER_COLUMN_WIDTH) << result
200 		<< " " << reference << " vs " << result
201 		<< std::setprecision(precision)
202 		<< '\n';
203 }
204 
205 template<typename TestType>
ReportTwoInputFunctionSuccess(const std::string & test_case,const std::string & op,const TestType & a,const TestType & b,const TestType & reference,const TestType & result)206 void ReportTwoInputFunctionSuccess(const std::string& test_case, const std::string& op, const TestType& a, const TestType& b, const TestType& reference, const TestType& result) {
207 	auto precision = std::cerr.precision();
208 	std::cerr << test_case << " " << op << "("
209 		<< std::setprecision(20)
210 		<< std::setw(NUMBER_COLUMN_WIDTH) << a
211 		<< ","
212 		<< std::setw(NUMBER_COLUMN_WIDTH) << b << ")"
213 		<< " == "
214 		<< std::setw(NUMBER_COLUMN_WIDTH) << reference << " ==  "
215 		<< std::setw(NUMBER_COLUMN_WIDTH) << result
216 		<< " " << reference << " vs " << result
217 		<< std::setprecision(precision)
218 		<< '\n';
219 }
220 
221 } // namespace sw::universal
222