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