1 //
2 // Copyright (c) 2022 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #ifndef TEST_COMPARISONS_FP_H
18 #define TEST_COMPARISONS_FP_H
19
20 #include <map>
21 #include <memory>
22 #include <string>
23 #include <vector>
24
25 #include <CL/cl_half.h>
26
27 #include "testBase.h"
28
29 #define HALF_NAN 0x7e00
30 template <typename T> using VerifyFunc = bool (*)(const T &, const T &);
31
32 struct RelTestBase
33 {
RelTestBaseRelTestBase34 explicit RelTestBase(const ExplicitTypes &dt): dataType(dt) {}
35 virtual ~RelTestBase() = default;
36 ExplicitTypes dataType;
37 };
38
39 template <typename T> struct RelTestParams : public RelTestBase
40 {
RelTestParamsRelTestParams41 RelTestParams(const VerifyFunc<T> &vfn, const ExplicitTypes &dt,
42 const T &nan_)
43 : RelTestBase(dt), verifyFn(vfn), nan(nan_)
44 {}
45
46 VerifyFunc<T> verifyFn;
47 T nan;
48 };
49
50 struct RelationalsFPTest
51 {
52 RelationalsFPTest(cl_context context, cl_device_id device,
53 cl_command_queue queue, const char *fn, const char *op);
54
55 virtual cl_int SetUp(int elements);
56
57 // Test body returning an OpenCL error code
58 virtual cl_int Run();
59
60 template <typename T>
61 void generate_equiv_test_data(T *, unsigned int, bool,
62 const RelTestParams<T> &, const MTdata &);
63
64 template <typename T, typename U>
65 void verify_equiv_values(unsigned int, const T *const, const T *const,
66 U *const, const VerifyFunc<T> &);
67
68 template <typename T>
69 int test_equiv_kernel(unsigned int vecSize, const RelTestParams<T> ¶m,
70 const MTdata &d);
71
72 template <typename T>
73 int test_relational(int numElements, const RelTestParams<T> ¶m);
74
75 protected:
76 cl_context context;
77 cl_device_id device;
78 cl_command_queue queue;
79
80 std::string fnName;
81 std::string opName;
82
83 std::vector<std::unique_ptr<RelTestBase>> params;
84 std::map<ExplicitTypes, std::string> eqTypeNames;
85 size_t num_elements;
86
87 int halfFlushDenormsToZero;
88 };
89
90 struct IsEqualFPTest : public RelationalsFPTest
91 {
IsEqualFPTestIsEqualFPTest92 IsEqualFPTest(cl_device_id d, cl_context c, cl_command_queue q)
93 : RelationalsFPTest(c, d, q, "isequal", "==")
94 {}
95 cl_int SetUp(int elements) override;
96
97 // for correct handling nan/inf we need fp value
98 struct half_equals_to
99 {
operatorIsEqualFPTest::half_equals_to100 bool operator()(const cl_half &lhs, const cl_half &rhs) const
101 {
102 return cl_half_to_float(lhs) == cl_half_to_float(rhs);
103 }
104 };
105 };
106
107 struct IsNotEqualFPTest : public RelationalsFPTest
108 {
IsNotEqualFPTestIsNotEqualFPTest109 IsNotEqualFPTest(cl_device_id d, cl_context c, cl_command_queue q)
110 : RelationalsFPTest(c, d, q, "isnotequal", "!=")
111 {}
112 cl_int SetUp(int elements) override;
113
114 // for correct handling nan/inf we need fp value
115 struct half_not_equals_to
116 {
operatorIsNotEqualFPTest::half_not_equals_to117 bool operator()(const cl_half &lhs, const cl_half &rhs) const
118 {
119 return cl_half_to_float(lhs) != cl_half_to_float(rhs);
120 }
121 };
122 };
123
124 struct IsGreaterFPTest : public RelationalsFPTest
125 {
IsGreaterFPTestIsGreaterFPTest126 IsGreaterFPTest(cl_device_id d, cl_context c, cl_command_queue q)
127 : RelationalsFPTest(c, d, q, "isgreater", ">")
128 {}
129 cl_int SetUp(int elements) override;
130
131 struct half_greater
132 {
operatorIsGreaterFPTest::half_greater133 bool operator()(const cl_half &lhs, const cl_half &rhs) const
134 {
135 return cl_half_to_float(lhs) > cl_half_to_float(rhs);
136 }
137 };
138 };
139
140 struct IsGreaterEqualFPTest : public RelationalsFPTest
141 {
IsGreaterEqualFPTestIsGreaterEqualFPTest142 IsGreaterEqualFPTest(cl_device_id d, cl_context c, cl_command_queue q)
143 : RelationalsFPTest(c, d, q, "isgreaterequal", ">=")
144 {}
145 cl_int SetUp(int elements) override;
146
147 struct half_greater_equal
148 {
operatorIsGreaterEqualFPTest::half_greater_equal149 bool operator()(const cl_half &lhs, const cl_half &rhs) const
150 {
151 return cl_half_to_float(lhs) >= cl_half_to_float(rhs);
152 }
153 };
154 };
155
156 struct IsLessFPTest : public RelationalsFPTest
157 {
IsLessFPTestIsLessFPTest158 IsLessFPTest(cl_device_id d, cl_context c, cl_command_queue q)
159 : RelationalsFPTest(c, d, q, "isless", "<")
160 {}
161 cl_int SetUp(int elements) override;
162
163 struct half_less
164 {
operatorIsLessFPTest::half_less165 bool operator()(const cl_half &lhs, const cl_half &rhs) const
166 {
167 return cl_half_to_float(lhs) < cl_half_to_float(rhs);
168 }
169 };
170 };
171
172 struct IsLessEqualFPTest : public RelationalsFPTest
173 {
IsLessEqualFPTestIsLessEqualFPTest174 IsLessEqualFPTest(cl_device_id d, cl_context c, cl_command_queue q)
175 : RelationalsFPTest(c, d, q, "islessequal", "<=")
176 {}
177 cl_int SetUp(int elements) override;
178
179 struct half_less_equal
180 {
operatorIsLessEqualFPTest::half_less_equal181 bool operator()(const cl_half &lhs, const cl_half &rhs) const
182 {
183 return cl_half_to_float(lhs) <= cl_half_to_float(rhs);
184 }
185 };
186 };
187
188 struct IsLessGreaterFPTest : public RelationalsFPTest
189 {
IsLessGreaterFPTestIsLessGreaterFPTest190 IsLessGreaterFPTest(cl_device_id d, cl_context c, cl_command_queue q)
191 : RelationalsFPTest(c, d, q, "islessgreater", "<>")
192 {}
193 cl_int SetUp(int elements) override;
194
195 struct half_less_greater
196 {
operatorIsLessGreaterFPTest::half_less_greater197 bool operator()(const cl_half &lhs, const cl_half &rhs) const
198 {
199 float flhs = cl_half_to_float(lhs), frhs = cl_half_to_float(rhs);
200 return (flhs < frhs) || (flhs > frhs);
201 }
202 };
203
204 template <typename T> struct less_greater
205 {
operatorIsLessGreaterFPTest::less_greater206 bool operator()(const T &lhs, const T &rhs) const
207 {
208 return (lhs < rhs) || (lhs > rhs);
209 }
210 };
211 };
212
213 template <class T>
MakeAndRunTest(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)214 int MakeAndRunTest(cl_device_id device, cl_context context,
215 cl_command_queue queue, int num_elements)
216 {
217 auto test_fixture = T(device, context, queue);
218
219 cl_int error = test_fixture.SetUp(num_elements);
220 test_error_ret(error, "Error in test initialization", TEST_FAIL);
221
222 error = test_fixture.Run();
223 test_error_ret(error, "Test Failed", TEST_FAIL);
224
225 return TEST_PASS;
226 }
227
228 #endif // TEST_COMPARISONS_FP_H
229