#ifndef TEST_CONFORMANCE_CLCPP_UTILS_TEST_COMPARE_HPP
#define TEST_CONFORMANCE_CLCPP_UTILS_TEST_COMPARE_HPP
#include <random>
#include <limits>
#include <type_traits>
#include <algorithm>
#include <cmath>
#include "../common.hpp"
template<class type, class delta_type, class op_type>
inline bool are_equal(const type& x,
const type& y,
const delta_type& delta,
op_type op,
typename std::enable_if<
is_vector_type<type>::value
&& std::is_integral<typename scalar_type<type>::type>::value
>::type* = 0)
{
(void) delta;
for(size_t i = 0; i < vector_size<type>::value; i++)
{
if(op.is_out_bool())
{
if(!((x.s[i] != 0) == (y.s[i] != 0)))
{
return false;
}
}
else if(!(x.s[i] == y.s[i]))
{
return false;
}
}
return true;
}
template<class type, class delta_type, class op_type>
inline bool are_equal(const type& x,
const type& y,
const delta_type& delta,
op_type op,
typename std::enable_if<
!is_vector_type<type>::value
&& std::is_integral<type>::value
>::type* = 0)
{
(void) delta;
if(op.is_out_bool())
{
if(!((x != 0) == (y != 0)))
{
return false;
}
}
return x == y;
}
template<class type, class type1, class type2, class op_type>
inline bool are_equal(const type& x,
const type1& y,
const type2& delta,
op_type op,
typename std::enable_if<
!is_vector_type<type>::value
&& std::is_floating_point<type>::value
>::type* = 0)
{
if(std::fpclassify(static_cast<type1>(x)) == FP_SUBNORMAL || std::fpclassify(y) == FP_SUBNORMAL)
{
return true;
}
if((std::isnan)(static_cast<type1>(x)) && (std::isnan)(y))
{
return true;
}
else if((std::isnan)(static_cast<type1>(x)) || (std::isnan)(y))
{
return false;
}
if(static_cast<type1>(x) != y)
{
if(std::abs(static_cast<type1>(x) - y) > (std::max)(std::numeric_limits<type2>::epsilon(), std::abs(delta)))
{
return false;
}
if(op.use_ulp())
{
return !(std::abs(Ulp_Error(x, y)) > op.ulp());
}
}
return true;
}
template<class type, class type1, class type2, class op_type>
inline bool are_equal(const type& x,
const type1& y,
const type2& delta,
op_type op,
typename std::enable_if<
is_vector_type<type>::value
&& std::is_floating_point<typename scalar_type<type>::type>::value
>::type* = 0)
{
for(size_t i = 0; i < vector_size<type>::value; i++)
{
if(!are_equal(x.s[i], y.s[i], delta.s[i], op))
{
return false;
}
}
return true;
}
template<class type, class type1, class func>
inline void print_error_msg(const type& expected, const type1& result, size_t i, func op)
{
log_error(
"ERROR: test_%s %s failed. Error at %lu: Expected: %s, got: %s\n",
op.str().c_str(),
op.decl_str().c_str(),
i,
format_value(expected).c_str(),
format_value(result).c_str()
);
}
#endif