Skip to content

Commit

Permalink
Fixed comparison of double in some tests
Browse files Browse the repository at this point in the history
  • Loading branch information
JohanMabille committed Sep 20, 2021
1 parent 1bc610d commit 9a6fed4
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 21 deletions.
2 changes: 2 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ endif()
# Therefore, we need keep this small but complete for analysis.
set(TEST_HEADERS
test_common.hpp
test_common_macros.hpp
test_utils.hpp
test_xsemantic.hpp
)
set(COMMON_BASE
Expand Down
6 changes: 4 additions & 2 deletions test/test_common_macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "doctest/doctest.h"
#include "xtensor/xtensor_config.hpp"
#include "test_utils.hpp"

#if defined(XTENSOR_DISABLE_EXCEPTIONS)

Expand Down Expand Up @@ -50,7 +51,8 @@
#define ASSERT_TRUE(A) REQUIRE_EQ(A, true)
#define ASSERT_FALSE(A) REQUIRE_FALSE(A)

#define EXPECT_DOUBLE_EQ(x,y) CHECK(x == doctest::Approx(y));
#define EXPECT_DOUBLE_EQ(x,y) CHECK(xt::scalar_near(x,y));
#define EXPECT_TENSOR_EQ(x,y) CHECK(xt::tensor_near(x,y));

#define TEST_F(FIXTURE_CLASS, NAME)\
TEST_CASE_FIXTURE(FIXTURE_CLASS, #NAME)
Expand All @@ -61,4 +63,4 @@
#define HETEROGEN_PARAMETRIZED_TEST_APPLY(ID, TEST_FUNC)\
TEST_CASE_TEMPLATE_APPLY(ID, augment_t<std::decay_t<decltype(TEST_FUNC())>>)

#endif
#endif
101 changes: 101 additions & 0 deletions test/test_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#ifndef TEST_UTILS_HPP
#define TEST_UTILS_HPP

#include <cmath>
#include <limits>
#include <type_traits>

#include "xtensor/xexpression.hpp"

namespace xt
{
namespace detail
{
template <class T>
bool check_is_small(const T& value, const T& tolerance)
{
using std::abs;
return abs(value) < abs(tolerance);
}

template <class T>
T safe_division(const T& lhs, const T& rhs)
{
if (rhs < static_cast<T>(1) && lhs > rhs * (std::numeric_limits<T>::max)())
{
return (std::numeric_limits<T>::max)();
}
if ((lhs == static_cast<T>(0)) ||
(rhs > static_cast<T>(1) &&
lhs < rhs * (std::numeric_limits<T>::min)()))
{
return static_cast<T>(0);
}
return lhs / rhs;
}

template <class T>
bool check_is_close(const T& lhs, const T& rhs, const T& relative_precision)
{
using std::abs;
T diff = abs(lhs - rhs);
T d1 = safe_division(diff, T(abs(rhs)));
T d2 = safe_division(diff, T(abs(lhs)));

return d1 <= relative_precision && d2 <= relative_precision;
}
}

template <class T>
bool scalar_near(const T& lhs, const T& rhs)
{
using std::abs;
using std::max;

if (std::isnan(lhs))
{
return std::isnan(rhs);
}

if (std::isinf(lhs))
{
return std::isinf(rhs) && (lhs * rhs > 0) /* same sign */;
}

T relative_precision = 2048 * std::numeric_limits<T>::epsilon();
T absolute_zero_prox = 2048 * std::numeric_limits<T>::epsilon();

if (max(abs(lhs), abs(rhs)) < T(1e-3))
{
using res_type = decltype(lhs - rhs);
return detail::check_is_small(lhs - rhs, res_type(absolute_zero_prox));
}
else
{
return detail::check_is_close(lhs, rhs, relative_precision);
}
}

template <class T>
bool scalar_near(const std::complex<T>& lhs, const std::complex<T>& rhs)
{
return scalar_near(lhs.real(), rhs.real()) && scalar_near(lhs.imag(), rhs.imag());
}

template <class E1, class E2>
bool tensor_near(const E1& e1, const E2& e2)
{
bool res = e1.dimension() == e2.dimension() && std::equal(e1.shape().begin(), e1.shape().end(), e2.shape().begin());
auto iter1 = e1.begin();
auto iter2 = e2.begin();
auto iter_end = e1.end();
while (res && iter1 != iter_end)
{
res = scalar_near(*iter1++, *iter2++);
}
return res;
}
}

#endif

2 changes: 1 addition & 1 deletion test/test_xbuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ namespace xt
double at_end = 99.78730976641236;
xt::xarray<double> a = xt::linspace(0., at_end, 100);
auto b = xt::linspace(0., at_end, 100);
EXPECT_EQ(a, b);
EXPECT_TENSOR_EQ(a, b);
}

TEST(xbuilder, logspace)
Expand Down
12 changes: 6 additions & 6 deletions test/test_xfunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,13 +458,13 @@ namespace xt
*(resit4++) = *it;
}

