mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-22 05:16:10 +01:00
Fix ulp distance calculation for numbers with different signs
This is a simplification of the fix proposed in #2152, with the critical function split out so that it can be tested directly, without having to go through the ULP matcher. Closes #2152
This commit is contained in:
parent
6f21a3609c
commit
3d1cf95b32
@ -161,6 +161,11 @@ away from the `target` value. The short version of what this means
|
||||
is that there is no more than `maxUlpDiff - 1` representeable floating
|
||||
point numbers between the argument for matching and the `target` value.
|
||||
|
||||
**Important**: The WithinULP matcher requires the platform to use the
|
||||
[IEEE-754](https://en.wikipedia.org/wiki/IEEE_754) representation for
|
||||
floating point numbers.
|
||||
|
||||
|
||||
`WithinRel` creates a matcher that accepts floating point numbers that
|
||||
are _approximately equal_ with the `target` with tolerance of `eps.`
|
||||
Specifically, it matches if
|
||||
|
@ -65,6 +65,7 @@ set(INTERNAL_HEADERS
|
||||
${SOURCES_DIR}/internal/catch_errno_guard.hpp
|
||||
${SOURCES_DIR}/internal/catch_exception_translator_registry.hpp
|
||||
${SOURCES_DIR}/internal/catch_fatal_condition_handler.hpp
|
||||
${SOURCES_DIR}/internal/catch_floating_point_helpers.hpp
|
||||
${SOURCES_DIR}/internal/catch_unique_name.hpp
|
||||
${SOURCES_DIR}/generators/catch_generator_exception.hpp
|
||||
${SOURCES_DIR}/generators/catch_generators.hpp
|
||||
@ -160,6 +161,7 @@ set(IMPL_SOURCES
|
||||
${SOURCES_DIR}/internal/catch_enum_values_registry.cpp
|
||||
${SOURCES_DIR}/internal/catch_exception_translator_registry.cpp
|
||||
${SOURCES_DIR}/internal/catch_fatal_condition_handler.cpp
|
||||
${SOURCES_DIR}/internal/catch_floating_point_helpers.cpp
|
||||
${SOURCES_DIR}/generators/internal/catch_generators_combined_tu.cpp
|
||||
${SOURCES_DIR}/interfaces/catch_interfaces_combined_tu.cpp
|
||||
${SOURCES_DIR}/interfaces/catch_interfaces_reporter.cpp
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include <catch2/internal/catch_errno_guard.hpp>
|
||||
#include <catch2/internal/catch_exception_translator_registry.hpp>
|
||||
#include <catch2/internal/catch_fatal_condition_handler.hpp>
|
||||
#include <catch2/internal/catch_floating_point_helpers.hpp>
|
||||
#include <catch2/internal/catch_lazy_expr.hpp>
|
||||
#include <catch2/internal/catch_leak_detector.hpp>
|
||||
#include <catch2/internal/catch_list.hpp>
|
||||
|
32
src/catch2/internal/catch_floating_point_helpers.cpp
Normal file
32
src/catch2/internal/catch_floating_point_helpers.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
// 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
|
||||
|
||||
#include <catch2/internal/catch_floating_point_helpers.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
|
||||
uint32_t convertToBits(float f) {
|
||||
static_assert(sizeof(float) == sizeof(uint32_t), "Important ULP matcher assumption violated");
|
||||
uint32_t i;
|
||||
std::memcpy(&i, &f, sizeof(f));
|
||||
return i;
|
||||
}
|
||||
|
||||
uint64_t convertToBits(double d) {
|
||||
static_assert(sizeof(double) == sizeof(uint64_t), "Important ULP matcher assumption violated");
|
||||
uint64_t i;
|
||||
std::memcpy(&i, &d, sizeof(d));
|
||||
return i;
|
||||
}
|
||||
|
||||
} // end namespace Detail
|
||||
} // end namespace Catch
|
||||
|
88
src/catch2/internal/catch_floating_point_helpers.hpp
Normal file
88
src/catch2/internal/catch_floating_point_helpers.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
// 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
|
||||
#ifndef CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
|
||||
#define CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_polyfills.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
|
||||
uint32_t convertToBits(float f);
|
||||
uint64_t convertToBits(double d);
|
||||
|
||||
} // end namespace Detail
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the ULP distance between two floating point numbers
|
||||
*
|
||||
* The ULP distance of two floating point numbers is the count of
|
||||
* valid floating point numbers representable between them.
|
||||
*
|
||||
* There are some exceptions between how this function counts the
|
||||
* distance, and the interpretation of the standard as implemented.
|
||||
* by e.g. `nextafter`. For this function it always holds that:
|
||||
* * `(x == y) => ulpDistance(x, y) == 0` (so `ulpDistance(-0, 0) == 0`)
|
||||
* * `ulpDistance(maxFinite, INF) == 1`
|
||||
* * `ulpDistance(x, -x) == 2 * ulpDistance(x, 0)`
|
||||
*
|
||||
* \pre `!isnan( lhs )`
|
||||
* \pre `!isnan( rhs )`
|
||||
* \pre floating point numbers are represented in IEEE-754 format
|
||||
*/
|
||||
template <typename FP>
|
||||
uint64_t ulpDistance( FP lhs, FP rhs ) {
|
||||
assert( std::numeric_limits<FP>::is_iec559 &&
|
||||
"ulpDistance assumes IEEE-754 format for floating point types" );
|
||||
assert( !Catch::isnan( lhs ) &&
|
||||
"Distance between NaN and number is not meaningful" );
|
||||
assert( !Catch::isnan( rhs ) &&
|
||||
"Distance between NaN and number is not meaningful" );
|
||||
|
||||
// We want X == Y to imply 0 ULP distance even if X and Y aren't
|
||||
// bit-equal (-0 and 0), or X - Y != 0 (same sign infinities).
|
||||
if ( lhs == rhs ) { return 0; }
|
||||
|
||||
// We need a properly typed positive zero for type inference.
|
||||
static constexpr FP positive_zero{};
|
||||
|
||||
// We want to ensure that +/- 0 is always represented as positive zero
|
||||
if ( lhs == positive_zero ) { lhs = positive_zero; }
|
||||
if ( rhs == positive_zero ) { rhs = positive_zero; }
|
||||
|
||||
// If arguments have different signs, we can handle them by summing
|
||||
// how far are they from 0 each.
|
||||
if ( std::signbit( lhs ) != std::signbit( rhs ) ) {
|
||||
return ulpDistance( std::abs( lhs ), positive_zero ) +
|
||||
ulpDistance( std::abs( rhs ), positive_zero );
|
||||
}
|
||||
|
||||
// When both lhs and rhs are of the same sign, we can just
|
||||
// read the numbers bitwise as integers, and then subtract them
|
||||
// (assuming IEEE).
|
||||
uint64_t lc = Detail::convertToBits( lhs );
|
||||
uint64_t rc = Detail::convertToBits( rhs );
|
||||
|
||||
// The ulp distance between two numbers is symmetric, so to avoid
|
||||
// dealing with overflows we want the bigger converted number on the lhs
|
||||
if ( lc < rc ) {
|
||||
std::swap( lc, rc );
|
||||
}
|
||||
|
||||
return lc - rc;
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
|
@ -10,12 +10,12 @@
|
||||
#include <catch2/internal/catch_polyfills.hpp>
|
||||
#include <catch2/internal/catch_to_string.hpp>
|
||||
#include <catch2/catch_tostring.hpp>
|
||||
#include <catch2/internal/catch_floating_point_helpers.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
@ -24,20 +24,6 @@
|
||||
namespace Catch {
|
||||
namespace {
|
||||
|
||||
int32_t convert(float f) {
|
||||
static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated");
|
||||
int32_t i;
|
||||
std::memcpy(&i, &f, sizeof(f));
|
||||
return i;
|
||||
}
|
||||
|
||||
int64_t convert(double d) {
|
||||
static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated");
|
||||
int64_t i;
|
||||
std::memcpy(&i, &d, sizeof(d));
|
||||
return i;
|
||||
}
|
||||
|
||||
template <typename FP>
|
||||
bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) {
|
||||
// Comparison with NaN should always be false.
|
||||
@ -46,17 +32,10 @@ namespace {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto lc = convert(lhs);
|
||||
auto rc = convert(rhs);
|
||||
// This should also handle positive and negative zeros, infinities
|
||||
const auto ulpDist = ulpDistance(lhs, rhs);
|
||||
|
||||
if ((lc < 0) != (rc < 0)) {
|
||||
// Potentially we can have +0 and -0
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
// static cast as a workaround for IBM XLC
|
||||
auto ulpDiff = std::abs(static_cast<FP>(lc - rc));
|
||||
return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;
|
||||
return ulpDist <= maxUlpDiff;
|
||||
}
|
||||
|
||||
#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
|
||||
@ -131,6 +110,9 @@ namespace Detail {
|
||||
CATCH_ENFORCE(m_type == Detail::FloatingPointKind::Double
|
||||
|| m_ulps < (std::numeric_limits<uint32_t>::max)(),
|
||||
"Provided ULP is impossibly large for a float comparison.");
|
||||
CATCH_ENFORCE( std::numeric_limits<double>::is_iec559,
|
||||
"WithinUlp matcher only supports platforms with "
|
||||
"IEEE-754 compatible floating point representation" );
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
|
@ -80,6 +80,7 @@ set(TEST_SOURCES
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/Clara.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/Details.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/FloatingPoint.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/GeneratorsImpl.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/InternalBenchmark.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp
|
||||
|
@ -24,6 +24,8 @@ Nor would this
|
||||
:test-result: PASS #1954 - 7 arg template test case sig compiles - 1, 1, 1, 1, 1, 0, 0
|
||||
:test-result: PASS #1954 - 7 arg template test case sig compiles - 5, 1, 1, 1, 1, 0, 0
|
||||
:test-result: PASS #1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0
|
||||
:test-result: PASS #2152 - ULP checks between differently signed values were wrong - double
|
||||
:test-result: PASS #2152 - ULP checks between differently signed values were wrong - float
|
||||
:test-result: XFAIL #748 - captures with unexpected exceptions
|
||||
:test-result: PASS #809
|
||||
:test-result: PASS #833
|
||||
@ -282,6 +284,7 @@ Message from section two
|
||||
:test-result: PASS classify_outliers
|
||||
:test-result: PASS comparisons between const int variables
|
||||
:test-result: PASS comparisons between int variables
|
||||
:test-result: PASS convertToBits
|
||||
:test-result: PASS empty tags are not allowed
|
||||
:test-result: PASS erfc_inv
|
||||
:test-result: PASS estimate_clock_resolution
|
||||
|
@ -80,6 +80,10 @@ PartTracker.tests.cpp:<line number>: passed: n for: 3
|
||||
Misc.tests.cpp:<line number>: passed:
|
||||
Misc.tests.cpp:<line number>: passed:
|
||||
Misc.tests.cpp:<line number>: passed:
|
||||
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0 is within 2 ULPs of -4.9406564584124654e-324 ([-1.4821969375237396e-323, 4.9406564584124654e-324])
|
||||
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0 not is within 1 ULPs of -4.9406564584124654e-324 ([-9.8813129168249309e-324, -0.0000000000000000e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45])
|
||||
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00])
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception'
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42'
|
||||
@ -586,6 +590,7 @@ Matchers.tests.cpp:<line number>: passed: 10.f, !WithinAbs( 11.f, 0.5f ) for: 10
|
||||
Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs( -10.f, 0.5f ) for: -10.0f is within 0.5 of -10.0
|
||||
Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs( -9.6f, 0.5f ) for: -10.0f is within 0.5 of -9.6000003815
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP( 1.f, 0 ) for: 1.0f is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: -1.f, WithinULP( -1.f, 0 ) for: -1.0f is within 0 ULPs of -1.00000000e+00f ([-1.00000000e+00, -1.00000000e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter( 1.f, 2.f ), WithinULP( 1.f, 1 ) for: 1.0f is within 1 ULPs of 1.00000000e+00f ([9.99999940e-01, 1.00000012e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: 0.f, WithinULP( nextafter( 0.f, 1.f ), 1 ) for: 0.0f is within 1 ULPs of 1.40129846e-45f ([0.00000000e+00, 2.80259693e-45])
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP( nextafter( 1.f, 0.f ), 1 ) for: 1.0f is within 1 ULPs of 9.99999940e-01f ([9.99999881e-01, 1.00000000e+00])
|
||||
@ -2065,6 +2070,16 @@ Condition.tests.cpp:<line number>: passed: long_var == unsigned_char_var for: 1
|
||||
Condition.tests.cpp:<line number>: passed: long_var == unsigned_short_var for: 1 == 1
|
||||
Condition.tests.cpp:<line number>: passed: long_var == unsigned_int_var for: 1 == 1
|
||||
Condition.tests.cpp:<line number>: passed: long_var == unsigned_long_var for: 1 == 1
|
||||
FloatingPoint.tests.cpp:<line number>: passed: convertToBits( 0.f ) == 0 for: 0 == 0
|
||||
FloatingPoint.tests.cpp:<line number>: passed: convertToBits( -0.f ) == ( 1ULL << 31 ) for: 2147483648 (0x<hex digits>)
|
||||
==
|
||||
2147483648 (0x<hex digits>)
|
||||
FloatingPoint.tests.cpp:<line number>: passed: convertToBits( 0. ) == 0 for: 0 == 0
|
||||
FloatingPoint.tests.cpp:<line number>: passed: convertToBits( -0. ) == ( 1ULL << 63 ) for: 9223372036854775808 (0x<hex digits>)
|
||||
==
|
||||
9223372036854775808 (0x<hex digits>)
|
||||
FloatingPoint.tests.cpp:<line number>: passed: convertToBits( std::numeric_limits<float>::denorm_min() ) == 1 for: 1 == 1
|
||||
FloatingPoint.tests.cpp:<line number>: passed: convertToBits( std::numeric_limits<double>::denorm_min() ) == 1 for: 1 == 1
|
||||
Tag.tests.cpp:<line number>: passed: Catch::TestCaseInfo("", { "test with an empty tag", "[]" }, dummySourceLineInfo)
|
||||
InternalBenchmark.tests.cpp:<line number>: passed: erfc_inv(1.103560) == Approx(-0.09203687623843015) for: -0.0920368762 == Approx( -0.0920368762 )
|
||||
InternalBenchmark.tests.cpp:<line number>: passed: erfc_inv(1.067400) == Approx(-0.05980291115763361) for: -0.0598029112 == Approx( -0.0598029112 )
|
||||
|
@ -1386,6 +1386,6 @@ due to unexpected exception with message:
|
||||
Why would you throw a std::string?
|
||||
|
||||
===============================================================================
|
||||
test cases: 365 | 289 passed | 70 failed | 6 failed as expected
|
||||
assertions: 2092 | 1940 passed | 129 failed | 23 failed as expected
|
||||
test cases: 368 | 292 passed | 70 failed | 6 failed as expected
|
||||
assertions: 2103 | 1951 passed | 129 failed | 23 failed as expected
|
||||
|
||||
|
@ -744,6 +744,41 @@ Misc.tests.cpp:<line number>
|
||||
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#2152 - ULP checks between differently signed values were wrong - double
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) )
|
||||
with expansion:
|
||||
0.0 is within 2 ULPs of -4.9406564584124654e-324 ([-1.4821969375237396e-323,
|
||||
4.9406564584124654e-324])
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) )
|
||||
with expansion:
|
||||
0.0 not is within 1 ULPs of -4.9406564584124654e-324 ([-9.8813129168249309e-
|
||||
324, -0.0000000000000000e+00])
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#2152 - ULP checks between differently signed values were wrong - float
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) )
|
||||
with expansion:
|
||||
0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45])
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) )
|
||||
with expansion:
|
||||
0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.
|
||||
00000000e+00])
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#748 - captures with unexpected exceptions
|
||||
outside assertions
|
||||
@ -4490,6 +4525,12 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
1.0f is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00])
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( -1.f, WithinULP( -1.f, 0 ) )
|
||||
with expansion:
|
||||
-1.0f is within 0 ULPs of -1.00000000e+00f ([-1.00000000e+00, -1.00000000e+
|
||||
00])
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( nextafter( 1.f, 2.f ), WithinULP( 1.f, 1 ) )
|
||||
with expansion:
|
||||
@ -14597,6 +14638,46 @@ Condition.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
1 == 1
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
convertToBits
|
||||
-------------------------------------------------------------------------------
|
||||
FloatingPoint.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
FloatingPoint.tests.cpp:<line number>: PASSED:
|
||||
CHECK( convertToBits( 0.f ) == 0 )
|
||||
with expansion:
|
||||
0 == 0
|
||||
|
||||
FloatingPoint.tests.cpp:<line number>: PASSED:
|
||||
CHECK( convertToBits( -0.f ) == ( 1ULL << 31 ) )
|
||||
with expansion:
|
||||
2147483648 (0x<hex digits>)
|
||||
==
|
||||
2147483648 (0x<hex digits>)
|
||||
|
||||
FloatingPoint.tests.cpp:<line number>: PASSED:
|
||||
CHECK( convertToBits( 0. ) == 0 )
|
||||
with expansion:
|
||||
0 == 0
|
||||
|
||||
FloatingPoint.tests.cpp:<line number>: PASSED:
|
||||
CHECK( convertToBits( -0. ) == ( 1ULL << 63 ) )
|
||||
with expansion:
|
||||
9223372036854775808 (0x<hex digits>)
|
||||
==
|
||||
9223372036854775808 (0x<hex digits>)
|
||||
|
||||
FloatingPoint.tests.cpp:<line number>: PASSED:
|
||||
CHECK( convertToBits( std::numeric_limits<float>::denorm_min() ) == 1 )
|
||||
with expansion:
|
||||
1 == 1
|
||||
|
||||
FloatingPoint.tests.cpp:<line number>: PASSED:
|
||||
CHECK( convertToBits( std::numeric_limits<double>::denorm_min() ) == 1 )
|
||||
with expansion:
|
||||
1 == 1
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
empty tags are not allowed
|
||||
-------------------------------------------------------------------------------
|
||||
@ -16852,6 +16933,6 @@ Misc.tests.cpp:<line number>
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
|
||||
===============================================================================
|
||||
test cases: 365 | 273 passed | 86 failed | 6 failed as expected
|
||||
assertions: 2109 | 1940 passed | 146 failed | 23 failed as expected
|
||||
test cases: 368 | 276 passed | 86 failed | 6 failed as expected
|
||||
assertions: 2120 | 1951 passed | 146 failed | 23 failed as expected
|
||||
|
||||
|
@ -744,6 +744,41 @@ Misc.tests.cpp:<line number>
|
||||
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#2152 - ULP checks between differently signed values were wrong - double
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) )
|
||||
with expansion:
|
||||
0.0 is within 2 ULPs of -4.9406564584124654e-324 ([-1.4821969375237396e-323,
|
||||
4.9406564584124654e-324])
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) )
|
||||
with expansion:
|
||||
0.0 not is within 1 ULPs of -4.9406564584124654e-324 ([-9.8813129168249309e-
|
||||
324, -0.0000000000000000e+00])
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#2152 - ULP checks between differently signed values were wrong - float
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) )
|
||||
with expansion:
|
||||
0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45])
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) )
|
||||
with expansion:
|
||||
0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.
|
||||
00000000e+00])
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#748 - captures with unexpected exceptions
|
||||
outside assertions
|
||||
@ -924,6 +959,6 @@ Condition.tests.cpp:<line number>: FAILED:
|
||||
CHECK( true != true )
|
||||
|
||||
===============================================================================
|
||||
test cases: 31 | 26 passed | 3 failed | 2 failed as expected
|
||||
assertions: 99 | 92 passed | 4 failed | 3 failed as expected
|
||||
test cases: 33 | 28 passed | 3 failed | 2 failed as expected
|
||||
assertions: 103 | 96 passed | 4 failed | 3 failed as expected
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuitesloose text artifact
|
||||
>
|
||||
<testsuite name="<exe-name>" errors="17" failures="130" tests="2110" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="17" failures="130" tests="2121" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<properties>
|
||||
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/>
|
||||
<property name="random-seed" value="1"/>
|
||||
@ -47,6 +47,8 @@ Nor would this
|
||||
<testcase classname="<exe-name>.global" name="#1954 - 7 arg template test case sig compiles - 1, 1, 1, 1, 1, 0, 0" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="#1954 - 7 arg template test case sig compiles - 5, 1, 1, 1, 1, 0, 0" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="#1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="#2152 - ULP checks between differently signed values were wrong - double" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="#2152 - ULP checks between differently signed values were wrong - float" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}" status="run">
|
||||
<error type="TEST_CASE">
|
||||
FAILED:
|
||||
@ -1548,6 +1550,7 @@ Misc.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="classify_outliers/mixed" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="comparisons between const int variables" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="comparisons between int variables" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="convertToBits" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="empty tags are not allowed" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="erfc_inv" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="estimate_clock_resolution" time="{duration}" status="run"/>
|
||||
|
@ -77,6 +77,9 @@
|
||||
<testCase name="Process can be configured on command line/Benchmark options/warmup-time" duration="{duration}"/>
|
||||
<testCase name="Test with special, characters "in name" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="tests/<exe-name>/IntrospectiveTests/FloatingPoint.tests.cpp">
|
||||
<testCase name="convertToBits" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp">
|
||||
<testCase name="Generators internals/Single value" duration="{duration}"/>
|
||||
<testCase name="Generators internals/Preset values" duration="{duration}"/>
|
||||
@ -988,6 +991,8 @@ Exception.tests.cpp:<line number>
|
||||
<testCase name="tables" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="tests/<exe-name>/UsageTests/Matchers.tests.cpp">
|
||||
<testCase name="#2152 - ULP checks between differently signed values were wrong - double" duration="{duration}"/>
|
||||
<testCase name="#2152 - ULP checks between differently signed values were wrong - float" duration="{duration}"/>
|
||||
<testCase name="Arbitrary predicate matcher/Function pointer" duration="{duration}"/>
|
||||
<testCase name="Arbitrary predicate matcher/Lambdas + different type" duration="{duration}"/>
|
||||
<testCase name="Combining MatchAllOfGeneric does not nest" duration="{duration}"/>
|
||||
|
@ -158,6 +158,14 @@ ok {test-number} -
|
||||
ok {test-number} -
|
||||
# #1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0
|
||||
ok {test-number} -
|
||||
# #2152 - ULP checks between differently signed values were wrong - double
|
||||
ok {test-number} - smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0 is within 2 ULPs of -4.9406564584124654e-324 ([-1.4821969375237396e-323, 4.9406564584124654e-324])
|
||||
# #2152 - ULP checks between differently signed values were wrong - double
|
||||
ok {test-number} - smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0 not is within 1 ULPs of -4.9406564584124654e-324 ([-9.8813129168249309e-324, -0.0000000000000000e+00])
|
||||
# #2152 - ULP checks between differently signed values were wrong - float
|
||||
ok {test-number} - smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45])
|
||||
# #2152 - ULP checks between differently signed values were wrong - float
|
||||
ok {test-number} - smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00])
|
||||
# #748 - captures with unexpected exceptions
|
||||
not ok {test-number} - unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
|
||||
# #748 - captures with unexpected exceptions
|
||||
@ -1155,6 +1163,8 @@ ok {test-number} - -10.f, WithinAbs( -9.6f, 0.5f ) for: -10.0f is within 0.5 of
|
||||
# Floating point matchers: float
|
||||
ok {test-number} - 1.f, WithinULP( 1.f, 0 ) for: 1.0f is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00])
|
||||
# Floating point matchers: float
|
||||
ok {test-number} - -1.f, WithinULP( -1.f, 0 ) for: -1.0f is within 0 ULPs of -1.00000000e+00f ([-1.00000000e+00, -1.00000000e+00])
|
||||
# Floating point matchers: float
|
||||
ok {test-number} - nextafter( 1.f, 2.f ), WithinULP( 1.f, 1 ) for: 1.0f is within 1 ULPs of 1.00000000e+00f ([9.99999940e-01, 1.00000012e+00])
|
||||
# Floating point matchers: float
|
||||
ok {test-number} - 0.f, WithinULP( nextafter( 0.f, 1.f ), 1 ) for: 0.0f is within 1 ULPs of 1.40129846e-45f ([0.00000000e+00, 2.80259693e-45])
|
||||
@ -3703,6 +3713,18 @@ ok {test-number} - long_var == unsigned_short_var for: 1 == 1
|
||||
ok {test-number} - long_var == unsigned_int_var for: 1 == 1
|
||||
# comparisons between int variables
|
||||
ok {test-number} - long_var == unsigned_long_var for: 1 == 1
|
||||
# convertToBits
|
||||
ok {test-number} - convertToBits( 0.f ) == 0 for: 0 == 0
|
||||
# convertToBits
|
||||
ok {test-number} - convertToBits( -0.f ) == ( 1ULL << 31 ) for: 2147483648 (0x<hex digits>) == 2147483648 (0x<hex digits>)
|
||||
# convertToBits
|
||||
ok {test-number} - convertToBits( 0. ) == 0 for: 0 == 0
|
||||
# convertToBits
|
||||
ok {test-number} - convertToBits( -0. ) == ( 1ULL << 63 ) for: 9223372036854775808 (0x<hex digits>) == 9223372036854775808 (0x<hex digits>)
|
||||
# convertToBits
|
||||
ok {test-number} - convertToBits( std::numeric_limits<float>::denorm_min() ) == 1 for: 1 == 1
|
||||
# convertToBits
|
||||
ok {test-number} - convertToBits( std::numeric_limits<double>::denorm_min() ) == 1 for: 1 == 1
|
||||
# empty tags are not allowed
|
||||
ok {test-number} - Catch::TestCaseInfo("", { "test with an empty tag", "[]" }, dummySourceLineInfo)
|
||||
# erfc_inv
|
||||
@ -4220,5 +4242,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
|
||||
ok {test-number} -
|
||||
# xmlentitycheck
|
||||
ok {test-number} -
|
||||
1..2109
|
||||
1..2120
|
||||
|
||||
|
@ -50,6 +50,10 @@ Tricky.tests.cpp:<line number>|nexplicit failure with message:|n "1514"']
|
||||
##teamcity[testFinished name='#1954 - 7 arg template test case sig compiles - 5, 1, 1, 1, 1, 0, 0' duration="{duration}"]
|
||||
##teamcity[testStarted name='#1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0']
|
||||
##teamcity[testFinished name='#1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0' duration="{duration}"]
|
||||
##teamcity[testStarted name='#2152 - ULP checks between differently signed values were wrong - double']
|
||||
##teamcity[testFinished name='#2152 - ULP checks between differently signed values were wrong - double' duration="{duration}"]
|
||||
##teamcity[testStarted name='#2152 - ULP checks between differently signed values were wrong - float']
|
||||
##teamcity[testFinished name='#2152 - ULP checks between differently signed values were wrong - float' duration="{duration}"]
|
||||
##teamcity[testStarted name='#748 - captures with unexpected exceptions']
|
||||
Exception.tests.cpp:<line number>|nunexpected exception with messages:|n "answer := 42"|n "expected exception"- failure ignore as test marked as |'ok to fail|'|n']
|
||||
Exception.tests.cpp:<line number>|nunexpected exception with messages:|n "answer := 42"|n "expected exception"|n REQUIRE_NOTHROW( thisThrows() )|nwith expansion:|n thisThrows()|n- failure ignore as test marked as |'ok to fail|'|n']
|
||||
@ -690,6 +694,8 @@ Misc.tests.cpp:<line number>|nexpression failed|n REQUIRE( testCheckedIf( false
|
||||
##teamcity[testFinished name='comparisons between const int variables' duration="{duration}"]
|
||||
##teamcity[testStarted name='comparisons between int variables']
|
||||
##teamcity[testFinished name='comparisons between int variables' duration="{duration}"]
|
||||
##teamcity[testStarted name='convertToBits']
|
||||
##teamcity[testFinished name='convertToBits' duration="{duration}"]
|
||||
##teamcity[testStarted name='empty tags are not allowed']
|
||||
##teamcity[testFinished name='empty tags are not allowed' duration="{duration}"]
|
||||
##teamcity[testStarted name='erfc_inv']
|
||||
|
@ -650,6 +650,44 @@ Nor would this
|
||||
<TestCase name="#1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0" tags="[.][compilation][regression]" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" >
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="#2152 - ULP checks between differently signed values were wrong - double" tags="[floating-point][matchers][ulp]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
smallest_non_zero, WithinULP( -smallest_non_zero, 2 )
|
||||
</Original>
|
||||
<Expanded>
|
||||
0.0 is within 2 ULPs of -4.9406564584124654e-324 ([-1.4821969375237396e-323, 4.9406564584124654e-324])
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
smallest_non_zero, !WithinULP( -smallest_non_zero, 1 )
|
||||
</Original>
|
||||
<Expanded>
|
||||
0.0 not is within 1 ULPs of -4.9406564584124654e-324 ([-9.8813129168249309e-324, -0.0000000000000000e+00])
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="#2152 - ULP checks between differently signed values were wrong - float" tags="[floating-point][matchers][ulp]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
smallest_non_zero, WithinULP( -smallest_non_zero, 2 )
|
||||
</Original>
|
||||
<Expanded>
|
||||
0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45])
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
smallest_non_zero, !WithinULP( -smallest_non_zero, 1 )
|
||||
</Original>
|
||||
<Expanded>
|
||||
0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00])
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="#748 - captures with unexpected exceptions" tags="[!shouldfail][!throws][.][failing]" filename="tests/<exe-name>/UsageTests/Exception.tests.cpp" >
|
||||
<Section name="outside assertions" filename="tests/<exe-name>/UsageTests/Exception.tests.cpp" >
|
||||
<Info>
|
||||
@ -5087,6 +5125,14 @@ Nor would this
|
||||
1.0f is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00])
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
-1.f, WithinULP( -1.f, 0 )
|
||||
</Original>
|
||||
<Expanded>
|
||||
-1.0f is within 0 ULPs of -1.00000000e+00f ([-1.00000000e+00, -1.00000000e+00])
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
nextafter( 1.f, 2.f ), WithinULP( 1.f, 1 )
|
||||
@ -5135,7 +5181,7 @@ Nor would this
|
||||
-0.0f is within 0 ULPs of 0.00000000e+00f ([0.00000000e+00, 0.00000000e+00])
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="7" failures="0" expectedFailures="0"/>
|
||||
<OverallResults successes="8" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="Composed" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
@ -17257,6 +17303,61 @@ There is no extra whitespace here
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="convertToBits" tags="[conversion][floating-point]" filename="tests/<exe-name>/IntrospectiveTests/FloatingPoint.tests.cpp" >
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/FloatingPoint.tests.cpp" >
|
||||
<Original>
|
||||
convertToBits( 0.f ) == 0
|
||||
</Original>
|
||||
<Expanded>
|
||||
0 == 0
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/FloatingPoint.tests.cpp" >
|
||||
<Original>
|
||||
convertToBits( -0.f ) == ( 1ULL << 31 )
|
||||
</Original>
|
||||
<Expanded>
|
||||
2147483648 (0x<hex digits>)
|
||||
==
|
||||
2147483648 (0x<hex digits>)
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/FloatingPoint.tests.cpp" >
|
||||
<Original>
|
||||
convertToBits( 0. ) == 0
|
||||
</Original>
|
||||
<Expanded>
|
||||
0 == 0
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/FloatingPoint.tests.cpp" >
|
||||
<Original>
|
||||
convertToBits( -0. ) == ( 1ULL << 63 )
|
||||
</Original>
|
||||
<Expanded>
|
||||
9223372036854775808 (0x<hex digits>)
|
||||
==
|
||||
9223372036854775808 (0x<hex digits>)
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/FloatingPoint.tests.cpp" >
|
||||
<Original>
|
||||
convertToBits( std::numeric_limits<float>::denorm_min() ) == 1
|
||||
</Original>
|
||||
<Expanded>
|
||||
1 == 1
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/FloatingPoint.tests.cpp" >
|
||||
<Original>
|
||||
convertToBits( std::numeric_limits<double>::denorm_min() ) == 1
|
||||
</Original>
|
||||
<Expanded>
|
||||
1 == 1
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="empty tags are not allowed" tags="[tags]" filename="tests/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THROWS" filename="tests/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
|
||||
<Original>
|
||||
@ -19826,9 +19927,9 @@ loose text artifact
|
||||
</Section>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<OverallResults successes="1940" failures="147" expectedFailures="23"/>
|
||||
<OverallResultsCases successes="273" failures="86" expectedFailures="6"/>
|
||||
<OverallResults successes="1951" failures="147" expectedFailures="23"/>
|
||||
<OverallResultsCases successes="276" failures="86" expectedFailures="6"/>
|
||||
</Group>
|
||||
<OverallResults successes="1940" failures="146" expectedFailures="23"/>
|
||||
<OverallResultsCases successes="273" failures="86" expectedFailures="6"/>
|
||||
<OverallResults successes="1951" failures="146" expectedFailures="23"/>
|
||||
<OverallResultsCases successes="276" failures="86" expectedFailures="6"/>
|
||||
</Catch>
|
||||
|
66
tests/SelfTest/IntrospectiveTests/FloatingPoint.tests.cpp
Normal file
66
tests/SelfTest/IntrospectiveTests/FloatingPoint.tests.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_template_test_macros.hpp>
|
||||
#include <catch2/internal/catch_floating_point_helpers.hpp>
|
||||
|
||||
|
||||
TEST_CASE("convertToBits", "[floating-point][conversion]") {
|
||||
using Catch::Detail::convertToBits;
|
||||
|
||||
CHECK( convertToBits( 0.f ) == 0 );
|
||||
CHECK( convertToBits( -0.f ) == ( 1ULL << 31 ) );
|
||||
CHECK( convertToBits( 0. ) == 0 );
|
||||
CHECK( convertToBits( -0. ) == ( 1ULL << 63 ) );
|
||||
CHECK( convertToBits( std::numeric_limits<float>::denorm_min() ) == 1 );
|
||||
CHECK( convertToBits( std::numeric_limits<double>::denorm_min() ) == 1 );
|
||||
}
|
||||
|
||||
TEMPLATE_TEST_CASE("type-shared ulpDistance tests", "[floating-point][ulp][approvals]", float, double) {
|
||||
using FP = TestType;
|
||||
using Catch::ulpDistance;
|
||||
|
||||
// Distance between zeros is zero
|
||||
CHECK( ulpDistance( FP{}, FP{} ) == 0 );
|
||||
CHECK( ulpDistance( FP{}, -FP{} ) == 0 );
|
||||
CHECK( ulpDistance( -FP{}, -FP{} ) == 0 );
|
||||
|
||||
// Distance between same-sign infinities is zero
|
||||
static constexpr FP infinity = std::numeric_limits<FP>::infinity();
|
||||
CHECK( ulpDistance( infinity, infinity ) == 0 );
|
||||
CHECK( ulpDistance( -infinity, -infinity ) == 0 );
|
||||
|
||||
// Distance between max-finite-val and same sign infinity is 1
|
||||
static constexpr FP max_finite = std::numeric_limits<FP>::max();
|
||||
CHECK( ulpDistance( max_finite, infinity ) == 1 );
|
||||
CHECK( ulpDistance( -max_finite, -infinity ) == 1 );
|
||||
|
||||
// Distance between X and 0 is half of distance between X and -X
|
||||
CHECK( ulpDistance( -infinity, infinity ) ==
|
||||
2 * ulpDistance( infinity, FP{} ) );
|
||||
CHECK( 2 * ulpDistance( FP{ -2. }, FP{} ) ==
|
||||
ulpDistance( FP{ -2. }, FP{ 2. } ) );
|
||||
CHECK( 2 * ulpDistance( FP{ 2. }, FP{} ) ==
|
||||
ulpDistance( FP{ -2. }, FP{ 2. } ) );
|
||||
|
||||
// Denorms are supported
|
||||
CHECK( ulpDistance( std::numeric_limits<FP>::denorm_min(), FP{} ) == 1 );
|
||||
CHECK( ulpDistance( std::numeric_limits<FP>::denorm_min(), -FP{} ) == 1 );
|
||||
CHECK( ulpDistance( -std::numeric_limits<FP>::denorm_min(), FP{} ) == 1 );
|
||||
CHECK( ulpDistance( -std::numeric_limits<FP>::denorm_min(), -FP{} ) == 1 );
|
||||
CHECK( ulpDistance( std::numeric_limits<FP>::denorm_min(),
|
||||
-std::numeric_limits<FP>::denorm_min() ) == 2 );
|
||||
|
||||
// Machine epsilon
|
||||
CHECK( ulpDistance( FP{ 1. },
|
||||
FP{ 1. } + std::numeric_limits<FP>::epsilon() ) == 1 );
|
||||
CHECK( ulpDistance( -FP{ 1. },
|
||||
-FP{ 1. } - std::numeric_limits<FP>::epsilon() ) == 1 );
|
||||
}
|
||||
|
||||
TEST_CASE("UlpDistance", "[floating-point][ulp][approvals]") {
|
||||
using Catch::ulpDistance;
|
||||
|
||||
CHECK( ulpDistance( 1., 2. ) == 0x10'00'00'00'00'00'00 );
|
||||
CHECK( ulpDistance( -2., 2. ) == 0x80'00'00'00'00'00'00'00 );
|
||||
CHECK( ulpDistance( 1.f, 2.f ) == 0x80'00'00 );
|
||||
CHECK( ulpDistance( -2.f, 2.f ) == 0x80'00'00'00 );
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_template_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_exception.hpp>
|
||||
#include <catch2/matchers/catch_matchers_floating_point.hpp>
|
||||
#include <catch2/matchers/catch_matchers_predicate.hpp>
|
||||
@ -465,6 +466,7 @@ TEST_CASE( "Floating point matchers: float", "[matchers][floating-point]" ) {
|
||||
}
|
||||
SECTION( "ULPs" ) {
|
||||
REQUIRE_THAT( 1.f, WithinULP( 1.f, 0 ) );
|
||||
REQUIRE_THAT(-1.f, WithinULP( -1.f, 0 ) );
|
||||
|
||||
REQUIRE_THAT( nextafter( 1.f, 2.f ), WithinULP( 1.f, 1 ) );
|
||||
REQUIRE_THAT( 0.f, WithinULP( nextafter( 0.f, 1.f ), 1 ) );
|
||||
@ -1081,3 +1083,17 @@ TEST_CASE( "Matchers can take references",
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
TEMPLATE_TEST_CASE(
|
||||
"#2152 - ULP checks between differently signed values were wrong",
|
||||
"[matchers][floating-point][ulp]",
|
||||
float,
|
||||
double ) {
|
||||
using Catch::Matchers::WithinULP;
|
||||
|
||||
static constexpr TestType smallest_non_zero =
|
||||
std::numeric_limits<TestType>::denorm_min();
|
||||
|
||||
CHECK_THAT( smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) );
|
||||
CHECK_THAT( smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user