• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_UTILS_TEST_COMPARE_HPP
17 #define TEST_CONFORMANCE_CLCPP_UTILS_TEST_COMPARE_HPP
18 
19 #include <random>
20 #include <limits>
21 #include <type_traits>
22 #include <algorithm>
23 
24 #include <cmath>
25 
26 #include "../common.hpp"
27 
28 // Checks if x is equal to y.
29 template<class type, class delta_type, class op_type>
are_equal(const type & x,const type & y,const delta_type & delta,op_type op,typename std::enable_if<is_vector_type<type>::value && std::is_integral<typename scalar_type<type>::type>::value>::type * =0)30 inline bool are_equal(const type& x,
31                       const type& y,
32                       const delta_type& delta,
33                       op_type op,
34                       typename std::enable_if<
35                         is_vector_type<type>::value
36                         && std::is_integral<typename scalar_type<type>::type>::value
37                       >::type* = 0)
38 {
39     (void) delta;
40     for(size_t i = 0; i < vector_size<type>::value; i++)
41     {
42         if(op.is_out_bool())
43         {
44             if(!((x.s[i] != 0) == (y.s[i] != 0)))
45             {
46                 return false;
47             }
48         }
49         else if(!(x.s[i] == y.s[i]))
50         {
51             return false;
52         }
53     }
54     return true;
55 }
56 
57 template<class type, class delta_type, class op_type>
are_equal(const type & x,const type & y,const delta_type & delta,op_type op,typename std::enable_if<!is_vector_type<type>::value && std::is_integral<type>::value>::type * =0)58 inline bool are_equal(const type& x,
59                       const type& y,
60                       const delta_type& delta,
61                       op_type op,
62                       typename std::enable_if<
63                         !is_vector_type<type>::value
64                         && std::is_integral<type>::value
65                       >::type* = 0)
66 {
67     (void) delta;
68     if(op.is_out_bool())
69     {
70         if(!((x != 0) == (y != 0)))
71         {
72             return false;
73         }
74     }
75     return x == y;
76 }
77 
78 template<class type, class type1, class type2, class op_type>
are_equal(const type & x,const type1 & y,const type2 & delta,op_type op,typename std::enable_if<!is_vector_type<type>::value && std::is_floating_point<type>::value>::type * =0)79 inline bool are_equal(const type& x,
80                       const type1& y,
81                       const type2& delta,
82                       op_type op,
83                       typename std::enable_if<
84                         !is_vector_type<type>::value
85                         && std::is_floating_point<type>::value
86                       >::type* = 0)
87 {
88     // x - expected
89     // y - result
90 
91     // INFO:
92     // Whe don't care about subnormal values in OpenCL C++ tests
93     if(std::fpclassify(static_cast<type1>(x)) == FP_SUBNORMAL || std::fpclassify(y) == FP_SUBNORMAL)
94     {
95         return true;
96     }
97 
98     // both are NaN
99     if((std::isnan)(static_cast<type1>(x)) && (std::isnan)(y))
100     {
101         return true;
102     }
103     // one is NaN
104     else if((std::isnan)(static_cast<type1>(x)) || (std::isnan)(y))
105     {
106         return false;
107     }
108 
109     // Check for perfect match, it also covers inf, -inf
110     if(static_cast<type1>(x) != y)
111     {
112         // Check if values are close
113         if(std::abs(static_cast<type1>(x) - y) > (std::max)(std::numeric_limits<type2>::epsilon(), std::abs(delta)))
114         {
115             return false;
116         }
117         // Check ulp
118         if(op.use_ulp())
119         {
120             return !(std::abs(Ulp_Error(x, y)) > op.ulp());
121         }
122     }
123     return true;
124 }
125 
126 template<class type, class type1, class type2, class op_type>
are_equal(const type & x,const type1 & y,const type2 & delta,op_type op,typename std::enable_if<is_vector_type<type>::value && std::is_floating_point<typename scalar_type<type>::type>::value>::type * =0)127 inline bool are_equal(const type& x,
128                       const type1& y,
129                       const type2& delta,
130                       op_type op,
131                       typename std::enable_if<
132                         is_vector_type<type>::value
133                         && std::is_floating_point<typename scalar_type<type>::type>::value
134                       >::type* = 0)
135 {
136     // x - expected
137     // y - result
138     for(size_t i = 0; i < vector_size<type>::value; i++)
139     {
140         if(!are_equal(x.s[i], y.s[i], delta.s[i], op))
141         {
142             return false;
143         }
144     }
145     return true;
146 }
147 
148 template<class type, class type1, class func>
print_error_msg(const type & expected,const type1 & result,size_t i,func op)149 inline void print_error_msg(const type& expected, const type1& result, size_t i, func op)
150 {
151     log_error(
152         "ERROR: test_%s %s failed. Error at %lu: Expected: %s, got: %s\n",
153         op.str().c_str(),
154         op.decl_str().c_str(),
155         i,
156         format_value(expected).c_str(),
157         format_value(result).c_str()
158     );
159 }
160 
161 #endif // TEST_CONFORMANCE_CLCPP_UTILS_TEST_COMPARE_HPP
162