1 //
2 // Copyright (c) 2017 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 #ifndef TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_TEST_FUNCS_HPP
17 #define TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_TEST_FUNCS_HPP
18
19 #include "common.hpp"
20
21 // This marco creates a class wrapper for unary test function we want to test.
22 #define DEF_UNARY_TEST_FUNC(CLASS_NAME, FUNC_NAME, HOST_FUNC_EXPRESSION) \
23 template <cl_int N /* Vector size */> \
24 struct CLASS_NAME : public unary_func< \
25 typename make_vector_type<cl_float, N>::type, /* create cl_floatN type */ \
26 typename make_vector_type<cl_int, N>::type /* create cl_intN type */ \
27 > \
28 { \
29 typedef typename make_vector_type<cl_float, N>::type input_type; \
30 typedef typename make_vector_type<cl_int, N>::type result_type; \
31 \
32 std::string str() \
33 { \
34 return #FUNC_NAME; \
35 } \
36 \
37 std::string headers() \
38 { \
39 return "#include <opencl_relational>\n"; \
40 } \
41 \
42 result_type operator()(const input_type& x) \
43 { \
44 typedef typename scalar_type<input_type>::type SCALAR; \
45 return perform_function<input_type, result_type>( \
46 x, \
47 [](const SCALAR& a) \
48 { \
49 if(HOST_FUNC_EXPRESSION) \
50 { \
51 return cl_int(1); \
52 } \
53 return cl_int(0); \
54 } \
55 ); \
56 } \
57 \
58 bool is_out_bool() \
59 { \
60 return true; \
61 } \
62 \
63 input_type min1() \
64 { \
65 return detail::def_limit<input_type>(-10000.0f); \
66 } \
67 \
68 input_type max1() \
69 { \
70 return detail::def_limit<input_type>(10000.0f); \
71 } \
72 \
73 std::vector<input_type> in1_special_cases() \
74 { \
75 typedef typename scalar_type<input_type>::type SCALAR; \
76 return { \
77 detail::make_value<input_type>(std::numeric_limits<SCALAR>::infinity()), \
78 detail::make_value<input_type>(-std::numeric_limits<SCALAR>::infinity()), \
79 detail::make_value<input_type>(std::numeric_limits<SCALAR>::quiet_NaN()), \
80 detail::make_value<input_type>(std::numeric_limits<SCALAR>::signaling_NaN()), \
81 detail::make_value<input_type>(std::numeric_limits<SCALAR>::denorm_min()), \
82 detail::make_value<input_type>(0.0f), \
83 detail::make_value<input_type>(-0.0f) \
84 }; \
85 } \
86 };
87
88 // This marco creates a class wrapper for binary test function we want to test.
89 #define DEF_BINARY_TEST_FUNC(CLASS_NAME, FUNC_NAME, HOST_FUNC_EXPRESSION) \
90 template <cl_int N /* Vector size */> \
91 struct CLASS_NAME : public binary_func< \
92 typename make_vector_type<cl_float, N>::type, /* create cl_floatN type */ \
93 typename make_vector_type<cl_float, N>::type, /* create cl_floatN type */ \
94 typename make_vector_type<cl_int, N>::type /* create cl_intN type */ \
95 > \
96 { \
97 typedef typename make_vector_type<cl_float, N>::type input_type; \
98 typedef typename make_vector_type<cl_int, N>::type result_type; \
99 \
100 std::string str() \
101 { \
102 return #FUNC_NAME; \
103 } \
104 \
105 std::string headers() \
106 { \
107 return "#include <opencl_relational>\n"; \
108 } \
109 \
110 result_type operator()(const input_type& x, const input_type& y) \
111 { \
112 typedef typename scalar_type<input_type>::type SCALAR; \
113 return perform_function<input_type, input_type, result_type>( \
114 x, y, \
115 [](const SCALAR& a, const SCALAR& b) \
116 { \
117 if(HOST_FUNC_EXPRESSION) \
118 { \
119 return cl_int(1); \
120 } \
121 return cl_int(0); \
122 } \
123 ); \
124 } \
125 \
126 bool is_out_bool() \
127 { \
128 return true; \
129 } \
130 \
131 input_type min1() \
132 { \
133 return detail::def_limit<input_type>(-10000.0f); \
134 } \
135 \
136 input_type max1() \
137 { \
138 return detail::def_limit<input_type>(10000.0f); \
139 } \
140 \
141 input_type min2() \
142 { \
143 return detail::def_limit<input_type>(-10000.0f); \
144 } \
145 \
146 input_type max2() \
147 { \
148 return detail::def_limit<input_type>(10000.0f); \
149 } \
150 \
151 std::vector<input_type> in1_special_cases() \
152 { \
153 typedef typename scalar_type<input_type>::type SCALAR; \
154 return { \
155 detail::make_value<input_type>(std::numeric_limits<SCALAR>::infinity()), \
156 detail::make_value<input_type>(-std::numeric_limits<SCALAR>::infinity()), \
157 detail::make_value<input_type>(std::numeric_limits<SCALAR>::quiet_NaN()), \
158 detail::make_value<input_type>(std::numeric_limits<SCALAR>::signaling_NaN()), \
159 detail::make_value<input_type>(std::numeric_limits<SCALAR>::denorm_min()), \
160 detail::make_value<input_type>(0.0f), \
161 detail::make_value<input_type>(-0.0f) \
162 }; \
163 } \
164 \
165 std::vector<input_type> in2_special_cases() \
166 { \
167 typedef typename scalar_type<input_type>::type SCALAR; \
168 return { \
169 detail::make_value<input_type>(std::numeric_limits<SCALAR>::infinity()), \
170 detail::make_value<input_type>(-std::numeric_limits<SCALAR>::infinity()), \
171 detail::make_value<input_type>(std::numeric_limits<SCALAR>::quiet_NaN()), \
172 detail::make_value<input_type>(std::numeric_limits<SCALAR>::signaling_NaN()), \
173 detail::make_value<input_type>(std::numeric_limits<SCALAR>::denorm_min()), \
174 detail::make_value<input_type>(0.0f), \
175 detail::make_value<input_type>(-0.0f) \
176 }; \
177 } \
178 };
179
180 DEF_UNARY_TEST_FUNC(test_func_isfinite, isfinite, (std::isfinite)(a))
181 DEF_UNARY_TEST_FUNC(test_func_isinf, isinf, (std::isinf)(a))
182 DEF_UNARY_TEST_FUNC(test_func_isnan, isnan, (std::isnan)(a))
183 DEF_UNARY_TEST_FUNC(test_func_isnormal, isnormal, (std::isnormal)(a))
184 DEF_UNARY_TEST_FUNC(test_func_signbit, signbit , (std::signbit)(a))
185
186 DEF_BINARY_TEST_FUNC(test_func_isordered, isordered, !(std::isunordered)(a, b))
187 DEF_BINARY_TEST_FUNC(test_func_isunordered, isunordered, (std::isunordered)(a, b))
188
189 #undef DEF_UNARY_TEST_FUNC
190 #undef DEF_BINARY_TEST_FUNC
191
192 template <cl_int N /* Vector size */>
193 struct test_func_all : public unary_func<
194 typename make_vector_type<cl_int, N>::type, /* create cl_intN type */
195 cl_int /* create cl_intN type */
196 >
197 {
198 typedef typename make_vector_type<cl_int, N>::type input_type;
199 typedef cl_int result_type;
200
strtest_func_all201 std::string str()
202 {
203 return "all";
204 }
205
headerstest_func_all206 std::string headers()
207 {
208 return "#include <opencl_relational>\n";
209 }
210
operator ()test_func_all211 result_type operator()(const input_type& x)
212 {
213 return perform_all_function(x);
214 }
215
is_out_booltest_func_all216 bool is_out_bool()
217 {
218 return true;
219 }
220
is_in1_booltest_func_all221 bool is_in1_bool()
222 {
223 return true;
224 }
225
in1_special_casestest_func_all226 std::vector<input_type> in1_special_cases()
227 {
228 return {
229 detail::make_value<input_type>(0),
230 detail::make_value<input_type>(1),
231 detail::make_value<input_type>(12),
232 detail::make_value<input_type>(-12)
233 };
234 }
235 };
236
237 template <cl_int N /* Vector size */>
238 struct test_func_any : public unary_func<
239 typename make_vector_type<cl_int, N>::type, /* create cl_intN type */
240 cl_int /* create cl_intN type */
241 >
242 {
243 typedef typename make_vector_type<cl_int, N>::type input_type;
244 typedef cl_int result_type;
245
strtest_func_any246 std::string str()
247 {
248 return "any";
249 }
250
headerstest_func_any251 std::string headers()
252 {
253 return "#include <opencl_relational>\n";
254 }
255
operator ()test_func_any256 result_type operator()(const input_type& x)
257 {
258 return perform_any_function(x);
259 }
260
is_out_booltest_func_any261 bool is_out_bool()
262 {
263 return true;
264 }
265
is_in1_booltest_func_any266 bool is_in1_bool()
267 {
268 return true;
269 }
270
in1_special_casestest_func_any271 std::vector<input_type> in1_special_cases()
272 {
273 return {
274 detail::make_value<input_type>(0),
275 detail::make_value<input_type>(1),
276 detail::make_value<input_type>(12),
277 detail::make_value<input_type>(-12)
278 };
279 }
280 };
281
AUTO_TEST_CASE(test_relational_test_funcs)282 AUTO_TEST_CASE(test_relational_test_funcs)
283 (cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
284 {
285 int error = CL_SUCCESS;
286 int last_error = CL_SUCCESS;
287
288 // Helper macro, so we don't have to repreat the same code.
289 #define TEST_UNARY_REL_FUNC_MACRO(CLASS_NAME) \
290 TEST_UNARY_FUNC_MACRO(CLASS_NAME<1>()) \
291 TEST_UNARY_FUNC_MACRO(CLASS_NAME<2>()) \
292 TEST_UNARY_FUNC_MACRO(CLASS_NAME<4>()) \
293 TEST_UNARY_FUNC_MACRO(CLASS_NAME<8>()) \
294 TEST_UNARY_FUNC_MACRO(CLASS_NAME<16>())
295
296 TEST_UNARY_REL_FUNC_MACRO(test_func_isfinite)
297 TEST_UNARY_REL_FUNC_MACRO(test_func_isinf)
298 TEST_UNARY_REL_FUNC_MACRO(test_func_isnan)
299 TEST_UNARY_REL_FUNC_MACRO(test_func_isnormal)
300 TEST_UNARY_REL_FUNC_MACRO(test_func_signbit)
301
302 // Tests for all(booln x) and any(booln x) are not run in USE_OPENCLC_KERNELS mode,
303 // because those functions in OpenCL C require different reference functions on host
304 // compared to their equivalents from OpenCL C++.
305 // (In OpenCL C those functions returns true/false based on the most significant bits
306 // in any/all component/s of x)
307 #ifndef USE_OPENCLC_KERNELS
308 TEST_UNARY_REL_FUNC_MACRO(test_func_all)
309 TEST_UNARY_REL_FUNC_MACRO(test_func_any)
310 #else
311 log_info("WARNING:\n\tTests for bool all(booln x) are not run in USE_OPENCLC_KERNELS mode\n");
312 log_info("WARNING:\n\tTests for bool any(booln x) are not run in USE_OPENCLC_KERNELS mode\n");
313 #endif
314
315 #undef TEST_UNARY_REL_FUNC_MACRO
316
317 #define TEST_BINARY_REL_FUNC_MACRO(CLASS_NAME) \
318 TEST_BINARY_FUNC_MACRO(CLASS_NAME<1>()) \
319 TEST_BINARY_FUNC_MACRO(CLASS_NAME<2>()) \
320 TEST_BINARY_FUNC_MACRO(CLASS_NAME<4>()) \
321 TEST_BINARY_FUNC_MACRO(CLASS_NAME<8>()) \
322 TEST_BINARY_FUNC_MACRO(CLASS_NAME<16>())
323
324 TEST_BINARY_REL_FUNC_MACRO(test_func_isordered)
325 TEST_BINARY_REL_FUNC_MACRO(test_func_isunordered)
326
327 #undef TEST_BINARY_REL_FUNC_MACRO
328
329 if(error != CL_SUCCESS)
330 {
331 return -1;
332 }
333 return error;
334 }
335
336 #endif // TEST_CONFORMANCE_CLCPP_RELATIONAL_FUNCS_TEST_FUNCS_HPP
337