File indexing completed on 2025-09-18 09:08:51
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
0009 #define CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
0010
0011 #include <catch2/internal/catch_polyfills.hpp>
0012
0013 #include <cassert>
0014 #include <cmath>
0015 #include <cstdint>
0016 #include <utility>
0017 #include <limits>
0018
0019 namespace Catch {
0020 namespace Detail {
0021
0022 uint32_t convertToBits(float f);
0023 uint64_t convertToBits(double d);
0024
0025
0026
0027 bool directCompare( float lhs, float rhs );
0028 bool directCompare( double lhs, double rhs );
0029
0030 }
0031
0032
0033
0034 #if defined( __GNUC__ ) || defined( __clang__ )
0035 # pragma GCC diagnostic push
0036
0037
0038
0039 # pragma GCC diagnostic ignored "-Wfloat-equal"
0040 #endif
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 template <typename FP>
0060 uint64_t ulpDistance( FP lhs, FP rhs ) {
0061 assert( std::numeric_limits<FP>::is_iec559 &&
0062 "ulpDistance assumes IEEE-754 format for floating point types" );
0063 assert( !Catch::isnan( lhs ) &&
0064 "Distance between NaN and number is not meaningful" );
0065 assert( !Catch::isnan( rhs ) &&
0066 "Distance between NaN and number is not meaningful" );
0067
0068
0069
0070 if ( lhs == rhs ) { return 0; }
0071
0072
0073 static constexpr FP positive_zero{};
0074
0075
0076 if ( lhs == positive_zero ) { lhs = positive_zero; }
0077 if ( rhs == positive_zero ) { rhs = positive_zero; }
0078
0079
0080
0081 if ( std::signbit( lhs ) != std::signbit( rhs ) ) {
0082 return ulpDistance( std::abs( lhs ), positive_zero ) +
0083 ulpDistance( std::abs( rhs ), positive_zero );
0084 }
0085
0086
0087
0088
0089 uint64_t lc = Detail::convertToBits( lhs );
0090 uint64_t rc = Detail::convertToBits( rhs );
0091
0092
0093
0094 if ( lc < rc ) {
0095 std::swap( lc, rc );
0096 }
0097
0098 return lc - rc;
0099 }
0100
0101 #if defined( __GNUC__ ) || defined( __clang__ )
0102 # pragma GCC diagnostic pop
0103 #endif
0104
0105
0106 }
0107
0108 #endif