File indexing completed on 2025-01-18 09:54:05
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
0028
0029 #if defined( __GNUC__ ) || defined( __clang__ )
0030 # pragma GCC diagnostic push
0031
0032
0033
0034 # pragma GCC diagnostic ignored "-Wfloat-equal"
0035 #endif
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 template <typename FP>
0055 uint64_t ulpDistance( FP lhs, FP rhs ) {
0056 assert( std::numeric_limits<FP>::is_iec559 &&
0057 "ulpDistance assumes IEEE-754 format for floating point types" );
0058 assert( !Catch::isnan( lhs ) &&
0059 "Distance between NaN and number is not meaningful" );
0060 assert( !Catch::isnan( rhs ) &&
0061 "Distance between NaN and number is not meaningful" );
0062
0063
0064
0065 if ( lhs == rhs ) { return 0; }
0066
0067
0068 static constexpr FP positive_zero{};
0069
0070
0071 if ( lhs == positive_zero ) { lhs = positive_zero; }
0072 if ( rhs == positive_zero ) { rhs = positive_zero; }
0073
0074
0075
0076 if ( std::signbit( lhs ) != std::signbit( rhs ) ) {
0077 return ulpDistance( std::abs( lhs ), positive_zero ) +
0078 ulpDistance( std::abs( rhs ), positive_zero );
0079 }
0080
0081
0082
0083
0084 uint64_t lc = Detail::convertToBits( lhs );
0085 uint64_t rc = Detail::convertToBits( rhs );
0086
0087
0088
0089 if ( lc < rc ) {
0090 std::swap( lc, rc );
0091 }
0092
0093 return lc - rc;
0094 }
0095
0096 #if defined( __GNUC__ ) || defined( __clang__ )
0097 # pragma GCC diagnostic pop
0098 #endif
0099
0100
0101 }
0102
0103 #endif