myxlib/src/myx/math/almost_equal_ulps.cpp

80 lines
1.6 KiB
C++

#include <myx/math/float_cmp_types.hpp>
#include <myx/math/almost_equal_ulps.hpp>
#include <cmath>
namespace myx {
namespace math {
bool almost_equal_ulps( const float a, const float b,
const int maxUlpsDiff )
{
float_cmp_t uA( a );
float_cmp_t uB( b );
// Если знаки разные, то числа не равны.
if ( uA.negative() != uB.negative() )
{
// Кроме случая, когда +0==-0
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
if ( a == b )
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
{
return( true );
}
return( false );
}
// Разница в младших битах.
auto ulpsDiff = std::abs( uA.i - uB.i );
if ( ulpsDiff <= maxUlpsDiff )
{
return( true );
}
return( false );
} // almost_equal_ulps
bool almost_equal_ulps( const double a, const double b,
const int maxUlpsDiff )
{
double_cmp_t uA( a );
double_cmp_t uB( b );
// Если знаки разные, то числа не равны.
if ( uA.negative() != uB.negative() )
{
// Кроме случая, когда +0==-0
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
if ( a == b )
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
{
return( true );
}
return( false );
}
// Разница в младших битах.
auto ulpsDiff = std::abs( uA.i - uB.i );
if ( ulpsDiff <= maxUlpsDiff )
{
return( true );
}
return( false );
} // almost_equal_ulps
} // namespace math
} // namespace myx