2022-01-29 00:03:43 +01:00
|
|
|
|
|
|
|
// Copyright Catch2 Authors
|
|
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
|
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
|
|
// https://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
|
|
|
|
// SPDX-License-Identifier: BSL-1.0
|
2011-04-28 09:28:03 +02:00
|
|
|
|
2020-01-20 23:24:04 +01:00
|
|
|
#include <catch2/catch_test_macros.hpp>
|
2020-03-30 10:34:21 +02:00
|
|
|
#include <catch2/catch_approx.hpp>
|
2011-04-28 09:28:03 +02:00
|
|
|
|
2017-11-01 07:30:11 +01:00
|
|
|
#include <cmath>
|
|
|
|
|
2020-02-03 15:07:59 +01:00
|
|
|
using Catch::Approx;
|
2020-01-20 23:24:04 +01:00
|
|
|
|
2021-06-20 16:25:57 +02:00
|
|
|
namespace {
|
|
|
|
static double divide(double a, double b) {
|
|
|
|
return a / b;
|
2017-11-15 08:48:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
class StrongDoubleTypedef {
|
|
|
|
double d_ = 0.0;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit StrongDoubleTypedef(double d) : d_(d) {}
|
|
|
|
explicit operator double() const { return d_; }
|
|
|
|
};
|
|
|
|
|
2021-06-20 16:25:57 +02:00
|
|
|
static std::ostream& operator<<(std::ostream& os, StrongDoubleTypedef td) {
|
2017-11-15 08:48:21 +01:00
|
|
|
return os << "StrongDoubleTypedef(" << static_cast<double>(td) << ")";
|
|
|
|
}
|
2021-06-20 16:25:57 +02:00
|
|
|
} // end unnamed namespace
|
2017-11-15 08:48:21 +01:00
|
|
|
|
2018-05-21 15:42:40 +02:00
|
|
|
using namespace Catch::literals;
|
2017-11-15 08:48:21 +01:00
|
|
|
|
2011-04-28 09:28:03 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2018-05-21 15:42:40 +02:00
|
|
|
TEST_CASE( "A comparison that uses literals instead of the normal constructor", "[Approx]" ) {
|
|
|
|
double d = 1.23;
|
|
|
|
|
|
|
|
REQUIRE( d == 1.23_a );
|
|
|
|
REQUIRE( d != 1.22_a );
|
|
|
|
REQUIRE( -d == -1.23_a );
|
|
|
|
|
|
|
|
REQUIRE( d == 1.2_a .epsilon(.1) );
|
|
|
|
REQUIRE( d != 1.2_a .epsilon(.001) );
|
|
|
|
REQUIRE( d == 1_a .epsilon(.3) );
|
|
|
|
}
|
|
|
|
|
2017-11-15 08:48:21 +01:00
|
|
|
TEST_CASE( "Some simple comparisons between doubles", "[Approx]" ) {
|
2011-04-28 09:28:03 +02:00
|
|
|
double d = 1.23;
|
2015-11-04 19:01:28 +01:00
|
|
|
|
2011-04-28 09:28:03 +02:00
|
|
|
REQUIRE( d == Approx( 1.23 ) );
|
|
|
|
REQUIRE( d != Approx( 1.22 ) );
|
|
|
|
REQUIRE( d != Approx( 1.24 ) );
|
|
|
|
|
2018-05-21 15:42:40 +02:00
|
|
|
REQUIRE( d == 1.23_a );
|
|
|
|
REQUIRE( d != 1.22_a );
|
|
|
|
|
2011-04-28 09:28:03 +02:00
|
|
|
REQUIRE( Approx( d ) == 1.23 );
|
|
|
|
REQUIRE( Approx( d ) != 1.22 );
|
|
|
|
REQUIRE( Approx( d ) != 1.24 );
|
|
|
|
}
|
2011-05-24 09:23:02 +02:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2017-11-15 08:48:21 +01:00
|
|
|
TEST_CASE( "Approximate comparisons with different epsilons", "[Approx]" ) {
|
2011-05-24 09:23:02 +02:00
|
|
|
double d = 1.23;
|
2015-11-04 19:01:28 +01:00
|
|
|
|
2011-05-24 09:23:02 +02:00
|
|
|
REQUIRE( d != Approx( 1.231 ) );
|
|
|
|
REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) );
|
2011-06-03 19:56:47 +02:00
|
|
|
}
|
|
|
|
|
2016-09-24 18:59:23 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2017-11-15 08:48:21 +01:00
|
|
|
TEST_CASE( "Less-than inequalities with different epsilons", "[Approx]" ) {
|
2016-09-24 18:59:23 +02:00
|
|
|
double d = 1.23;
|
|
|
|
|
|
|
|
REQUIRE( d <= Approx( 1.24 ) );
|
|
|
|
REQUIRE( d <= Approx( 1.23 ) );
|
|
|
|
REQUIRE_FALSE( d <= Approx( 1.22 ) );
|
|
|
|
REQUIRE( d <= Approx( 1.22 ).epsilon(0.1) );
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2017-11-15 08:48:21 +01:00
|
|
|
TEST_CASE( "Greater-than inequalities with different epsilons", "[Approx]" ) {
|
2016-09-24 18:59:23 +02:00
|
|
|
double d = 1.23;
|
|
|
|
|
|
|
|
REQUIRE( d >= Approx( 1.22 ) );
|
|
|
|
REQUIRE( d >= Approx( 1.23 ) );
|
|
|
|
REQUIRE_FALSE( d >= Approx( 1.24 ) );
|
|
|
|
REQUIRE( d >= Approx( 1.24 ).epsilon(0.1) );
|
|
|
|
}
|
|
|
|
|
2011-06-03 19:56:47 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2017-11-15 08:48:21 +01:00
|
|
|
TEST_CASE( "Approximate comparisons with floats", "[Approx]" ) {
|
2011-06-03 19:56:47 +02:00
|
|
|
REQUIRE( 1.23f == Approx( 1.23f ) );
|
|
|
|
REQUIRE( 0.0f == Approx( 0.0f ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2017-11-15 08:48:21 +01:00
|
|
|
TEST_CASE( "Approximate comparisons with ints", "[Approx]" ) {
|
2011-06-03 19:56:47 +02:00
|
|
|
REQUIRE( 1 == Approx( 1 ) );
|
|
|
|
REQUIRE( 0 == Approx( 0 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2017-11-15 08:48:21 +01:00
|
|
|
TEST_CASE( "Approximate comparisons with mixed numeric types", "[Approx]" ) {
|
2011-06-03 19:56:47 +02:00
|
|
|
const double dZero = 0;
|
|
|
|
const double dSmall = 0.00001;
|
|
|
|
const double dMedium = 1.234;
|
2015-11-04 19:01:28 +01:00
|
|
|
|
2011-06-03 19:56:47 +02:00
|
|
|
REQUIRE( 1.0f == Approx( 1 ) );
|
|
|
|
REQUIRE( 0 == Approx( dZero) );
|
2017-11-01 07:30:11 +01:00
|
|
|
REQUIRE( 0 == Approx( dSmall ).margin( 0.001 ) );
|
2011-06-03 19:56:47 +02:00
|
|
|
REQUIRE( 1.234f == Approx( dMedium ) );
|
|
|
|
REQUIRE( dMedium == Approx( 1.234f ) );
|
2011-05-24 09:23:02 +02:00
|
|
|
}
|
2011-06-06 09:21:21 +02:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2017-11-15 08:48:21 +01:00
|
|
|
TEST_CASE( "Use a custom approx", "[Approx][custom]" ) {
|
2011-06-06 09:21:21 +02:00
|
|
|
double d = 1.23;
|
2015-11-04 19:01:28 +01:00
|
|
|
|
2017-11-01 07:30:11 +01:00
|
|
|
Approx approx = Approx::custom().epsilon( 0.01 );
|
2015-11-04 19:01:28 +01:00
|
|
|
|
2011-06-06 09:21:21 +02:00
|
|
|
REQUIRE( d == approx( 1.23 ) );
|
|
|
|
REQUIRE( d == approx( 1.22 ) );
|
|
|
|
REQUIRE( d == approx( 1.24 ) );
|
|
|
|
REQUIRE( d != approx( 1.25 ) );
|
2015-11-04 19:01:28 +01:00
|
|
|
|
2011-06-06 09:21:21 +02:00
|
|
|
REQUIRE( approx( d ) == 1.23 );
|
|
|
|
REQUIRE( approx( d ) == 1.22 );
|
|
|
|
REQUIRE( approx( d ) == 1.24 );
|
|
|
|
REQUIRE( approx( d ) != 1.25 );
|
|
|
|
}
|
|
|
|
|
2017-11-15 08:48:21 +01:00
|
|
|
TEST_CASE( "Approximate PI", "[Approx][PI]" ) {
|
2013-03-04 12:19:15 +01:00
|
|
|
REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) );
|
|
|
|
REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) );
|
|
|
|
}
|
2016-05-12 20:18:44 +02:00
|
|
|
|
2017-02-27 14:15:03 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
TEST_CASE( "Absolute margin", "[Approx]" ) {
|
|
|
|
REQUIRE( 104.0 != Approx(100.0) );
|
|
|
|
REQUIRE( 104.0 == Approx(100.0).margin(5) );
|
2017-10-30 15:25:48 +01:00
|
|
|
REQUIRE( 104.0 == Approx(100.0).margin(4) );
|
2017-02-27 14:15:03 +01:00
|
|
|
REQUIRE( 104.0 != Approx(100.0).margin(3) );
|
|
|
|
REQUIRE( 100.3 != Approx(100.0) );
|
|
|
|
REQUIRE( 100.3 == Approx(100.0).margin(0.5) );
|
|
|
|
}
|
|
|
|
|
2017-10-30 15:25:48 +01:00
|
|
|
TEST_CASE("Approx with exactly-representable margin", "[Approx]") {
|
|
|
|
CHECK( 0.25f == Approx(0.0f).margin(0.25f) );
|
|
|
|
|
|
|
|
CHECK( 0.0f == Approx(0.25f).margin(0.25f) );
|
|
|
|
CHECK( 0.5f == Approx(0.25f).margin(0.25f) );
|
|
|
|
|
|
|
|
CHECK( 245.0f == Approx(245.25f).margin(0.25f) );
|
|
|
|
CHECK( 245.5f == Approx(245.25f).margin(0.25f) );
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("Approx setters validate their arguments", "[Approx]") {
|
|
|
|
REQUIRE_NOTHROW(Approx(0).margin(0));
|
|
|
|
REQUIRE_NOTHROW(Approx(0).margin(1234656));
|
|
|
|
|
|
|
|
REQUIRE_THROWS_AS(Approx(0).margin(-2), std::domain_error);
|
2017-11-01 07:30:11 +01:00
|
|
|
|
|
|
|
REQUIRE_NOTHROW(Approx(0).epsilon(0));
|
|
|
|
REQUIRE_NOTHROW(Approx(0).epsilon(1));
|
|
|
|
|
|
|
|
REQUIRE_THROWS_AS(Approx(0).epsilon(-0.001), std::domain_error);
|
|
|
|
REQUIRE_THROWS_AS(Approx(0).epsilon(1.0001), std::domain_error);
|
2017-10-30 15:25:48 +01:00
|
|
|
}
|
|
|
|
|
2017-11-01 07:30:11 +01:00
|
|
|
TEST_CASE("Default scale is invisible to comparison", "[Approx]") {
|
|
|
|
REQUIRE(101.000001 != Approx(100).epsilon(0.01));
|
|
|
|
REQUIRE(std::pow(10, -5) != Approx(std::pow(10, -7)));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("Epsilon only applies to Approx's value", "[Approx]") {
|
|
|
|
REQUIRE(101.01 != Approx(100).epsilon(0.01));
|
|
|
|
}
|
|
|
|
|
2019-10-04 13:23:14 +02:00
|
|
|
TEST_CASE("Assorted miscellaneous tests", "[Approx][approvals]") {
|
2017-11-01 07:30:11 +01:00
|
|
|
REQUIRE(INFINITY == Approx(INFINITY));
|
2019-10-04 13:23:14 +02:00
|
|
|
REQUIRE(-INFINITY != Approx(INFINITY));
|
|
|
|
REQUIRE(1 != Approx(INFINITY));
|
2019-10-04 14:00:34 +02:00
|
|
|
REQUIRE(INFINITY != Approx(1));
|
2017-11-10 18:48:45 +01:00
|
|
|
REQUIRE(NAN != Approx(NAN));
|
|
|
|
REQUIRE_FALSE(NAN == Approx(NAN));
|
2017-11-01 07:30:11 +01:00
|
|
|
}
|
2016-05-12 20:18:44 +02:00
|
|
|
|
2017-07-13 09:52:51 +02:00
|
|
|
TEST_CASE( "Comparison with explicitly convertible types", "[Approx]" )
|
2016-05-12 20:18:44 +02:00
|
|
|
{
|
|
|
|
StrongDoubleTypedef td(10.0);
|
|
|
|
|
|
|
|
REQUIRE(td == Approx(10.0));
|
|
|
|
REQUIRE(Approx(10.0) == td);
|
|
|
|
|
|
|
|
REQUIRE(td != Approx(11.0));
|
|
|
|
REQUIRE(Approx(11.0) != td);
|
2017-01-26 23:13:12 +01:00
|
|
|
|
2016-05-12 20:18:44 +02:00
|
|
|
REQUIRE(td <= Approx(10.0));
|
|
|
|
REQUIRE(td <= Approx(11.0));
|
|
|
|
REQUIRE(Approx(10.0) <= td);
|
|
|
|
REQUIRE(Approx(9.0) <= td);
|
2017-01-26 23:13:12 +01:00
|
|
|
|
2016-05-12 20:18:44 +02:00
|
|
|
REQUIRE(td >= Approx(9.0));
|
2017-11-28 21:29:34 +01:00
|
|
|
REQUIRE(td >= Approx(td));
|
|
|
|
REQUIRE(Approx(td) >= td);
|
2016-05-12 20:18:44 +02:00
|
|
|
REQUIRE(Approx(11.0) >= td);
|
2017-01-26 23:13:12 +01:00
|
|
|
|
2016-05-12 20:18:44 +02:00
|
|
|
}
|
2021-08-26 20:56:18 +02:00
|
|
|
|
|
|
|
TEST_CASE("Approx::operator() is const correct", "[Approx][.approvals]") {
|
|
|
|
const Approx ap = Approx(0.0).margin(0.01);
|
|
|
|
|
|
|
|
// As long as this compiles, the test should be considered passing
|
|
|
|
REQUIRE(1.0 == ap(1.0));
|
|
|
|
}
|