mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-21 14:59:02 +00:00
Initial open source release of OpenCL 2.2 CTS.
This commit is contained in:
12
test_conformance/clcpp/math_funcs/CMakeLists.txt
Normal file
12
test_conformance/clcpp/math_funcs/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(MODULE_NAME CPP_MATH_FUNCS)
|
||||
|
||||
set(${MODULE_NAME}_SOURCES
|
||||
main.cpp
|
||||
../../../test_common/harness/errorHelpers.c
|
||||
../../../test_common/harness/testHarness.c
|
||||
../../../test_common/harness/kernelHelpers.c
|
||||
../../../test_common/harness/msvc9.c
|
||||
../../../test_common/harness/parseParameters.cpp
|
||||
)
|
||||
|
||||
include(../../CMakeCommon.txt)
|
||||
347
test_conformance/clcpp/math_funcs/common.hpp
Normal file
347
test_conformance/clcpp/math_funcs/common.hpp
Normal file
@@ -0,0 +1,347 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_COMMON_FUNCS_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_COMMON_FUNCS_HPP
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include "../common.hpp"
|
||||
#include "../funcs_test_utils.hpp"
|
||||
|
||||
#include "reference.hpp"
|
||||
|
||||
#ifndef MATH_FUNCS_CLASS_NAME
|
||||
#define MATH_FUNCS_CLASS_NAME(x, y) x ## _func_ ## y
|
||||
#endif
|
||||
|
||||
#define MATH_FUNCS_DEFINE_UNARY_FUNC1(GROUP_NAME, NAME, OCL_FUNC, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1) \
|
||||
struct MATH_FUNCS_CLASS_NAME(GROUP_NAME, NAME) : public unary_func<cl_float, cl_float> \
|
||||
{ \
|
||||
MATH_FUNCS_CLASS_NAME(GROUP_NAME, NAME)(bool is_embedded) : m_is_embedded(is_embedded) \
|
||||
{ \
|
||||
\
|
||||
} \
|
||||
\
|
||||
std::string str() \
|
||||
{ \
|
||||
return #OCL_FUNC; \
|
||||
} \
|
||||
\
|
||||
std::string headers() \
|
||||
{ \
|
||||
return "#include <opencl_math>\n"; \
|
||||
} \
|
||||
/* Reference value type is cl_double */ \
|
||||
cl_double operator()(const cl_float& x) \
|
||||
{ \
|
||||
return (HOST_FUNC)(static_cast<cl_double>(x)); \
|
||||
} \
|
||||
\
|
||||
cl_float min1() \
|
||||
{ \
|
||||
return MIN1; \
|
||||
} \
|
||||
\
|
||||
cl_float max1() \
|
||||
{ \
|
||||
return MAX1; \
|
||||
} \
|
||||
\
|
||||
std::vector<cl_float> in1_special_cases() \
|
||||
{ \
|
||||
return { \
|
||||
cl_float(0.0f), \
|
||||
cl_float(-0.0f), \
|
||||
cl_float(1.0f), \
|
||||
cl_float(-1.0f), \
|
||||
cl_float(2.0f), \
|
||||
cl_float(-2.0f), \
|
||||
std::numeric_limits<cl_float>::infinity(), \
|
||||
-std::numeric_limits<cl_float>::infinity(), \
|
||||
std::numeric_limits<cl_float>::quiet_NaN() \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
bool use_ulp() \
|
||||
{ \
|
||||
return USE_ULP; \
|
||||
} \
|
||||
\
|
||||
template<class T> \
|
||||
typename make_vector_type<cl_double, vector_size<T>::value>::type \
|
||||
delta(const cl_float& in1, const T& expected) \
|
||||
{ \
|
||||
typedef \
|
||||
typename make_vector_type<cl_double, vector_size<T>::value>::type \
|
||||
delta_vector_type; \
|
||||
(void) in1; \
|
||||
auto e = detail::make_value<delta_vector_type>(DELTA); \
|
||||
return detail::multiply<delta_vector_type>(e, expected); \
|
||||
} \
|
||||
\
|
||||
float ulp() \
|
||||
{ \
|
||||
if(m_is_embedded) \
|
||||
{ \
|
||||
return ULP_EMBEDDED; \
|
||||
} \
|
||||
return ULP; \
|
||||
} \
|
||||
private: \
|
||||
bool m_is_embedded; \
|
||||
};
|
||||
|
||||
#define MATH_FUNCS_DEFINE_BINARY_FUNC1(GROUP_NAME, NAME, OCL_NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1, MIN2, MAX2) \
|
||||
struct MATH_FUNCS_CLASS_NAME(GROUP_NAME, NAME) : public binary_func<cl_float, cl_float, cl_float> \
|
||||
{ \
|
||||
MATH_FUNCS_CLASS_NAME(GROUP_NAME, NAME)(bool is_embedded) : m_is_embedded(is_embedded) \
|
||||
{ \
|
||||
\
|
||||
} \
|
||||
\
|
||||
std::string str() \
|
||||
{ \
|
||||
return #OCL_NAME; \
|
||||
} \
|
||||
\
|
||||
std::string headers() \
|
||||
{ \
|
||||
return "#include <opencl_math>\n"; \
|
||||
} \
|
||||
\
|
||||
cl_float operator()(const cl_float& x, const cl_float& y) \
|
||||
{ \
|
||||
return (HOST_FUNC)(x, y); \
|
||||
} \
|
||||
\
|
||||
cl_float min1() \
|
||||
{ \
|
||||
return MIN1; \
|
||||
} \
|
||||
\
|
||||
cl_float max1() \
|
||||
{ \
|
||||
return MAX1; \
|
||||
} \
|
||||
\
|
||||
cl_float min2() \
|
||||
{ \
|
||||
return MIN2; \
|
||||
} \
|
||||
\
|
||||
cl_float max2() \
|
||||
{ \
|
||||
return MAX2; \
|
||||
} \
|
||||
\
|
||||
std::vector<cl_float> in1_special_cases() \
|
||||
{ \
|
||||
return { \
|
||||
cl_float(0.0f), \
|
||||
cl_float(-0.0f), \
|
||||
cl_float(1.0f), \
|
||||
cl_float(-1.0f), \
|
||||
cl_float(2.0f), \
|
||||
cl_float(-2.0f), \
|
||||
std::numeric_limits<cl_float>::infinity(), \
|
||||
-std::numeric_limits<cl_float>::infinity(), \
|
||||
std::numeric_limits<cl_float>::quiet_NaN() \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
std::vector<cl_float> in2_special_cases() \
|
||||
{ \
|
||||
return { \
|
||||
cl_float(0.0f), \
|
||||
cl_float(-0.0f), \
|
||||
cl_float(1.0f), \
|
||||
cl_float(-1.0f), \
|
||||
cl_float(2.0f), \
|
||||
cl_float(-2.0f), \
|
||||
std::numeric_limits<cl_float>::infinity(), \
|
||||
-std::numeric_limits<cl_float>::infinity(), \
|
||||
std::numeric_limits<cl_float>::quiet_NaN() \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
template<class T> \
|
||||
typename make_vector_type<cl_double, vector_size<T>::value>::type \
|
||||
delta(const cl_float& in1, const cl_float& in2, const T& expected) \
|
||||
{ \
|
||||
typedef \
|
||||
typename make_vector_type<cl_double, vector_size<T>::value>::type \
|
||||
delta_vector_type; \
|
||||
(void) in1; \
|
||||
(void) in2; \
|
||||
auto e = detail::make_value<delta_vector_type>(DELTA); \
|
||||
return detail::multiply<delta_vector_type>(e, expected); \
|
||||
} \
|
||||
\
|
||||
bool use_ulp() \
|
||||
{ \
|
||||
return USE_ULP; \
|
||||
} \
|
||||
\
|
||||
float ulp() \
|
||||
{ \
|
||||
if(m_is_embedded) \
|
||||
{ \
|
||||
return ULP_EMBEDDED; \
|
||||
} \
|
||||
return ULP; \
|
||||
} \
|
||||
private: \
|
||||
bool m_is_embedded; \
|
||||
};
|
||||
|
||||
#define MATH_FUNCS_DEFINE_TERNARY_FUNC1(GROUP_NAME, NAME, OCL_NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1, MIN2, MAX2, MIN3, MAX3) \
|
||||
struct MATH_FUNCS_CLASS_NAME(GROUP_NAME, NAME) : public ternary_func<cl_float, cl_float, cl_float, cl_float> \
|
||||
{ \
|
||||
MATH_FUNCS_CLASS_NAME(GROUP_NAME, NAME)(bool is_embedded) : m_is_embedded(is_embedded) \
|
||||
{ \
|
||||
\
|
||||
} \
|
||||
\
|
||||
std::string str() \
|
||||
{ \
|
||||
return #OCL_NAME; \
|
||||
} \
|
||||
\
|
||||
std::string headers() \
|
||||
{ \
|
||||
return "#include <opencl_math>\n"; \
|
||||
} \
|
||||
\
|
||||
cl_double operator()(const cl_float& x, const cl_float& y, const cl_float& z) \
|
||||
{ \
|
||||
return (HOST_FUNC)(static_cast<cl_double>(x), static_cast<cl_double>(y), static_cast<cl_double>(z)); \
|
||||
} \
|
||||
\
|
||||
cl_float min1() \
|
||||
{ \
|
||||
return MIN1; \
|
||||
} \
|
||||
\
|
||||
cl_float max1() \
|
||||
{ \
|
||||
return MAX1; \
|
||||
} \
|
||||
\
|
||||
cl_float min2() \
|
||||
{ \
|
||||
return MIN2; \
|
||||
} \
|
||||
\
|
||||
cl_float max2() \
|
||||
{ \
|
||||
return MAX2; \
|
||||
} \
|
||||
\
|
||||
cl_float min3() \
|
||||
{ \
|
||||
return MIN3; \
|
||||
} \
|
||||
\
|
||||
cl_float max3() \
|
||||
{ \
|
||||
return MAX3; \
|
||||
} \
|
||||
\
|
||||
std::vector<cl_float> in1_special_cases() \
|
||||
{ \
|
||||
return { \
|
||||
cl_float(0.0f), \
|
||||
cl_float(-0.0f), \
|
||||
cl_float(1.0f), \
|
||||
cl_float(-1.0f), \
|
||||
cl_float(2.0f), \
|
||||
cl_float(-2.0f), \
|
||||
std::numeric_limits<cl_float>::infinity(), \
|
||||
-std::numeric_limits<cl_float>::infinity(), \
|
||||
std::numeric_limits<cl_float>::quiet_NaN() \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
std::vector<cl_float> in2_special_cases() \
|
||||
{ \
|
||||
return { \
|
||||
cl_float(0.0f), \
|
||||
cl_float(-0.0f), \
|
||||
cl_float(1.0f), \
|
||||
cl_float(-1.0f), \
|
||||
cl_float(2.0f), \
|
||||
cl_float(-2.0f), \
|
||||
std::numeric_limits<cl_float>::infinity(), \
|
||||
-std::numeric_limits<cl_float>::infinity(), \
|
||||
std::numeric_limits<cl_float>::quiet_NaN() \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
std::vector<cl_float> in3_special_cases() \
|
||||
{ \
|
||||
return { \
|
||||
cl_float(0.0f), \
|
||||
cl_float(-0.0f), \
|
||||
cl_float(1.0f), \
|
||||
cl_float(-1.0f), \
|
||||
cl_float(2.0f), \
|
||||
cl_float(-2.0f), \
|
||||
std::numeric_limits<cl_float>::infinity(), \
|
||||
-std::numeric_limits<cl_float>::infinity(), \
|
||||
std::numeric_limits<cl_float>::quiet_NaN() \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
template<class T> \
|
||||
typename make_vector_type<cl_double, vector_size<T>::value>::type \
|
||||
delta(const cl_float& in1, const cl_float& in2, const cl_float& in3, const T& expected) \
|
||||
{ \
|
||||
typedef \
|
||||
typename make_vector_type<cl_double, vector_size<T>::value>::type \
|
||||
delta_vector_type; \
|
||||
(void) in1; \
|
||||
(void) in2; \
|
||||
(void) in3; \
|
||||
auto e = detail::make_value<delta_vector_type>(DELTA); \
|
||||
return detail::multiply<delta_vector_type>(e, expected); \
|
||||
} \
|
||||
\
|
||||
bool use_ulp() \
|
||||
{ \
|
||||
return USE_ULP; \
|
||||
} \
|
||||
\
|
||||
float ulp() \
|
||||
{ \
|
||||
if(m_is_embedded) \
|
||||
{ \
|
||||
return ULP_EMBEDDED; \
|
||||
} \
|
||||
return ULP; \
|
||||
} \
|
||||
private: \
|
||||
bool m_is_embedded; \
|
||||
};
|
||||
|
||||
#define MATH_FUNCS_DEFINE_UNARY_FUNC(GROUP_NAME, NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1) \
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(GROUP_NAME, NAME, NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1)
|
||||
#define MATH_FUNCS_DEFINE_BINARY_FUNC(GROUP_NAME, NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1, MIN2, MAX2) \
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC1(GROUP_NAME, NAME, NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1, MIN2, MAX2)
|
||||
#define MATH_FUNCS_DEFINE_TERNARY_FUNC(GROUP_NAME, NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1, MIN2, MAX2, MIN3, MAX3) \
|
||||
MATH_FUNCS_DEFINE_TERNARY_FUNC1(GROUP_NAME, NAME, NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, DELTA, MIN1, MAX1, MIN2, MAX2, MIN3, MAX3)
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_COMMON_FUNCS_HPP
|
||||
59
test_conformance/clcpp/math_funcs/comparison_funcs.hpp
Normal file
59
test_conformance/clcpp/math_funcs/comparison_funcs.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_COMPARISON_FUNCS_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_COMPARISON_FUNCS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(comparison, fdim, std::fdim, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(comparison, fmax, std::fmax, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(comparison, fmin, std::fmin, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(comparison, maxmag, reference::maxmag, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(comparison, minmag, reference::minmag, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f)
|
||||
|
||||
// comparison functions
|
||||
AUTO_TEST_CASE(test_comparison_funcs)
|
||||
(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
|
||||
{
|
||||
int error = CL_SUCCESS;
|
||||
int last_error = CL_SUCCESS;
|
||||
|
||||
// Check for EMBEDDED_PROFILE
|
||||
bool is_embedded_profile = false;
|
||||
char profile[128];
|
||||
last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL);
|
||||
RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo")
|
||||
if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0)
|
||||
is_embedded_profile = true;
|
||||
|
||||
TEST_BINARY_FUNC_MACRO((comparison_func_fdim(is_embedded_profile)))
|
||||
TEST_BINARY_FUNC_MACRO((comparison_func_fmax(is_embedded_profile)))
|
||||
TEST_BINARY_FUNC_MACRO((comparison_func_fmin(is_embedded_profile)))
|
||||
TEST_BINARY_FUNC_MACRO((comparison_func_maxmag(is_embedded_profile)))
|
||||
TEST_BINARY_FUNC_MACRO((comparison_func_minmag(is_embedded_profile)))
|
||||
|
||||
if(error != CL_SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_COMPARISON_FUNCS_HPP
|
||||
139
test_conformance/clcpp/math_funcs/exponential_funcs.hpp
Normal file
139
test_conformance/clcpp/math_funcs/exponential_funcs.hpp
Normal file
@@ -0,0 +1,139 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_EXP_FUNCS_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_EXP_FUNCS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(exponential, exp, std::exp, true, 3.0f, 4.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(exponential, expm1, std::expm1, true, 3.0f, 4.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(exponential, exp2, std::exp2, true, 3.0f, 4.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(exponential, exp10, reference::exp10, true, 3.0f, 4.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
|
||||
struct exponential_func_ldexp : public binary_func<cl_float, cl_int, cl_float>
|
||||
{
|
||||
exponential_func_ldexp(bool is_embedded) : m_is_embedded(is_embedded)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
return "ldexp";
|
||||
}
|
||||
|
||||
std::string headers()
|
||||
{
|
||||
return "#include <opencl_math>\n";
|
||||
}
|
||||
|
||||
/* Reference value type is cl_double */
|
||||
cl_double operator()(const cl_float& x, const cl_int& y)
|
||||
{
|
||||
return (std::ldexp)(static_cast<cl_double>(x), y);
|
||||
}
|
||||
|
||||
cl_float min1()
|
||||
{
|
||||
return -1000.0f;
|
||||
}
|
||||
|
||||
cl_float max1()
|
||||
{
|
||||
return 1000.0f;
|
||||
}
|
||||
|
||||
cl_int min2()
|
||||
{
|
||||
return -8;
|
||||
}
|
||||
|
||||
cl_int max2()
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
std::vector<cl_float> in1_special_cases()
|
||||
{
|
||||
return {
|
||||
cl_float(0.0f),
|
||||
cl_float(-0.0f),
|
||||
cl_float(1.0f),
|
||||
cl_float(-1.0f),
|
||||
cl_float(2.0f),
|
||||
cl_float(-2.0f),
|
||||
std::numeric_limits<cl_float>::infinity(),
|
||||
-std::numeric_limits<cl_float>::infinity(),
|
||||
std::numeric_limits<cl_float>::quiet_NaN()
|
||||
};
|
||||
}
|
||||
|
||||
bool use_ulp()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
float ulp()
|
||||
{
|
||||
if(m_is_embedded)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
private:
|
||||
bool m_is_embedded;
|
||||
};
|
||||
|
||||
// exponential functions
|
||||
AUTO_TEST_CASE(test_exponential_funcs)
|
||||
(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
|
||||
{
|
||||
int error = CL_SUCCESS;
|
||||
int last_error = CL_SUCCESS;
|
||||
|
||||
// Check for EMBEDDED_PROFILE
|
||||
bool is_embedded_profile = false;
|
||||
char profile[128];
|
||||
last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL);
|
||||
RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo")
|
||||
if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0)
|
||||
is_embedded_profile = true;
|
||||
|
||||
// auto exp(gentype x);
|
||||
// auto expm1(gentype x);
|
||||
// auto exp2(gentype x);
|
||||
// auto exp10(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((exponential_func_exp(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((exponential_func_expm1(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((exponential_func_exp2(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((exponential_func_exp10(is_embedded_profile)))
|
||||
|
||||
// auto ldexp(gentype x, intn k);
|
||||
TEST_BINARY_FUNC_MACRO((exponential_func_ldexp(is_embedded_profile)))
|
||||
|
||||
if(error != CL_SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_EXP_FUNCS_HPP
|
||||
733
test_conformance/clcpp/math_funcs/floating_point_funcs.hpp
Normal file
733
test_conformance/clcpp/math_funcs/floating_point_funcs.hpp
Normal file
@@ -0,0 +1,733 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_FP_FUNCS_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_FP_FUNCS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
// -------------- UNARY FUNCTIONS
|
||||
|
||||
// gentype ceil(gentype x);
|
||||
// gentype floor(gentype x);
|
||||
// gentype rint(gentype x);
|
||||
// gentype round(gentype x);
|
||||
// gentype trunc(gentype x);
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(fp, ceil, std::ceil, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(fp, floor, std::floor, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(fp, rint, std::rint, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(fp, round, std::round, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(fp, trunc, std::trunc, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
|
||||
// floatn nan(uintn nancode);
|
||||
struct fp_func_nan : public unary_func<cl_uint, cl_float>
|
||||
{
|
||||
std::string str()
|
||||
{
|
||||
return "nan";
|
||||
}
|
||||
|
||||
std::string headers()
|
||||
{
|
||||
return "#include <opencl_math>\n";
|
||||
}
|
||||
|
||||
cl_float operator()(const cl_uint& x)
|
||||
{
|
||||
cl_uint r = x | 0x7fc00000U;
|
||||
// cl_float and cl_int have the same size so that's correct
|
||||
cl_float rf = *reinterpret_cast<cl_float*>(&r);
|
||||
return rf;
|
||||
}
|
||||
|
||||
cl_uint min1()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cl_uint max1()
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
std::vector<cl_uint> in1_special_cases()
|
||||
{
|
||||
return {
|
||||
0, 1
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// -------------- UNARY FUNCTIONS, 2ND ARG IS POINTER
|
||||
|
||||
// gentype fract(gentype x, gentype* iptr);
|
||||
//
|
||||
// Fuction fract() returns additional value via pointer (2nd argument). In order to test
|
||||
// if it's correct output buffer type is cl_float2. In first compontent we store what
|
||||
// fract() function returns, and in the 2nd component we store what is returned via its
|
||||
// 2nd argument (gentype* iptr).
|
||||
struct fp_func_fract : public unary_func<cl_float, cl_float2>
|
||||
{
|
||||
fp_func_fract(bool is_embedded) : m_is_embedded(is_embedded)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
return "fract";
|
||||
}
|
||||
|
||||
std::string headers()
|
||||
{
|
||||
return "#include <opencl_math>\n";
|
||||
}
|
||||
|
||||
cl_double2 operator()(const cl_float& x)
|
||||
{
|
||||
return reference::fract(static_cast<cl_double>(x));
|
||||
}
|
||||
|
||||
cl_float min1()
|
||||
{
|
||||
return -1000.0f;
|
||||
}
|
||||
|
||||
cl_float max1()
|
||||
{
|
||||
return 1000.0f;
|
||||
}
|
||||
|
||||
std::vector<cl_float> in1_special_cases()
|
||||
{
|
||||
return {
|
||||
cl_float(0.0f),
|
||||
cl_float(-0.0f),
|
||||
cl_float(1.0f),
|
||||
cl_float(-1.0f),
|
||||
cl_float(2.0f),
|
||||
cl_float(-2.0f),
|
||||
std::numeric_limits<cl_float>::infinity(),
|
||||
-std::numeric_limits<cl_float>::infinity(),
|
||||
std::numeric_limits<cl_float>::quiet_NaN()
|
||||
};
|
||||
}
|
||||
|
||||
bool use_ulp()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
float ulp()
|
||||
{
|
||||
if(m_is_embedded)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
private:
|
||||
bool m_is_embedded;
|
||||
};
|
||||
|
||||
// We need to specialize generate_kernel_unary<>() function template for fp_func_fract.
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
|
||||
template <>
|
||||
std::string generate_kernel_unary<fp_func_fract, cl_float, cl_float2>(fp_func_fract func)
|
||||
{
|
||||
return
|
||||
"__kernel void test_fract(global float *input, global float2 *output)\n"
|
||||
"{\n"
|
||||
" size_t gid = get_global_id(0);\n"
|
||||
" float2 result;\n"
|
||||
" float itpr = 0;\n"
|
||||
" result.x = fract(input[gid], &itpr);\n"
|
||||
" result.y = itpr;\n"
|
||||
" output[gid] = result;\n"
|
||||
"}\n";
|
||||
}
|
||||
#else
|
||||
template <>
|
||||
std::string generate_kernel_unary<fp_func_fract, cl_float, cl_float2>(fp_func_fract func)
|
||||
{
|
||||
return
|
||||
"" + func.defs() +
|
||||
"" + func.headers() +
|
||||
"#include <opencl_memory>\n"
|
||||
"#include <opencl_work_item>\n"
|
||||
"using namespace cl;\n"
|
||||
"__kernel void test_fract(global_ptr<float[]> input, global_ptr<float2[]> output)\n"
|
||||
"{\n"
|
||||
" size_t gid = get_global_id(0);\n"
|
||||
" float2 result;\n"
|
||||
" float itpr = 0;\n"
|
||||
" result.x = fract(input[gid], &itpr);\n"
|
||||
" result.y = itpr;\n"
|
||||
" output[gid] = result;\n"
|
||||
"}\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
// gentype modf(gentype x, gentype* iptr);
|
||||
//
|
||||
// Fuction modf() returns additional value via pointer (2nd argument). In order to test
|
||||
// if it's correct output buffer type is cl_float2. In first compontent we store what
|
||||
// modf() function returns, and in the 2nd component we store what is returned via its
|
||||
// 2nd argument (gentype* iptr).
|
||||
struct fp_func_modf : public unary_func<cl_float, cl_float2>
|
||||
{
|
||||
fp_func_modf(bool is_embedded) : m_is_embedded(is_embedded)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
return "modf";
|
||||
}
|
||||
|
||||
std::string headers()
|
||||
{
|
||||
return "#include <opencl_math>\n";
|
||||
}
|
||||
|
||||
cl_double2 operator()(const cl_float& x)
|
||||
{
|
||||
cl_double2 r;
|
||||
r.s[0] = (std::modf)(static_cast<cl_double>(x), &(r.s[1]));
|
||||
return r;
|
||||
}
|
||||
|
||||
cl_float min1()
|
||||
{
|
||||
return -1000.0f;
|
||||
}
|
||||
|
||||
cl_float max1()
|
||||
{
|
||||
return 1000.0f;
|
||||
}
|
||||
|
||||
std::vector<cl_float> in1_special_cases()
|
||||
{
|
||||
return {
|
||||
cl_float(0.0f),
|
||||
cl_float(-0.0f),
|
||||
cl_float(1.0f),
|
||||
cl_float(-1.0f),
|
||||
cl_float(2.0f),
|
||||
cl_float(-2.0f),
|
||||
std::numeric_limits<cl_float>::infinity(),
|
||||
-std::numeric_limits<cl_float>::infinity(),
|
||||
std::numeric_limits<cl_float>::quiet_NaN()
|
||||
};
|
||||
}
|
||||
|
||||
bool use_ulp()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
float ulp()
|
||||
{
|
||||
if(m_is_embedded)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
private:
|
||||
bool m_is_embedded;
|
||||
};
|
||||
|
||||
// We need to specialize generate_kernel_unary<>() function template for fp_func_modf.
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
|
||||
template <>
|
||||
std::string generate_kernel_unary<fp_func_modf, cl_float, cl_float2>(fp_func_modf func)
|
||||
{
|
||||
return
|
||||
"__kernel void test_modf(global float *input, global float2 *output)\n"
|
||||
"{\n"
|
||||
" size_t gid = get_global_id(0);\n"
|
||||
" float2 result;\n"
|
||||
" float itpr = 0;\n"
|
||||
" result.x = modf(input[gid], &itpr);\n"
|
||||
" result.y = itpr;\n"
|
||||
" output[gid] = result;\n"
|
||||
"}\n";
|
||||
}
|
||||
#else
|
||||
template <>
|
||||
std::string generate_kernel_unary<fp_func_modf, cl_float, cl_float2>(fp_func_modf func)
|
||||
{
|
||||
return
|
||||
"" + func.defs() +
|
||||
"" + func.headers() +
|
||||
"#include <opencl_memory>\n"
|
||||
"#include <opencl_work_item>\n"
|
||||
"using namespace cl;\n"
|
||||
"__kernel void test_modf(global_ptr<float[]> input, global_ptr<float2[]> output)\n"
|
||||
"{\n"
|
||||
" size_t gid = get_global_id(0);\n"
|
||||
" float2 result;\n"
|
||||
" float itpr = 0;\n"
|
||||
" result.x = modf(input[gid], &itpr);\n"
|
||||
" result.y = itpr;\n"
|
||||
" output[gid] = result;\n"
|
||||
"}\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
// gentype frexp(gentype x, intn* exp);
|
||||
//
|
||||
// Fuction frexp() returns additional value via pointer (2nd argument). In order to test
|
||||
// if it's correct output buffer type is cl_float2. In first compontent we store what
|
||||
// modf() function returns, and in the 2nd component we store what is returned via its
|
||||
// 2nd argument (intn* exp).
|
||||
struct fp_func_frexp : public unary_func<cl_float, cl_float2>
|
||||
{
|
||||
fp_func_frexp(bool is_embedded) : m_is_embedded(is_embedded)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
return "frexp";
|
||||
}
|
||||
|
||||
std::string headers()
|
||||
{
|
||||
return "#include <opencl_math>\n";
|
||||
}
|
||||
|
||||
cl_double2 operator()(const cl_float& x)
|
||||
{
|
||||
cl_double2 r;
|
||||
cl_int e;
|
||||
r.s[0] = (std::frexp)(static_cast<cl_double>(x), &e);
|
||||
r.s[1] = static_cast<cl_float>(e);
|
||||
return r;
|
||||
}
|
||||
|
||||
cl_float min1()
|
||||
{
|
||||
return -1000.0f;
|
||||
}
|
||||
|
||||
cl_float max1()
|
||||
{
|
||||
return 1000.0f;
|
||||
}
|
||||
|
||||
std::vector<cl_float> in1_special_cases()
|
||||
{
|
||||
return {
|
||||
cl_float(0.0f),
|
||||
cl_float(-0.0f),
|
||||
cl_float(1.0f),
|
||||
cl_float(-1.0f),
|
||||
cl_float(2.0f),
|
||||
cl_float(-2.0f),
|
||||
std::numeric_limits<cl_float>::infinity(),
|
||||
-std::numeric_limits<cl_float>::infinity(),
|
||||
std::numeric_limits<cl_float>::quiet_NaN()
|
||||
};
|
||||
}
|
||||
|
||||
bool use_ulp()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
float ulp()
|
||||
{
|
||||
if(m_is_embedded)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
private:
|
||||
bool m_is_embedded;
|
||||
};
|
||||
|
||||
// We need to specialize generate_kernel_unary<>() function template for fp_func_frexp.
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
|
||||
template <>
|
||||
std::string generate_kernel_unary<fp_func_frexp, cl_float, cl_float2>(fp_func_frexp func)
|
||||
{
|
||||
return
|
||||
"__kernel void test_frexp(global float *input, global float2 *output)\n"
|
||||
"{\n"
|
||||
" size_t gid = get_global_id(0);\n"
|
||||
" float2 result;\n"
|
||||
" int itpr = 0;\n"
|
||||
" result.x = frexp(input[gid], &itpr);\n"
|
||||
" result.y = itpr;\n"
|
||||
" output[gid] = result;\n"
|
||||
"}\n";
|
||||
}
|
||||
#else
|
||||
template <>
|
||||
std::string generate_kernel_unary<fp_func_frexp, cl_float, cl_float2>(fp_func_frexp func)
|
||||
{
|
||||
return
|
||||
"" + func.defs() +
|
||||
"" + func.headers() +
|
||||
"#include <opencl_memory>\n"
|
||||
"#include <opencl_work_item>\n"
|
||||
"using namespace cl;\n"
|
||||
"__kernel void test_frexp(global_ptr<float[]> input, global_ptr<float2[]> output)\n"
|
||||
"{\n"
|
||||
" size_t gid = get_global_id(0);\n"
|
||||
" float2 result;\n"
|
||||
" int itpr = 0;\n"
|
||||
" result.x = frexp(input[gid], &itpr);\n"
|
||||
" result.y = itpr;\n"
|
||||
" output[gid] = result;\n"
|
||||
"}\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
// -------------- BINARY FUNCTIONS
|
||||
|
||||
// gentype copysign(gentype x, gentype y);
|
||||
// gentype fmod(gentype x, gentype y);
|
||||
// gentype remainder(gentype x, gentype y);
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(fp, copysign, std::copysign, true, 0.0f, 0.0f, 0.001f, -100.0f, 100.0f, -10.0f, 10.0f)
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(fp, fmod, std::fmod, true, 0.0f, 0.0f, 0.001f, -100.0f, 100.0f, -10.0f, 10.0f)
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(fp, remainder, std::remainder, true, 0.0f, 0.001f, 0.0f, -100.0f, 100.0f, -10.0f, 10.0f)
|
||||
|
||||
// In case of function float nextafter(float, float) reference function must
|
||||
// operate on floats and return float.
|
||||
struct fp_func_nextafter : public binary_func<cl_float, cl_float, cl_float>
|
||||
{
|
||||
fp_func_nextafter(bool is_embedded) : m_is_embedded(is_embedded)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
return "nextafter";
|
||||
}
|
||||
|
||||
std::string headers()
|
||||
{
|
||||
return "#include <opencl_math>\n";
|
||||
}
|
||||
|
||||
/* In this case reference value type MUST BE cl_float */
|
||||
cl_float operator()(const cl_float& x, const cl_float& y)
|
||||
{
|
||||
return (std::nextafter)(x, y);
|
||||
}
|
||||
|
||||
cl_float min1()
|
||||
{
|
||||
return -1000.0f;
|
||||
}
|
||||
|
||||
cl_float max1()
|
||||
{
|
||||
return 500.0f;
|
||||
}
|
||||
|
||||
cl_float min2()
|
||||
{
|
||||
return 501.0f;
|
||||
}
|
||||
|
||||
cl_float max2()
|
||||
{
|
||||
return 1000.0f;
|
||||
}
|
||||
|
||||
std::vector<cl_float> in1_special_cases()
|
||||
{
|
||||
return {
|
||||
cl_float(0.0f),
|
||||
cl_float(-0.0f),
|
||||
cl_float(1.0f),
|
||||
cl_float(-1.0f),
|
||||
cl_float(2.0f),
|
||||
cl_float(-2.0f),
|
||||
std::numeric_limits<cl_float>::infinity(),
|
||||
-std::numeric_limits<cl_float>::infinity(),
|
||||
std::numeric_limits<cl_float>::quiet_NaN()
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<cl_float> in2_special_cases()
|
||||
{
|
||||
return {
|
||||
cl_float(0.0f),
|
||||
cl_float(-0.0f),
|
||||
cl_float(1.0f),
|
||||
cl_float(-1.0f),
|
||||
cl_float(2.0f),
|
||||
cl_float(-2.0f),
|
||||
std::numeric_limits<cl_float>::infinity(),
|
||||
-std::numeric_limits<cl_float>::infinity(),
|
||||
std::numeric_limits<cl_float>::quiet_NaN()
|
||||
};
|
||||
}
|
||||
|
||||
bool use_ulp()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
float ulp()
|
||||
{
|
||||
if(m_is_embedded)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
private:
|
||||
bool m_is_embedded;
|
||||
};
|
||||
|
||||
// gentype remquo(gentype x, gentype y, intn* quo);
|
||||
struct fp_func_remquo : public binary_func<cl_float, cl_float, cl_float2>
|
||||
{
|
||||
fp_func_remquo(bool is_embedded) : m_is_embedded(is_embedded)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
return "remquo";
|
||||
}
|
||||
|
||||
std::string headers()
|
||||
{
|
||||
return "#include <opencl_math>\n";
|
||||
}
|
||||
|
||||
cl_double2 operator()(const cl_float& x, const cl_float& y)
|
||||
{
|
||||
return reference::remquo(static_cast<cl_double>(x), static_cast<cl_double>(y));
|
||||
}
|
||||
|
||||
cl_float min1()
|
||||
{
|
||||
return -1000.0f;
|
||||
}
|
||||
|
||||
cl_float max1()
|
||||
{
|
||||
return 1000.0f;
|
||||
}
|
||||
|
||||
cl_float min2()
|
||||
{
|
||||
return -1000.0f;
|
||||
}
|
||||
|
||||
cl_float max2()
|
||||
{
|
||||
return 1000.0f;
|
||||
}
|
||||
|
||||
std::vector<cl_float> in1_special_cases()
|
||||
{
|
||||
return {
|
||||
cl_float(0.0f),
|
||||
cl_float(-0.0f),
|
||||
cl_float(1.0f),
|
||||
cl_float(-1.0f),
|
||||
std::numeric_limits<cl_float>::infinity(),
|
||||
-std::numeric_limits<cl_float>::infinity(),
|
||||
std::numeric_limits<cl_float>::quiet_NaN()
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<cl_float> in2_special_cases()
|
||||
{
|
||||
return {
|
||||
cl_float(0.0f),
|
||||
cl_float(-0.0f),
|
||||
cl_float(1.0f),
|
||||
cl_float(-1.0f),
|
||||
std::numeric_limits<cl_float>::infinity(),
|
||||
-std::numeric_limits<cl_float>::infinity(),
|
||||
std::numeric_limits<cl_float>::quiet_NaN()
|
||||
};
|
||||
}
|
||||
|
||||
bool use_ulp()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
float ulp()
|
||||
{
|
||||
if(m_is_embedded)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
private:
|
||||
bool m_is_embedded;
|
||||
};
|
||||
|
||||
|
||||
// We need to specialize generate_kernel_binary<>() function template for fp_func_remquo.
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
|
||||
template <>
|
||||
std::string generate_kernel_binary<fp_func_remquo, cl_float, cl_float, cl_float2>(fp_func_remquo func)
|
||||
{
|
||||
return
|
||||
"__kernel void test_remquo(global float *input1, global float *input2, global float2 *output)\n"
|
||||
"{\n"
|
||||
" size_t gid = get_global_id(0);\n"
|
||||
" float2 result;\n"
|
||||
" int quo = 0;\n"
|
||||
" int sign = 0;\n"
|
||||
" result.x = remquo(input1[gid], input2[gid], &quo);\n"
|
||||
// Specification say:
|
||||
// "remquo also calculates the lower seven bits of the integral quotient x/y,
|
||||
// and gives that value the same sign as x/y. It stores this signed value in
|
||||
// the object pointed to by quo."
|
||||
// Implemenation may save into quo more than seven bits. We need to take
|
||||
// care of that here.
|
||||
" sign = (quo < 0) ? -1 : 1;\n"
|
||||
" quo = (quo < 0) ? -quo : quo;\n"
|
||||
" quo &= 0x0000007f;\n"
|
||||
" result.y = (sign < 0) ? -quo : quo;\n"
|
||||
" output[gid] = result;\n"
|
||||
"}\n";
|
||||
}
|
||||
#else
|
||||
template <>
|
||||
std::string generate_kernel_binary<fp_func_remquo, cl_float, cl_float, cl_float2>(fp_func_remquo func)
|
||||
{
|
||||
return
|
||||
"" + func.defs() +
|
||||
"" + func.headers() +
|
||||
"#include <opencl_memory>\n"
|
||||
"#include <opencl_work_item>\n"
|
||||
"using namespace cl;\n"
|
||||
"__kernel void test_remquo(global_ptr<float[]> input1, global_ptr<float[]> input2, global_ptr<float2[]> output)\n"
|
||||
"{\n"
|
||||
" size_t gid = get_global_id(0);\n"
|
||||
" float2 result;\n"
|
||||
" int quo = 0;\n"
|
||||
" int sign = 0;\n"
|
||||
" result.x = remquo(input1[gid], input2[gid], &quo);\n"
|
||||
// Specification say:
|
||||
// "remquo also calculates the lower seven bits of the integral quotient x/y,
|
||||
// and gives that value the same sign as x/y. It stores this signed value in
|
||||
// the object pointed to by quo."
|
||||
// Implemenation may save into quo more than seven bits. We need to take
|
||||
// care of that here.
|
||||
" sign = (quo < 0) ? -1 : 1;\n"
|
||||
" quo = (quo < 0) ? -quo : quo;\n"
|
||||
" quo &= 0x0000007f;\n"
|
||||
" result.y = (sign < 0) ? -quo : quo;\n"
|
||||
" output[gid] = result;\n"
|
||||
"}\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
// -------------- TERNARY FUNCTIONS
|
||||
|
||||
// gentype fma(gentype a, gentype b, gentype c);
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2, min3, max3
|
||||
MATH_FUNCS_DEFINE_TERNARY_FUNC(fp, fma, std::fma, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f, -1000.0f, 1000.0f)
|
||||
|
||||
// floating point functions
|
||||
AUTO_TEST_CASE(test_fp_funcs)
|
||||
(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
|
||||
{
|
||||
int error = CL_SUCCESS;
|
||||
int last_error = CL_SUCCESS;
|
||||
|
||||
// Check for EMBEDDED_PROFILE
|
||||
bool is_embedded_profile = false;
|
||||
char profile[128];
|
||||
last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL);
|
||||
RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo")
|
||||
if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0)
|
||||
is_embedded_profile = true;
|
||||
|
||||
// gentype ceil(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((fp_func_ceil(is_embedded_profile)))
|
||||
// gentype floor(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((fp_func_floor(is_embedded_profile)))
|
||||
// gentype rint(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((fp_func_rint(is_embedded_profile)))
|
||||
// gentype round(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((fp_func_round(is_embedded_profile)))
|
||||
// gentype trunc(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((fp_func_trunc(is_embedded_profile)))
|
||||
|
||||
// floatn nan(uintn nancode);
|
||||
TEST_UNARY_FUNC_MACRO((fp_func_nan()))
|
||||
|
||||
// gentype fract(gentype x, gentype* iptr);
|
||||
TEST_UNARY_FUNC_MACRO((fp_func_fract(is_embedded_profile)))
|
||||
// gentype modf(gentype x, gentype* iptr);
|
||||
TEST_UNARY_FUNC_MACRO((fp_func_modf(is_embedded_profile)))
|
||||
// gentype frexp(gentype x, intn* exp);
|
||||
TEST_UNARY_FUNC_MACRO((fp_func_frexp(is_embedded_profile)))
|
||||
|
||||
// gentype remainder(gentype x, gentype y);
|
||||
TEST_BINARY_FUNC_MACRO((fp_func_remainder(is_embedded_profile)))
|
||||
// gentype copysign(gentype x, gentype y);
|
||||
TEST_BINARY_FUNC_MACRO((fp_func_copysign(is_embedded_profile)))
|
||||
// gentype fmod(gentype x, gentype y);
|
||||
TEST_BINARY_FUNC_MACRO((fp_func_fmod(is_embedded_profile)))
|
||||
|
||||
// gentype nextafter(gentype x, gentype y);
|
||||
TEST_BINARY_FUNC_MACRO((fp_func_nextafter(is_embedded_profile)))
|
||||
|
||||
// gentype remquo(gentype x, gentype y, intn* quo);
|
||||
TEST_BINARY_FUNC_MACRO((fp_func_remquo(is_embedded_profile)))
|
||||
|
||||
// gentype fma(gentype a, gentype b, gentype c);
|
||||
TEST_TERNARY_FUNC_MACRO((fp_func_fma(is_embedded_profile)))
|
||||
|
||||
if(error != CL_SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_FP_FUNCS_HPP
|
||||
106
test_conformance/clcpp/math_funcs/half_math_funcs.hpp
Normal file
106
test_conformance/clcpp/math_funcs/half_math_funcs.hpp
Normal file
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_HALF_MATH_FUNCS_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_HALF_MATH_FUNCS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, cos, half_cos, std::cos, true, 8192.0f, 8192.0f, 0.1f, -CL_M_PI_F, CL_M_PI_F)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, sin, half_sin, std::sin, true, 8192.0f, 8192.0f, 0.1f, -CL_M_PI_F, CL_M_PI_F)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, tan, half_tan, std::tan, true, 8192.0f, 8192.0f, 0.1f, -CL_M_PI_F, CL_M_PI_F)
|
||||
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, exp, half_exp, std::exp, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, exp2, half_exp2, std::exp2, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, exp10, half_exp10, reference::exp10, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, log, half_log, std::log, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, log2, half_log2, std::log2, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, log10, half_log10, std::log10, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, rsqrt, half_rsqrt, reference::rsqrt, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, sqrt, half_sqrt, std::sqrt, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, recip, half_recip, reference::recip, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC1(half_math, divide, half_divide, reference::divide, true, 8192.0f, 8192.0f, 0.1f, -1024.0f, 1024.0f, -1024.0f, 1024.0f)
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC1(half_math, powr, half_powr, reference::powr, true, 8192.0f, 8192.0f, 0.1f, -1024.0f, 1024.0f, -1024.0f, 1024.0f)
|
||||
#else
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, cos, half_math::cos, std::cos, true, 8192.0f, 8192.0f, 0.1f, -CL_M_PI_F, CL_M_PI_F)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, sin, half_math::sin, std::sin, true, 8192.0f, 8192.0f, 0.1f, -CL_M_PI_F, CL_M_PI_F)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, tan, half_math::tan, std::tan, true, 8192.0f, 8192.0f, 0.1f, -CL_M_PI_F, CL_M_PI_F)
|
||||
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, exp, half_math::exp, std::exp, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, exp2, half_math::exp2, std::exp2, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, exp10, half_math::exp10, reference::exp10, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, log, half_math::log, std::log, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, log2, half_math::log2, std::log2, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, log10, half_math::log10, std::log10, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, rsqrt, half_math::rsqrt, reference::rsqrt, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, sqrt, half_math::sqrt, std::sqrt, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC1(half_math, recip, half_math::recip, reference::recip, true, 8192.0f, 8192.0f, 0.1f, -1000.0f, 1000.0f)
|
||||
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC1(half_math, divide, half_math::divide, reference::divide, true, 8192.0f, 8192.0f, 0.1f, -1024.0f, 1024.0f, -1024.0f, 1024.0f)
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC1(half_math, powr, half_math::powr, reference::powr, true, 8192.0f, 8192.0f, 0.1f, -1024.0f, 1024.0f, -1024.0f, 1024.0f)
|
||||
#endif
|
||||
|
||||
// comparison functions
|
||||
AUTO_TEST_CASE(test_half_math_funcs)
|
||||
(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
|
||||
{
|
||||
int error = CL_SUCCESS;
|
||||
int last_error = CL_SUCCESS;
|
||||
|
||||
// Check for EMBEDDED_PROFILE
|
||||
bool is_embedded_profile = false;
|
||||
char profile[128];
|
||||
last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL);
|
||||
RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo")
|
||||
if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0)
|
||||
is_embedded_profile = true;
|
||||
|
||||
TEST_UNARY_FUNC_MACRO((half_math_func_cos(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((half_math_func_sin(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((half_math_func_tan(is_embedded_profile)))
|
||||
|
||||
TEST_UNARY_FUNC_MACRO((half_math_func_exp(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((half_math_func_exp2(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((half_math_func_exp10(is_embedded_profile)))
|
||||
|
||||
TEST_UNARY_FUNC_MACRO((half_math_func_log(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((half_math_func_log2(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((half_math_func_log10(is_embedded_profile)))
|
||||
|
||||
TEST_BINARY_FUNC_MACRO((half_math_func_divide(is_embedded_profile)))
|
||||
|
||||
if(error != CL_SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_HALF_MATH_FUNCS_HPP
|
||||
260
test_conformance/clcpp/math_funcs/logarithmic_funcs.hpp
Normal file
260
test_conformance/clcpp/math_funcs/logarithmic_funcs.hpp
Normal file
@@ -0,0 +1,260 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_LOG_FUNCS_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_LOG_FUNCS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This function reads values of FP_ILOGB0 and FP_ILOGBNAN macros defined on the device.
|
||||
// OpenCL C++ Spec:
|
||||
// The value of FP_ILOGB0 shall be either {INT_MIN} or {INT_MAX}. The value of FP_ILOGBNAN
|
||||
// shall be either {INT_MAX} or {INT_MIN}.
|
||||
int get_ilogb_nan_zero(cl_device_id device, cl_context context, cl_command_queue queue, cl_int& ilogb_nan, cl_int& ilogb_zero)
|
||||
{
|
||||
cl_mem buffers[1];
|
||||
cl_program program;
|
||||
cl_kernel kernel;
|
||||
size_t work_size[1];
|
||||
int err;
|
||||
|
||||
std::string code_str =
|
||||
"__kernel void get_ilogb_nan_zero(__global int *out)\n"
|
||||
"{\n"
|
||||
" out[0] = FP_ILOGB0;\n"
|
||||
" out[1] = FP_ILOGBNAN;\n"
|
||||
"}\n";
|
||||
std::string kernel_name("get_ilogb_nan_zero");
|
||||
|
||||
err = create_opencl_kernel(context, &program, &kernel, code_str, kernel_name, "-cl-std=CL2.0", false);
|
||||
RETURN_ON_ERROR(err)
|
||||
|
||||
std::vector<cl_int> output = generate_output<cl_int>(2);
|
||||
|
||||
buffers[0] = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(cl_int) * output.size(), NULL, &err);
|
||||
RETURN_ON_CL_ERROR(err, "clCreateBuffer")
|
||||
|
||||
err = clSetKernelArg(kernel, 0, sizeof(buffers[0]), &buffers[0]);
|
||||
RETURN_ON_CL_ERROR(err, "clSetKernelArg");
|
||||
|
||||
work_size[0] = 1;
|
||||
err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, work_size, NULL, 0, NULL, NULL);
|
||||
RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel");
|
||||
|
||||
err = clEnqueueReadBuffer(
|
||||
queue, buffers[0], CL_TRUE, 0, sizeof(cl_int) * output.size(),
|
||||
static_cast<void *>(output.data()), 0, NULL, NULL
|
||||
);
|
||||
RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer");
|
||||
|
||||
// Save
|
||||
ilogb_zero = output[0];
|
||||
ilogb_nan = output[1];
|
||||
|
||||
clReleaseMemObject(buffers[0]);
|
||||
clReleaseKernel(kernel);
|
||||
clReleaseProgram(program);
|
||||
return err;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
struct logarithmic_func_ilogb : public unary_func<cl_float, cl_int>
|
||||
{
|
||||
logarithmic_func_ilogb(cl_int ilogb_nan, cl_int ilogb_zero)
|
||||
: m_ilogb_nan(ilogb_nan), m_ilogb_zero(ilogb_zero)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
return "ilogb";
|
||||
}
|
||||
|
||||
std::string headers()
|
||||
{
|
||||
return "#include <opencl_math>\n";
|
||||
}
|
||||
|
||||
cl_int operator()(const cl_float& x)
|
||||
{
|
||||
if((std::isnan)(x))
|
||||
{
|
||||
return m_ilogb_nan;
|
||||
}
|
||||
else if(x == 0.0 || x == -0.0)
|
||||
{
|
||||
return m_ilogb_zero;
|
||||
}
|
||||
static_assert(
|
||||
sizeof(cl_int) == sizeof(int),
|
||||
"Tests assumes that sizeof(cl_int) == sizeof(int)"
|
||||
);
|
||||
return (std::ilogb)(x);
|
||||
}
|
||||
|
||||
cl_float min1()
|
||||
{
|
||||
return -100.0f;
|
||||
}
|
||||
|
||||
cl_float max1()
|
||||
{
|
||||
return 1000.0f;
|
||||
}
|
||||
|
||||
std::vector<cl_float> in1_special_cases()
|
||||
{
|
||||
return {
|
||||
cl_float(0.0f),
|
||||
cl_float(-0.0f),
|
||||
cl_float(1.0f),
|
||||
cl_float(-1.0f),
|
||||
cl_float(2.0f),
|
||||
cl_float(-2.0f),
|
||||
std::numeric_limits<cl_float>::infinity(),
|
||||
-std::numeric_limits<cl_float>::infinity(),
|
||||
std::numeric_limits<cl_float>::quiet_NaN()
|
||||
};
|
||||
}
|
||||
private:
|
||||
cl_int m_ilogb_nan;
|
||||
cl_int m_ilogb_zero;
|
||||
};
|
||||
|
||||
// gentype log(gentype x);
|
||||
// gentype logb(gentype x);
|
||||
// gentype log2(gentype x);
|
||||
// gentype log10(gentype x);
|
||||
// gentype log1p(gentype x);
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, log, std::log, true, 3.0f, 4.0f, 0.001f, -10.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, logb, std::logb, true, 0.0f, 0.0f, 0.001f, -10.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, log2, std::log2, true, 3.0f, 4.0f, 0.001f, -10.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, log10, std::log10, true, 3.0f, 4.0f, 0.001f, -10.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, log1p, std::log1p, true, 2.0f, 4.0f, 0.001f, -10.0f, 1000.0f)
|
||||
|
||||
// gentype lgamma(gentype x);
|
||||
// OpenCL C++ Spec.:
|
||||
// The ULP values for built-in math functions lgamma and lgamma_r is currently undefined.
|
||||
// Because of that we don't check ULP and set acceptable delta to 0.2f (20%).
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, lgamma, std::lgamma, false, 0.0f, 0.0f, 0.2f, -10.0f, 1000.0f)
|
||||
|
||||
// gentype lgamma_r(gentype x, intn* signp);
|
||||
// OpenCL C++ Spec.:
|
||||
// The ULP values for built-in math functions lgamma and lgamma_r is currently undefined.
|
||||
// Because of that we don't check ULP and set acceptable delta to 0.2f (20%).
|
||||
//
|
||||
// Note:
|
||||
// We DO NOT test if sign of the gamma function return by lgamma_r is correct.
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(logarithmic, lgamma_r, std::lgamma, false, 0.0f, 0.0f, 0.2f, -10.0f, 1000.0f)
|
||||
|
||||
// We need to specialize generate_kernel_unary<>() function template for logarithmic_func_lgamma_r
|
||||
// because it takes two arguments, but only one of it is input, the 2nd one is used to return
|
||||
// the sign of the gamma function.
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
|
||||
template <>
|
||||
std::string generate_kernel_unary<logarithmic_func_lgamma_r, cl_float, cl_float>(logarithmic_func_lgamma_r func)
|
||||
{
|
||||
return
|
||||
"__kernel void test_lgamma_r(global float *input, global float *output)\n"
|
||||
"{\n"
|
||||
" size_t gid = get_global_id(0);\n"
|
||||
" int sign;\n"
|
||||
" output[gid] = lgamma_r(input[gid], &sign);\n"
|
||||
"}\n";
|
||||
}
|
||||
#else
|
||||
template <>
|
||||
std::string generate_kernel_unary<logarithmic_func_lgamma_r, cl_float, cl_float>(logarithmic_func_lgamma_r func)
|
||||
{
|
||||
return
|
||||
"" + func.defs() +
|
||||
"" + func.headers() +
|
||||
"#include <opencl_memory>\n"
|
||||
"#include <opencl_work_item>\n"
|
||||
"using namespace cl;\n"
|
||||
"__kernel void test_lgamma_r(global_ptr<float[]> input, global_ptr<float[]> output)\n"
|
||||
"{\n"
|
||||
" size_t gid = get_global_id(0);\n"
|
||||
" int sign;\n"
|
||||
" output[gid] = lgamma_r(input[gid], &sign);\n"
|
||||
"}\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
// logarithmic functions
|
||||
AUTO_TEST_CASE(test_logarithmic_funcs)
|
||||
(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
|
||||
{
|
||||
int error = CL_SUCCESS;
|
||||
int last_error = CL_SUCCESS;
|
||||
|
||||
// Check for EMBEDDED_PROFILE
|
||||
bool is_embedded_profile = false;
|
||||
char profile[128];
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL);
|
||||
RETURN_ON_CL_ERROR(error, "clGetDeviceInfo")
|
||||
if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0)
|
||||
is_embedded_profile = true;
|
||||
|
||||
// Write values of FP_ILOGB0 and FP_ILOGBNAN, which are macros defined on the device, to
|
||||
// ilogb_zero and ilogb_nan.
|
||||
cl_int ilogb_nan = 0;
|
||||
cl_int ilogb_zero = 0;
|
||||
error = detail::get_ilogb_nan_zero(device, context, queue, ilogb_nan, ilogb_zero);
|
||||
RETURN_ON_ERROR_MSG(error, "detail::get_ilogb_nan_zero function failed");
|
||||
|
||||
// intn ilogb(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((logarithmic_func_ilogb(ilogb_nan, ilogb_zero)))
|
||||
|
||||
// gentype log(gentype x);
|
||||
// gentype logb(gentype x);
|
||||
// gentype log2(gentype x);
|
||||
// gentype log10(gentype x);
|
||||
// gentype log1p(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((logarithmic_func_log(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((logarithmic_func_logb(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((logarithmic_func_log2(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((logarithmic_func_log10(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((logarithmic_func_log1p(is_embedded_profile)))
|
||||
|
||||
// gentype lgamma(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((logarithmic_func_lgamma(is_embedded_profile)))
|
||||
|
||||
// gentype lgamma(gentype x);
|
||||
//
|
||||
// Note:
|
||||
// We DO NOT test if sign of the gamma function return by lgamma_r is correct
|
||||
TEST_UNARY_FUNC_MACRO((logarithmic_func_lgamma_r(is_embedded_profile)))
|
||||
|
||||
if(error != CL_SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_LOG_FUNCS_HPP
|
||||
55
test_conformance/clcpp/math_funcs/main.cpp
Normal file
55
test_conformance/clcpp/math_funcs/main.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include <limits>
|
||||
|
||||
#include "../common.hpp"
|
||||
|
||||
#include "comparison_funcs.hpp"
|
||||
#include "exponential_funcs.hpp"
|
||||
#include "floating_point_funcs.hpp"
|
||||
#include "half_math_funcs.hpp"
|
||||
#include "logarithmic_funcs.hpp"
|
||||
#include "other_funcs.hpp"
|
||||
#include "power_funcs.hpp"
|
||||
#include "trigonometric_funcs.hpp"
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
// Check if cl_float (float) and cl_double (double) fulfill the requirements of
|
||||
// IEC 559 (IEEE 754) standard. This is required for the tests to run correctly.
|
||||
if(!std::numeric_limits<cl_float>::is_iec559)
|
||||
{
|
||||
RETURN_ON_ERROR_MSG(-1,
|
||||
"cl_float (float) does not fulfill the requirements of IEC 559 (IEEE 754) standard. "
|
||||
"Tests won't run correctly."
|
||||
);
|
||||
}
|
||||
if(!std::numeric_limits<cl_double>::is_iec559)
|
||||
{
|
||||
RETURN_ON_ERROR_MSG(-1,
|
||||
"cl_double (double) does not fulfill the requirements of IEC 559 (IEEE 754) standard. "
|
||||
"Tests won't run correctly."
|
||||
);
|
||||
}
|
||||
|
||||
// Get list to all test functions
|
||||
std::vector<basefn> testfn_list = autotest::test_suite::get_test_functions();
|
||||
// Get names of all test functions
|
||||
std::vector<std::string> testfn_names = autotest::test_suite::get_test_names();
|
||||
// Create a vector of pointers to the names test functions
|
||||
std::vector<const char *> testfn_names_c_str = autotest::get_strings_ptrs(testfn_names);
|
||||
return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0);
|
||||
}
|
||||
75
test_conformance/clcpp/math_funcs/other_funcs.hpp
Normal file
75
test_conformance/clcpp/math_funcs/other_funcs.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_OTHER_FUNCS_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_OTHER_FUNCS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(other, erfc, std::erfc, true, 16.0f, 16.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(other, erf, std::erf, true, 16.0f, 16.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(other, fabs, std::fabs, true, 0.0f, 0.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(other, tgamma, std::tgamma, true, 16.0f, 16.0f, 0.001f, -1000.0f, 1000.0f)
|
||||
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(other, hypot, std::hypot, true, 4.0f, 4.0f, 0.001f, -1000.0f, 1000.0f, -1000.0f, 1000.0f)
|
||||
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2, min3, max3
|
||||
MATH_FUNCS_DEFINE_TERNARY_FUNC(other, mad, reference::mad, false, 0.0f, 0.0f, 0.1f, -10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 10.0f)
|
||||
|
||||
// other functions
|
||||
AUTO_TEST_CASE(test_other_funcs)
|
||||
(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
|
||||
{
|
||||
int error = CL_SUCCESS;
|
||||
int last_error = CL_SUCCESS;
|
||||
|
||||
// Check for EMBEDDED_PROFILE
|
||||
bool is_embedded_profile = false;
|
||||
char profile[128];
|
||||
last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL);
|
||||
RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo")
|
||||
if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0)
|
||||
is_embedded_profile = true;
|
||||
|
||||
// gentype erf(gentype x);
|
||||
// gentype erfc(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((other_func_erfc(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((other_func_erf(is_embedded_profile)))
|
||||
|
||||
// gentype fabs(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((other_func_fabs(is_embedded_profile)))
|
||||
|
||||
// gentype tgamma(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((other_func_tgamma(is_embedded_profile)))
|
||||
|
||||
// gentype hypot(gentype x, gentype y);
|
||||
TEST_BINARY_FUNC_MACRO((other_func_hypot(is_embedded_profile)))
|
||||
|
||||
// gentype mad(gentype a, gentype b, gentype c);
|
||||
TEST_TERNARY_FUNC_MACRO((other_func_mad(is_embedded_profile)))
|
||||
|
||||
if(error != CL_SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_OTHER_FUNCS_HPP
|
||||
153
test_conformance/clcpp/math_funcs/power_funcs.hpp
Normal file
153
test_conformance/clcpp/math_funcs/power_funcs.hpp
Normal file
@@ -0,0 +1,153 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_POWER_FUNCS_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_POWER_FUNCS_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#define DEFINE_BINARY_POWER_FUNC_INT(NAME, HOST_FUNC, USE_ULP, ULP, ULP_EMBEDDED, MIN1, MAX1, MIN2, MAX2) \
|
||||
struct power_func_ ## NAME : public binary_func<cl_float, cl_int, cl_float> \
|
||||
{ \
|
||||
power_func_ ## NAME(bool is_embedded) : m_is_embedded(is_embedded) \
|
||||
{ \
|
||||
\
|
||||
} \
|
||||
\
|
||||
std::string str() \
|
||||
{ \
|
||||
return #NAME; \
|
||||
} \
|
||||
\
|
||||
std::string headers() \
|
||||
{ \
|
||||
return "#include <opencl_math>\n"; \
|
||||
} \
|
||||
/* Reference value type is cl_double */ \
|
||||
cl_double operator()(const cl_float& x, const cl_int& y) \
|
||||
{ \
|
||||
return (HOST_FUNC)(static_cast<cl_double>(x), y); \
|
||||
} \
|
||||
\
|
||||
cl_float min1() \
|
||||
{ \
|
||||
return MIN1; \
|
||||
} \
|
||||
\
|
||||
cl_float max1() \
|
||||
{ \
|
||||
return MAX1; \
|
||||
} \
|
||||
\
|
||||
cl_int min2() \
|
||||
{ \
|
||||
return MIN2; \
|
||||
} \
|
||||
\
|
||||
cl_int max2() \
|
||||
{ \
|
||||
return MAX2; \
|
||||
} \
|
||||
\
|
||||
std::vector<cl_float> in1_special_cases() \
|
||||
{ \
|
||||
return { \
|
||||
cl_float(-1.0f), \
|
||||
cl_float(0.0f), \
|
||||
cl_float(-0.0f), \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
std::vector<cl_int> in2_special_cases() \
|
||||
{ \
|
||||
return { \
|
||||
2, 3, -1, 1, -2, 2 \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
bool use_ulp() \
|
||||
{ \
|
||||
return USE_ULP; \
|
||||
} \
|
||||
\
|
||||
float ulp() \
|
||||
{ \
|
||||
if(m_is_embedded) \
|
||||
{ \
|
||||
return ULP_EMBEDDED; \
|
||||
} \
|
||||
return ULP; \
|
||||
} \
|
||||
private: \
|
||||
bool m_is_embedded; \
|
||||
};
|
||||
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(power, cbrt, std::cbrt, true, 2.0f, 4.0f, 0.001f, -1000.0f, -9.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(power, rsqrt, reference::rsqrt, true, 2.0f, 4.0f, 0.001f, 1.0f, 100.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(power, sqrt, std::sqrt, true, 3.0f, 4.0f, 0.001f, 1.0f, 100.0f)
|
||||
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(power, pow, std::pow, true, 16.0f, 16.0f, 0.001f, 1.0f, 100.0f, 1.0f, 10.0f)
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(power, powr, reference::powr, true, 16.0f, 16.0f, 0.001f, 1.0f, 100.0f, 1.0f, 10.0f)
|
||||
|
||||
// func_name, reference_func, use_ulp, ulp, ulp_for_embedded, min1, max1, min2, max2
|
||||
DEFINE_BINARY_POWER_FUNC_INT(pown, std::pow, true, 16.0f, 16.0f, 1.0f, 100.0f, 1, 10)
|
||||
DEFINE_BINARY_POWER_FUNC_INT(rootn, reference::rootn, true, 16.0f, 16.0f, -100.0f, 100.0f, -10, 10)
|
||||
|
||||
// power functions
|
||||
AUTO_TEST_CASE(test_power_funcs)
|
||||
(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
|
||||
{
|
||||
int error = CL_SUCCESS;
|
||||
int last_error = CL_SUCCESS;
|
||||
|
||||
// Check for EMBEDDED_PROFILE
|
||||
bool is_embedded_profile = false;
|
||||
char profile[128];
|
||||
last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL);
|
||||
RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo")
|
||||
if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0)
|
||||
is_embedded_profile = true;
|
||||
|
||||
// gentype cbrt(gentype x);
|
||||
// gentype rsqrt(gentype x);
|
||||
// gentype sqrt(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((power_func_cbrt(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((power_func_sqrt(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((power_func_rsqrt(is_embedded_profile)))
|
||||
|
||||
// gentype pow(gentype x, gentype y);
|
||||
// gentype powr(gentype x, gentype y);
|
||||
TEST_BINARY_FUNC_MACRO((power_func_pow(is_embedded_profile)))
|
||||
TEST_BINARY_FUNC_MACRO((power_func_powr(is_embedded_profile)))
|
||||
|
||||
// gentype pown(gentype x, intn y);
|
||||
// gentype rootn(gentype x, intn y);
|
||||
TEST_BINARY_FUNC_MACRO((power_func_pown(is_embedded_profile)))
|
||||
TEST_BINARY_FUNC_MACRO((power_func_rootn(is_embedded_profile)))
|
||||
|
||||
if(error != CL_SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_POWER_FUNCS_HPP
|
||||
315
test_conformance/clcpp/math_funcs/reference.hpp
Normal file
315
test_conformance/clcpp/math_funcs/reference.hpp
Normal file
@@ -0,0 +1,315 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_REFERENCE_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_REFERENCE_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include "../common.hpp"
|
||||
|
||||
namespace reference
|
||||
{
|
||||
// Reference functions for OpenCL comparison functions that
|
||||
// are not already defined in STL.
|
||||
cl_float maxmag(const cl_float& x, const cl_float& y)
|
||||
{
|
||||
if((std::abs)(x) > (std::abs)(y))
|
||||
{
|
||||
return x;
|
||||
}
|
||||
else if((std::abs)(y) > (std::abs)(x))
|
||||
{
|
||||
return y;
|
||||
}
|
||||
return (std::fmax)(x, y);
|
||||
}
|
||||
|
||||
cl_float minmag(const cl_float& x, const cl_float& y)
|
||||
{
|
||||
if((std::abs)(x) < (std::abs)(y))
|
||||
{
|
||||
return x;
|
||||
}
|
||||
else if((std::abs)(y) < (std::abs)(x))
|
||||
{
|
||||
return y;
|
||||
}
|
||||
return (std::fmin)(x, y);
|
||||
}
|
||||
|
||||
// Reference functions for OpenCL exp functions that
|
||||
// are not already defined in STL.
|
||||
cl_double exp10(const cl_double& x)
|
||||
{
|
||||
// 10^x = exp2( x * log2(10) )
|
||||
auto log2_10 = (std::log2)(static_cast<long double>(10.0));
|
||||
cl_double x_log2_10 = static_cast<cl_double>(x * log2_10);
|
||||
return (std::exp2)(x_log2_10);
|
||||
}
|
||||
|
||||
// Reference functions for OpenCL floating point functions that
|
||||
// are not already defined in STL.
|
||||
cl_double2 fract(cl_double x)
|
||||
{
|
||||
// Copied from math_brute_force/reference_math.c
|
||||
cl_double2 r;
|
||||
if((std::isnan)(x))
|
||||
{
|
||||
r.s[0] = std::numeric_limits<cl_double>::quiet_NaN();
|
||||
r.s[1] = std::numeric_limits<cl_double>::quiet_NaN();
|
||||
return r;
|
||||
}
|
||||
|
||||
r.s[0] = (std::modf)(x, &(r.s[1]));
|
||||
if(r.s[0] < 0.0 )
|
||||
{
|
||||
r.s[0] = 1.0f + r.s[0];
|
||||
r.s[1] -= 1.0f;
|
||||
if( r.s[0] == 1.0f )
|
||||
r.s[0] = HEX_FLT(+, 1, fffffe, -, 1);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
cl_double2 remquo(cl_double x, cl_double y)
|
||||
{
|
||||
cl_double2 r;
|
||||
// remquo return the same value that is returned by the
|
||||
// remainder function
|
||||
r.s[0] = (std::remainder)(x,y);
|
||||
// calulcate quo
|
||||
cl_double x_y = (x - r.s[0]) / y;
|
||||
cl_uint quo = (std::abs)(x_y);
|
||||
r.s[1] = quo & 0x0000007fU;
|
||||
if(x_y < 0.0)
|
||||
r.s[1] = -r.s[1];
|
||||
|
||||
// fix edge cases
|
||||
if(!(std::isnan)(x) && y == 0.0)
|
||||
{
|
||||
r.s[1] = 0;
|
||||
}
|
||||
else if((std::isnan)(x) && (std::isnan)(y))
|
||||
{
|
||||
r.s[1] = 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
// Reference functions for OpenCL half_math:: functions that
|
||||
// are not already defined in STL.
|
||||
cl_double divide(cl_double x, cl_double y)
|
||||
{
|
||||
return x / y;
|
||||
}
|
||||
|
||||
cl_double recip(cl_double x)
|
||||
{
|
||||
return 1.0 / x;
|
||||
}
|
||||
|
||||
// Reference functions for OpenCL other functions that
|
||||
// are not already defined in STL.
|
||||
cl_double mad(cl_double x, cl_double y, cl_double z)
|
||||
{
|
||||
return (x * y) + z;
|
||||
}
|
||||
|
||||
// Reference functions for OpenCL power functions that
|
||||
// are not already defined in STL.
|
||||
cl_double rsqrt(const cl_double& x)
|
||||
{
|
||||
return cl_double(1.0) / ((std::sqrt)(x));
|
||||
}
|
||||
|
||||
cl_double powr(const cl_double& x, const cl_double& y)
|
||||
{
|
||||
//powr(x, y) returns NaN for x < 0.
|
||||
if( x < 0.0 )
|
||||
return std::numeric_limits<cl_double>::quiet_NaN();
|
||||
|
||||
//powr ( x, NaN ) returns the NaN for x >= 0.
|
||||
//powr ( NaN, y ) returns the NaN.
|
||||
if((std::isnan)(x) || (std::isnan)(y) )
|
||||
return std::numeric_limits<cl_double>::quiet_NaN();
|
||||
|
||||
if( x == 1.0 )
|
||||
{
|
||||
//powr ( +1, +-inf ) returns NaN.
|
||||
if((std::abs)(y) == INFINITY )
|
||||
return std::numeric_limits<cl_double>::quiet_NaN();
|
||||
|
||||
//powr ( +1, y ) is 1 for finite y. (NaN handled above)
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
if( y == 0.0 )
|
||||
{
|
||||
//powr ( +inf, +-0 ) returns NaN.
|
||||
//powr ( +-0, +-0 ) returns NaN.
|
||||
if( x == 0.0 || x == std::numeric_limits<cl_double>::infinity())
|
||||
return std::numeric_limits<cl_double>::quiet_NaN();
|
||||
|
||||
//powr ( x, +-0 ) is 1 for finite x > 0. (x <= 0, NaN, INF already handled above)
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
if( x == 0.0 )
|
||||
{
|
||||
//powr ( +-0, -inf) is +inf.
|
||||
//powr ( +-0, y ) is +inf for finite y < 0.
|
||||
if( y < 0.0 )
|
||||
return std::numeric_limits<cl_double>::infinity();
|
||||
|
||||
//powr ( +-0, y ) is +0 for y > 0. (NaN, y==0 handled above)
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// x = +inf
|
||||
if( (std::isinf)(x) )
|
||||
{
|
||||
if( y < 0 )
|
||||
return 0;
|
||||
return std::numeric_limits<cl_double>::infinity();
|
||||
}
|
||||
|
||||
double fabsx = (std::abs)(x);
|
||||
double fabsy = (std::abs)(y);
|
||||
|
||||
//y = +-inf cases
|
||||
if( (std::isinf)(fabsy) )
|
||||
{
|
||||
if( y < 0.0 )
|
||||
{
|
||||
if( fabsx < 1.0 )
|
||||
return std::numeric_limits<cl_double>::infinity();
|
||||
return 0;
|
||||
}
|
||||
if( fabsx < 1.0 )
|
||||
return 0.0;
|
||||
return std::numeric_limits<cl_double>::infinity();
|
||||
}
|
||||
return (std::pow)(x, y);
|
||||
}
|
||||
|
||||
cl_double rootn(const cl_double& x, const cl_int n)
|
||||
{
|
||||
//rootn (x, 0) returns a NaN.
|
||||
if(n == 0)
|
||||
return std::numeric_limits<cl_double>::quiet_NaN();
|
||||
|
||||
//rootn ( x, n ) returns a NaN for x < 0 and n is even.
|
||||
if(x < 0 && 0 == (n & 1))
|
||||
return std::numeric_limits<cl_double>::quiet_NaN();
|
||||
|
||||
if(x == 0.0)
|
||||
{
|
||||
if(n > 0)
|
||||
{
|
||||
//rootn ( +-0, n ) is +0 for even n > 0.
|
||||
if(0 == (n & 1))
|
||||
{
|
||||
return cl_double(0.0);
|
||||
}
|
||||
//rootn ( +-0, n ) is +-0 for odd n > 0.
|
||||
else
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//rootn ( +-0, n ) is +inf for even n < 0.
|
||||
if(0 == ((-n) & 1))
|
||||
{
|
||||
return std::numeric_limits<cl_double>::infinity();
|
||||
}
|
||||
//rootn ( +-0, n ) is +-inf for odd n < 0.
|
||||
else
|
||||
{
|
||||
return (std::copysign)(
|
||||
std::numeric_limits<cl_double>::infinity(), x
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cl_double r = (std::abs)(x);
|
||||
r = (std::exp2)((std::log2)(r) / static_cast<cl_double>(n));
|
||||
return (std::copysign)(r, x);
|
||||
}
|
||||
|
||||
// Reference functions for OpenCL trigonometric functions that
|
||||
// are not already defined in STL.
|
||||
cl_double acospi(cl_double x)
|
||||
{
|
||||
return (std::acos)(x) / CL_M_PI;
|
||||
}
|
||||
|
||||
cl_double asinpi(cl_double x)
|
||||
{
|
||||
return (std::asin)(x) / CL_M_PI;
|
||||
}
|
||||
|
||||
cl_double atanpi(cl_double x)
|
||||
{
|
||||
return (std::atan)(x) / CL_M_PI;
|
||||
}
|
||||
|
||||
cl_double cospi(cl_double x)
|
||||
{
|
||||
return (std::cos)(x * CL_M_PI);
|
||||
}
|
||||
|
||||
cl_double sinpi(cl_double x)
|
||||
{
|
||||
return (std::sin)(x * CL_M_PI);
|
||||
}
|
||||
|
||||
cl_double tanpi(cl_double x)
|
||||
{
|
||||
return (std::tan)(x * CL_M_PI);
|
||||
}
|
||||
|
||||
cl_double atan2(cl_double x, cl_double y)
|
||||
{
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
// Fix edge cases for Windows
|
||||
if ((std::isinf)(x) && (std::isinf)(y)) {
|
||||
cl_double retval = (y > 0) ? CL_M_PI_4 : 3.f * CL_M_PI_4;
|
||||
return (x > 0) ? retval : -retval;
|
||||
}
|
||||
#endif // defined(WIN32) || defined(_WIN32)
|
||||
return (std::atan2)(x, y);
|
||||
}
|
||||
|
||||
cl_double atan2pi(cl_double x, cl_double y)
|
||||
{
|
||||
return ::reference::atan2(x, y) / CL_M_PI;
|
||||
}
|
||||
|
||||
cl_double2 sincos(cl_double x)
|
||||
{
|
||||
cl_double2 r;
|
||||
r.s[0] = (std::sin)(x);
|
||||
r.s[1] = (std::cos)(x);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_REFERENCE_HPP
|
||||
222
test_conformance/clcpp/math_funcs/trigonometric_funcs.hpp
Normal file
222
test_conformance/clcpp/math_funcs/trigonometric_funcs.hpp
Normal file
@@ -0,0 +1,222 @@
|
||||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_MATH_FUNCS_TRI_FUNCS_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_MATH_FUNCS_TRI_FUNCS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, acos, std::acos, true, 4.0f, 4.0f, 0.001f, -1.0f, 1.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, acosh, std::acosh, true, 4.0f, 4.0f, 0.001f, -1.0f, 1.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, acospi, reference::acospi, true, 5.0f, 5.0f, 0.001f, -1.0f, 1.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, asin, std::asin, true, 4.0f, 4.0f, 0.001f, -1.0f, 1.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, asinh, std::asinh, true, 4.0f, 4.0f, 0.001f, -1.0f, 1.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, asinpi, reference::asinpi, true, 5.0f, 5.0f, 0.001f, -1.0f, 1.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, atan, std::atan, true, 5.0f, 5.0f, 0.001f, -1.0f, 1.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, atanh, std::atanh, true, 5.0f, 5.0f, 0.001f, -1.0f, 1.0f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, atanpi, reference::atanpi, true, 5.0f, 5.0f, 0.001f, -1.0f, 1.0f)
|
||||
|
||||
// For (sin/cos/tan)pi functions min input value is -0.24 and max input value is 0.24,
|
||||
// so (CL_M_PI * x) is never greater than CL_M_PI_F.
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, cos, std::cos, true, 4.0f, 4.0f, 0.001f, -CL_M_PI_F, CL_M_PI_F)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, cosh, std::cosh, true, 4.0f, 4.0f, 0.001f, -CL_M_PI_F, CL_M_PI_F)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, cospi, reference::cospi, true, 4.0f, 4.0f, 0.001f, -0.24, -0.24f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, sin, std::sin, true, 4.0f, 4.0f, 0.001f, -CL_M_PI_F, CL_M_PI_F)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, sinh, std::sinh, true, 4.0f, 4.0f, 0.001f, -CL_M_PI_F, CL_M_PI_F)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, sinpi, reference::sinpi, true, 4.0f, 4.0f, 0.001f, -0.24, -0.24f)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, tan, std::tan, true, 5.0f, 5.0f, 0.001f, -CL_M_PI_F, CL_M_PI_F)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, tanh, std::tanh, true, 5.0f, 5.0f, 0.001f, -CL_M_PI_F, CL_M_PI_F)
|
||||
MATH_FUNCS_DEFINE_UNARY_FUNC(trigonometric, tanpi, reference::tanpi, true, 6.0f, 6.0f, 0.001f, -0.24, -0.24f)
|
||||
|
||||
// group_name, func_name, reference_func, use_ulp, ulp, ulp_for_embedded, max_delta, min1, max1, min2, max2
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(trigonometric, atan2, reference::atan2, true, 6.0f, 6.0f, 0.001f, -1.0f, 1.0f, -1.0f, 1.0f)
|
||||
MATH_FUNCS_DEFINE_BINARY_FUNC(trigonometric, atan2pi, reference::atan2pi, true, 6.0f, 6.0f, 0.001f, -1.0f, 1.0f, -1.0f, 1.0f)
|
||||
|
||||
// gentype sincos(gentype x, gentype * cosval);
|
||||
//
|
||||
// Fact that second argument is a pointer is inconvenient.
|
||||
//
|
||||
// We don't want to modify all helper functions defined in funcs_test_utils.hpp
|
||||
// that run test kernels generated based on this class and check if results are
|
||||
// correct, so instead of having two output cl_float buffers, one for sines and
|
||||
// one for cosines values, we use one cl_float2 output buffer (first component is
|
||||
// sine, second is cosine).
|
||||
//
|
||||
// Below we also define specialization of generate_kernel_unary function template
|
||||
// for trigonometric_func_sincos.
|
||||
struct trigonometric_func_sincos : public unary_func<cl_float, cl_float2>
|
||||
{
|
||||
trigonometric_func_sincos(bool is_embedded) : m_is_embedded(is_embedded)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
return "sincos";
|
||||
}
|
||||
|
||||
std::string headers()
|
||||
{
|
||||
return "#include <opencl_math>\n";
|
||||
}
|
||||
|
||||
/* Reference value type is cl_double */
|
||||
cl_double2 operator()(const cl_float& x)
|
||||
{
|
||||
return (reference::sincos)(static_cast<cl_double>(x));
|
||||
}
|
||||
|
||||
cl_float min1()
|
||||
{
|
||||
return -CL_M_PI_F;
|
||||
}
|
||||
|
||||
cl_float max1()
|
||||
{
|
||||
return CL_M_PI_F;
|
||||
}
|
||||
|
||||
bool use_ulp()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
float ulp()
|
||||
{
|
||||
if(m_is_embedded)
|
||||
{
|
||||
return 4.0f;
|
||||
}
|
||||
return 4.0f;
|
||||
}
|
||||
private:
|
||||
bool m_is_embedded;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
|
||||
template <>
|
||||
std::string generate_kernel_unary<trigonometric_func_sincos, cl_float, cl_float2>(trigonometric_func_sincos func)
|
||||
{
|
||||
return
|
||||
"__kernel void test_sincos(global float *input, global float2 *output)\n"
|
||||
"{\n"
|
||||
" size_t gid = get_global_id(0);\n"
|
||||
" float2 sine_cosine_of_x;\n"
|
||||
" float cosine_of_x = 0;\n"
|
||||
" sine_cosine_of_x.x = sincos(input[gid], &(cosine_of_x));\n"
|
||||
" sine_cosine_of_x.y = cosine_of_x;\n"
|
||||
" output[gid] = sine_cosine_of_x;\n"
|
||||
"}\n";
|
||||
}
|
||||
#else
|
||||
template <>
|
||||
std::string generate_kernel_unary<trigonometric_func_sincos, cl_float, cl_float2>(trigonometric_func_sincos func)
|
||||
{
|
||||
return
|
||||
"" + func.defs() +
|
||||
"" + func.headers() +
|
||||
"#include <opencl_memory>\n"
|
||||
"#include <opencl_work_item>\n"
|
||||
"using namespace cl;\n"
|
||||
"__kernel void test_sincos(global_ptr<float[]> input, global_ptr<float2[]> output)\n"
|
||||
"{\n"
|
||||
" size_t gid = get_global_id(0);\n"
|
||||
" float2 sine_cosine_of_x;\n"
|
||||
" float cosine_of_x = 0;\n"
|
||||
" sine_cosine_of_x.x = sincos(input[gid], &(cosine_of_x));\n"
|
||||
" sine_cosine_of_x.y = cosine_of_x;\n"
|
||||
" output[gid] = sine_cosine_of_x;\n"
|
||||
"}\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
// trigonometric functions
|
||||
AUTO_TEST_CASE(test_trigonometric_funcs)
|
||||
(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
|
||||
{
|
||||
int error = CL_SUCCESS;
|
||||
int last_error = CL_SUCCESS;
|
||||
|
||||
// Check for EMBEDDED_PROFILE
|
||||
bool is_embedded_profile = false;
|
||||
char profile[128];
|
||||
last_error = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), (void *)&profile, NULL);
|
||||
RETURN_ON_CL_ERROR(last_error, "clGetDeviceInfo")
|
||||
if (std::strcmp(profile, "EMBEDDED_PROFILE") == 0)
|
||||
is_embedded_profile = true;
|
||||
|
||||
// gentype acos(gentype x);
|
||||
// gentype acosh(gentype x);
|
||||
// gentype acospi(gentype x);
|
||||
// gentype asin(gentype x);
|
||||
// gentype asinh(gentype x);
|
||||
// gentype asinpi(gentype x);
|
||||
// gentype atan(gentype x);
|
||||
// gentype atanh(gentype x);
|
||||
// gentype atanpi(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_acos(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_acosh(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_acospi(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_asin(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_asinh(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_asinpi(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_atan(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_atanh(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_atanpi(is_embedded_profile)))
|
||||
|
||||
// gentype cos(gentype x);
|
||||
// gentype cosh(gentype x);
|
||||
// gentype cospi(gentype x);
|
||||
// gentype sin(gentype x);
|
||||
// gentype sinh(gentype x);
|
||||
// gentype sinpi(gentype x);
|
||||
// gentype tan(gentype x);
|
||||
// gentype tanh(gentype x);
|
||||
// gentype tanpi(gentype x);
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_cos(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_cosh(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_cospi(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_sin(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_sinh(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_sinpi(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_tan(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_tanh(is_embedded_profile)))
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_tanpi(is_embedded_profile)))
|
||||
|
||||
// gentype atan2(gentype y, gentype x);
|
||||
// gentype atan2pi(gentype y, gentype x);
|
||||
TEST_BINARY_FUNC_MACRO((trigonometric_func_atan2(is_embedded_profile)))
|
||||
TEST_BINARY_FUNC_MACRO((trigonometric_func_atan2pi(is_embedded_profile)))
|
||||
|
||||
// gentype sincos(gentype x, gentype * cosval);
|
||||
TEST_UNARY_FUNC_MACRO((trigonometric_func_sincos(is_embedded_profile)))
|
||||
|
||||
if(error != CL_SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_MATH_FUNCS_TRI_FUNCS_HPP
|
||||
Reference in New Issue
Block a user