|
5 | 5 | // RUN: %if preview-breaking-changes-supported %{ %{build} %{mathflags} -fpreview-breaking-changes -o %t_preview.out %}
|
6 | 6 | // RUN: %if preview-breaking-changes-supported %{ %{run} %t_preview.out%}
|
7 | 7 |
|
| 8 | +#include <cmath> |
8 | 9 | #include <sycl/sycl.hpp>
|
9 | 10 |
|
| 11 | +// Reference |
| 12 | +// https://github.com/KhronosGroup/SYCL-CTS/blob/SYCL-2020/util/accuracy.h |
| 13 | +template <typename T> T get_ulp_sycl(T x) { |
| 14 | + const T inf = std::numeric_limits<T>::infinity(); |
| 15 | + const T negative = sycl::fabs(sycl::nextafter(x, -inf) - x); |
| 16 | + const T positive = sycl::fabs(sycl::nextafter(x, inf) - x); |
| 17 | + return sycl::fmin(negative, positive); |
| 18 | +} |
| 19 | + |
| 20 | +// Case 1: According to the SYCL 2020 specification, the sycl::half_precision |
| 21 | +// math functions all take float or either an marray, vec, or swizzled vec of |
| 22 | +// float. Additionally, the ULP expectation of all of these should be 8192 |
| 23 | +// according to the spec. |
| 24 | +// |
| 25 | +// Case 2: The allowed error in ULP is less than 8192 for half precision |
| 26 | +// floating-point (sycl::half) |
| 27 | +template <typename T> T get_8192ulp_sycl(T x) { |
| 28 | + const auto ulp = get_ulp_sycl<float>(x); |
| 29 | + const float multiplier = 8192.0f; |
| 30 | + return static_cast<T>(ulp * multiplier); |
| 31 | +} |
| 32 | + |
| 33 | +template <typename T> bool compare_floats_8192ulp(T actual, T expected) { |
| 34 | + const T difference = static_cast<T>(std::fabs(actual - expected)); |
| 35 | + const T difference_expected = get_8192ulp_sycl(expected); |
| 36 | + return difference <= difference_expected; |
| 37 | +} |
| 38 | + |
10 | 39 | #define TEST(FUNC, MARRAY_ELEM_TYPE, DIM, EXPECTED, DELTA, ...) \
|
11 | 40 | { \
|
12 | 41 | { \
|
|
76 | 105 | } \
|
77 | 106 | }
|
78 | 107 |
|
| 108 | +#define TEST4(FUNC, MARRAY_ELEM_TYPE, DIM, EXPECTED, ...) \ |
| 109 | + { \ |
| 110 | + { \ |
| 111 | + MARRAY_ELEM_TYPE result[DIM]; \ |
| 112 | + { \ |
| 113 | + sycl::buffer<MARRAY_ELEM_TYPE> b(result, sycl::range{DIM}); \ |
| 114 | + deviceQueue.submit([&](sycl::handler &cgh) { \ |
| 115 | + sycl::accessor res_access{b, cgh}; \ |
| 116 | + cgh.single_task([=]() { \ |
| 117 | + sycl::marray<MARRAY_ELEM_TYPE, DIM> res = FUNC(__VA_ARGS__); \ |
| 118 | + for (int i = 0; i < DIM; i++) \ |
| 119 | + res_access[i] = res[i]; \ |
| 120 | + }); \ |
| 121 | + }); \ |
| 122 | + } \ |
| 123 | + for (int i = 0; i < DIM; i++) \ |
| 124 | + assert(compare_floats_8192ulp(result[i], EXPECTED[i])); \ |
| 125 | + } \ |
| 126 | + } |
| 127 | + |
79 | 128 | #define EXPECTED(TYPE, ...) ((TYPE[]){__VA_ARGS__})
|
80 | 129 |
|
81 | 130 | int main() {
|
@@ -117,8 +166,32 @@ int main() {
|
117 | 166 | TEST3(sycl::nan, float, 3, ma7);
|
118 | 167 | if (deviceQueue.get_device().has(sycl::aspect::fp64))
|
119 | 168 | TEST3(sycl::nan, double, 3, ma8);
|
120 |
| - TEST(sycl::half_precision::exp10, float, 2, EXPECTED(float, 10, 100), 0.1, |
121 |
| - ma1); |
| 169 | + |
| 170 | + TEST4(sycl::half_precision::sin, float, 3, |
| 171 | + EXPECTED(float, 0.98545f, -0.871576f, -0.832267f), ma6); |
| 172 | + TEST4(sycl::half_precision::cos, float, 3, |
| 173 | + EXPECTED(float, 0.169967f, -0.490261f, 0.554375f), ma6); |
| 174 | + TEST4(sycl::half_precision::tan, float, 3, |
| 175 | + EXPECTED(float, 5.797f, 1.777f, -1.501f), ma6); |
| 176 | + TEST4(sycl::half_precision::divide, float, 2, EXPECTED(float, 3.0f, 1.0f), |
| 177 | + ma2, ma1); |
| 178 | + TEST4(sycl::half_precision::log, float, 2, EXPECTED(float, 0.0f, 0.693f), |
| 179 | + ma1); |
| 180 | + TEST4(sycl::half_precision::log2, float, 2, EXPECTED(float, 0.0f, 1.f), ma1); |
| 181 | + TEST4(sycl::half_precision::log10, float, 2, EXPECTED(float, 0.0f, 0.301f), |
| 182 | + ma1); |
| 183 | + TEST4(sycl::half_precision::powr, float, 2, EXPECTED(float, 3.0f, 4.0f), ma2, |
| 184 | + ma1); |
| 185 | + TEST4(sycl::half_precision::recip, float, 2, EXPECTED(float, 0.333333f, 0.5f), |
| 186 | + ma2); |
| 187 | + TEST4(sycl::half_precision::sqrt, float, 2, EXPECTED(float, 1.0f, 1.414f), |
| 188 | + ma1); |
| 189 | + TEST4(sycl::half_precision::rsqrt, float, 2, EXPECTED(float, 1.0f, 0.707f), |
| 190 | + ma1); |
| 191 | + TEST4(sycl::half_precision::exp, float, 2, EXPECTED(float, 2.718f, 7.389f), |
| 192 | + ma1); |
| 193 | + TEST4(sycl::half_precision::exp2, float, 2, EXPECTED(float, 2, 4), ma1); |
| 194 | + TEST4(sycl::half_precision::exp10, float, 2, EXPECTED(float, 10, 100), ma1); |
122 | 195 |
|
123 | 196 | return 0;
|
124 | 197 | }
|
0 commit comments