EXPECT_EQ(res2, res5);
EXPECT_EQ(res4, res5);
EXPECT_TENSOR_EQ(res2, res5);
EXPECT_TENSOR_EQ(res4, res5);
}

EXPECT_EQ(res1, res5);
EXPECT_EQ(res3, res5);
EXPECT_EQ(func, res5);
EXPECT_TENSOR_EQ(res1, res5);
EXPECT_TENSOR_EQ(res3, res5);
EXPECT_TENSOR_EQ(func, res5);
}

TEST(xfunction, all_iterators)
Expand All @@ -475,7 +475,7 @@ namespace xt
auto f1 = 2.0 * x;
auto f2 = x * 2.0 * x;
iterator_tester(f1);
// For an unknown reason, MSVC is cannot correctly generate
// For an unknown reason, MSVC cannot correctly generate
// storage_cbegin() for a function of function. Moreover,
// a simple SFINAE deduction like has_storage_iterator
// harcoded and tested here fails (while it builds fine in any
Expand Down
24 changes: 12 additions & 12 deletions test/test_xnan_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,34 +187,34 @@ namespace xt
{
auto as = nanmean(nantest::aN)();
auto ase = nanmean(nantest::aN, evaluation_strategy::immediate)();
EXPECT_EQ(as, 17.125);
EXPECT_EQ(ase, 17.125);
EXPECT_DOUBLE_EQ(as, 17.125);
EXPECT_DOUBLE_EQ(ase, 17.125);

xarray<double> eaN0 = {1.0, 1.5, 123, 3};
xarray<double> eaN1 = {63.0, 2.0, 5.0/3.0};

EXPECT_EQ(nanmean(nantest::aN, {0}), eaN0);
EXPECT_EQ(nanmean(nantest::aN, {1}), eaN1);
EXPECT_TENSOR_EQ(nanmean(nantest::aN, {0}), eaN0);
EXPECT_TENSOR_EQ(nanmean(nantest::aN, {1}), eaN1);

std::array<std::size_t, 1> axis{0};
EXPECT_EQ(nanmean(nantest::aN, axis), eaN0);

EXPECT_EQ(nanmean(nantest::aN, {0}, evaluation_strategy::immediate), eaN0);
EXPECT_EQ(nanmean(nantest::aN, {1}, evaluation_strategy::immediate), eaN1);
EXPECT_TENSOR_EQ(nanmean(nantest::aN, {0}, evaluation_strategy::immediate), eaN0);
EXPECT_TENSOR_EQ(nanmean(nantest::aN, {1}, evaluation_strategy::immediate), eaN1);

auto cs = nanmean(nantest::cN)();
auto cse = nanmean(nantest::cN, evaluation_strategy::immediate)();
EXPECT_EQ(cs, std::complex<double>(1.4, 0.6));
EXPECT_EQ(cse, std::complex<double>(1.4, 0.6));
EXPECT_DOUBLE_EQ(cs, std::complex<double>(1.4, 0.6));
EXPECT_DOUBLE_EQ(cse, std::complex<double>(1.4, 0.6));

xarray<std::complex<double>> ecN0 = {1.0 + 0.0i, 1.0+0.5i, 3.0+2.0i};
xarray<std::complex<double>> ecN1 = {1.0 + 1.0i, (5.0 + 1.0i) / 3.0};

EXPECT_EQ(nanmean(nantest::cN, {0}), ecN0);
EXPECT_EQ(nanmean(nantest::cN, {1}), ecN1);
EXPECT_TENSOR_EQ(nanmean(nantest::cN, {0}), ecN0);
EXPECT_TENSOR_EQ(nanmean(nantest::cN, {1}), ecN1);

EXPECT_EQ(nanmean(nantest::cN, {0}, evaluation_strategy::immediate), ecN0);
EXPECT_EQ(nanmean(nantest::cN, {1}, evaluation_strategy::immediate), ecN1);
EXPECT_TENSOR_EQ(nanmean(nantest::cN, {0}, evaluation_strategy::immediate), ecN0);
EXPECT_TENSOR_EQ(nanmean(nantest::cN, {1}, evaluation_strategy::immediate), ecN1);
}


Expand Down

0 comments on commit 9a6fed4

Please sign in to comment.