80 lines
1.6 KiB
C++
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
|