Merge branch 'master' of gitlab.2:f1x1t/myxlib
This commit is contained in:
commit
a6d359d18c
@ -1 +1 @@
|
|||||||
Subproject commit 45284f97623b7ae952020771846ccfe2e0a3cf58
|
Subproject commit 2c51ecc3dc681b11a6283d8ab64e6410f8b11678
|
42
src/myx/math/almost_equal_relative.cpp
Normal file
42
src/myx/math/almost_equal_relative.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include <myx/math/almost_equal_relative.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace myx {
|
||||||
|
|
||||||
|
namespace math {
|
||||||
|
|
||||||
|
bool almost_equal_relative( const float a, const float b,
|
||||||
|
const float maxRelDiff )
|
||||||
|
{
|
||||||
|
float diff = fabsf( a - b );
|
||||||
|
float aN = fabsf( a );
|
||||||
|
float bN = fabsf( b );
|
||||||
|
float largest = ( bN > aN ) ? bN : aN;
|
||||||
|
|
||||||
|
if ( diff <= largest * maxRelDiff )
|
||||||
|
{
|
||||||
|
return( true );
|
||||||
|
}
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool almost_equal_relative( const double a, const double b,
|
||||||
|
const double maxRelDiff )
|
||||||
|
{
|
||||||
|
double diff = fabs( a - b );
|
||||||
|
double aN = fabs( a );
|
||||||
|
double bN = fabs( b );
|
||||||
|
double largest = ( bN > aN ) ? bN : aN;
|
||||||
|
|
||||||
|
if ( diff <= largest * maxRelDiff )
|
||||||
|
{
|
||||||
|
return( true );
|
||||||
|
}
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace math
|
||||||
|
|
||||||
|
} // namespace myx
|
31
src/myx/math/almost_equal_relative.hpp
Normal file
31
src/myx/math/almost_equal_relative.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef MYX_MATH_ALMOST_EQUAL_RELATIVE_HPP_
|
||||||
|
#define MYX_MATH_ALMOST_EQUAL_RELATIVE_HPP_
|
||||||
|
|
||||||
|
#include <cfloat>
|
||||||
|
|
||||||
|
// https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
|
||||||
|
|
||||||
|
namespace myx {
|
||||||
|
|
||||||
|
namespace math {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Проверка на равенство двух аргументов типа float.
|
||||||
|
* Параметр maxRelDiff определяет максимальную относительную допустимую разницу,
|
||||||
|
* при которой аргументы считаются равными.
|
||||||
|
*/
|
||||||
|
bool almost_equal_relative( const float a, const float b,
|
||||||
|
const float maxRelDiff = FLT_EPSILON );
|
||||||
|
/**
|
||||||
|
* @brief Проверка на равенство двух аргументов типа double.
|
||||||
|
* Параметр maxRelDiff определяет максимальную относительную допустимую разницу,
|
||||||
|
* при которой аргументы считаются равными.
|
||||||
|
*/
|
||||||
|
bool almost_equal_relative( const double a, const double b,
|
||||||
|
const double maxRelDiff = DBL_EPSILON );
|
||||||
|
|
||||||
|
} // namespace math
|
||||||
|
|
||||||
|
} // namespace myx
|
||||||
|
|
||||||
|
#endif // MYX_MATH_ALMOST_EQUAL_RELATIVE_HPP_
|
56
src/myx/math/almost_equal_relative_and_abs.cpp
Normal file
56
src/myx/math/almost_equal_relative_and_abs.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include <myx/math/almost_equal_relative_and_abs.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace myx {
|
||||||
|
|
||||||
|
namespace math {
|
||||||
|
|
||||||
|
bool almost_equal_relative_and_abs( const float a, const float b,
|
||||||
|
const float maxAbsDiff, const float maxRelDiff )
|
||||||
|
{
|
||||||
|
// Check if the numbers are really close -- needed
|
||||||
|
// when comparing numbers near zero.
|
||||||
|
float diff = fabsf( a - b );
|
||||||
|
if ( diff <= maxAbsDiff )
|
||||||
|
{
|
||||||
|
return( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
float aN = fabsf( a );
|
||||||
|
float bN = fabsf( b );
|
||||||
|
float largest = ( bN > aN ) ? bN : aN;
|
||||||
|
|
||||||
|
if ( diff <= largest * maxRelDiff )
|
||||||
|
{
|
||||||
|
return( true );
|
||||||
|
}
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool almost_equal_relative_and_abs( const double a, const double b,
|
||||||
|
const double maxAbsDiff, const double maxRelDiff )
|
||||||
|
{
|
||||||
|
// Check if the numbers are really close -- needed
|
||||||
|
// when comparing numbers near zero.
|
||||||
|
double diff = fabs( a - b );
|
||||||
|
if ( diff <= maxAbsDiff )
|
||||||
|
{
|
||||||
|
return( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
double aN = fabs( a );
|
||||||
|
double bN = fabs( b );
|
||||||
|
double largest = ( bN > aN ) ? bN : aN;
|
||||||
|
|
||||||
|
if ( diff <= largest * maxRelDiff )
|
||||||
|
{
|
||||||
|
return( true );
|
||||||
|
}
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace math
|
||||||
|
|
||||||
|
} // namespace myx
|
31
src/myx/math/almost_equal_relative_and_abs.hpp
Normal file
31
src/myx/math/almost_equal_relative_and_abs.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef MYX_MATH_ALMOST_EQUAL_RELATIVE_AND_ABS_HPP_
|
||||||
|
#define MYX_MATH_ALMOST_EQUAL_RELATIVE_AND_ABS_HPP_
|
||||||
|
|
||||||
|
#include <cfloat>
|
||||||
|
|
||||||
|
namespace myx {
|
||||||
|
|
||||||
|
namespace math {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Проверка на равенство двух аргументов типа float.
|
||||||
|
* Параметр maxAbsDiff определяет максимальную абсолютную допустимую разницу.
|
||||||
|
* Параметр maxRelDiff определяет максимальную относительную допустимую разницу,
|
||||||
|
* при которой аргументы считаются равными.
|
||||||
|
*/
|
||||||
|
bool almost_equal_relative_and_abs( const float a, const float b,
|
||||||
|
const float maxAbsDiff, const float maxRelDiff = FLT_EPSILON );
|
||||||
|
/**
|
||||||
|
* @brief Проверка на равенство двух аргументов типа double.
|
||||||
|
* Параметр maxAbsDiff определяет максимальную абсолютную допустимую разницу.
|
||||||
|
* Параметр maxRelDiff определяет максимальную относительную допустимую разницу,
|
||||||
|
* при которой аргументы считаются равными.
|
||||||
|
*/
|
||||||
|
bool almost_equal_relative_and_abs( const double a, const double b,
|
||||||
|
const double maxAbsDiff, const double maxRelDiff = DBL_EPSILON );
|
||||||
|
|
||||||
|
} // namespace math
|
||||||
|
|
||||||
|
} // namespace myx
|
||||||
|
|
||||||
|
#endif // MYX_MATH_ALMOST_EQUAL_RELATIVE_AND_ABS_HPP_
|
79
src/myx/math/almost_equal_ulps.cpp
Normal file
79
src/myx/math/almost_equal_ulps.cpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#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
|
31
src/myx/math/almost_equal_ulps.hpp
Normal file
31
src/myx/math/almost_equal_ulps.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef MYX_MATH_ALMOST_EQUAL_ULPS_HPP_
|
||||||
|
#define MYX_MATH_ALMOST_EQUAL_ULPS_HPP_
|
||||||
|
|
||||||
|
#include <myx/math/float_cmp_types.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace myx {
|
||||||
|
|
||||||
|
namespace math {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Проверка на равенство двух аргументов типа float.
|
||||||
|
* Параметр maxUlpsDiff определяет максимальную разницу между аргументами,
|
||||||
|
* при которой они считаются равными.
|
||||||
|
*/
|
||||||
|
bool almost_equal_ulps( const float a, const float b,
|
||||||
|
const int maxUlpsDiff );
|
||||||
|
/**
|
||||||
|
* @brief Проверка на равенство двух аргументов типа double.
|
||||||
|
* Параметр maxUlpsDiff определяет максимальную разницу между аргументами,
|
||||||
|
* при которой они считаются равными.
|
||||||
|
*/
|
||||||
|
bool almost_equal_ulps( const double a, const double b,
|
||||||
|
const int maxUlpsDiff );
|
||||||
|
|
||||||
|
} // namespace math
|
||||||
|
|
||||||
|
} // namespace myx
|
||||||
|
|
||||||
|
#endif // MYX_MATH_ALMOST_EQUAL_ULPS_HPP_
|
73
src/myx/math/almost_equal_ulps_and_abs.cpp
Normal file
73
src/myx/math/almost_equal_ulps_and_abs.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include <myx/math/float_cmp_types.hpp>
|
||||||
|
#include <myx/math/almost_equal_ulps_and_abs.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace myx {
|
||||||
|
|
||||||
|
namespace math {
|
||||||
|
|
||||||
|
bool almost_equal_ulps_and_abs( const float a, const float b,
|
||||||
|
const float maxAbsDiff, const int maxUlpsDiff )
|
||||||
|
{
|
||||||
|
// Check if the numbers are really close -- needed
|
||||||
|
// when comparing numbers near zero.
|
||||||
|
float absDiff = fabsf( a - b );
|
||||||
|
if ( absDiff <= maxAbsDiff )
|
||||||
|
{
|
||||||
|
return( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
float_cmp_t uA( a );
|
||||||
|
float_cmp_t uB( b );
|
||||||
|
|
||||||
|
// Different signs means they do not match.
|
||||||
|
if ( uA.negative() != uB.negative() )
|
||||||
|
{
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the difference in ULPs.
|
||||||
|
int ulpsDiff = std::abs( uA.i - uB.i );
|
||||||
|
if ( ulpsDiff <= maxUlpsDiff )
|
||||||
|
{
|
||||||
|
return( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( false );
|
||||||
|
} // almost_equal_ulps_and_abs
|
||||||
|
|
||||||
|
|
||||||
|
bool almost_equal_ulps_and_abs( const double a, const double b,
|
||||||
|
const double maxAbsDiff, const int maxUlpsDiff )
|
||||||
|
{
|
||||||
|
// Check if the numbers are really close -- needed
|
||||||
|
// when comparing numbers near zero.
|
||||||
|
double absDiff = fabs( a - b );
|
||||||
|
if ( absDiff <= maxAbsDiff )
|
||||||
|
{
|
||||||
|
return( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
double_cmp_t uA( a );
|
||||||
|
double_cmp_t uB( b );
|
||||||
|
|
||||||
|
// Different signs means they do not match.
|
||||||
|
if ( uA.negative() != uB.negative() )
|
||||||
|
{
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the difference in ULPs.
|
||||||
|
auto ulpsDiff = std::abs( uA.i - uB.i );
|
||||||
|
if ( ulpsDiff <= maxUlpsDiff )
|
||||||
|
{
|
||||||
|
return( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( false );
|
||||||
|
} // almost_equal_ulps_and_abs
|
||||||
|
|
||||||
|
} // namespace math
|
||||||
|
|
||||||
|
} // namespace myx
|
29
src/myx/math/almost_equal_ulps_and_abs.hpp
Normal file
29
src/myx/math/almost_equal_ulps_and_abs.hpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef MYX_MATH_ALMOST_EQUAL_ULPS_HPP_
|
||||||
|
#define MYX_MATH_ALMOST_EQUAL_ULPS_HPP_
|
||||||
|
|
||||||
|
namespace myx {
|
||||||
|
|
||||||
|
namespace math {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Проверка на равенство двух аргументов типа float.
|
||||||
|
* Параметр maxAbsDiff определяет максимальную абсолютную допустимую разницу.
|
||||||
|
* Параметр maxUlpsDiff определяет максимальную разницу между аргументами,
|
||||||
|
* при которой они считаются равными.
|
||||||
|
*/
|
||||||
|
bool almost_equal_ulps_and_abs( const float a, const float b,
|
||||||
|
const float maxAbsDiff, const int maxUlpsDiff );
|
||||||
|
/**
|
||||||
|
* @brief Проверка на равенство двух аргументов типа double.
|
||||||
|
* Параметр maxAbsDiff определяет максимальную абсолютную допустимую разницу.
|
||||||
|
* Параметр maxUlpsDiff определяет максимальную разницу между аргументами,
|
||||||
|
* при которой они считаются равными.
|
||||||
|
*/
|
||||||
|
bool almost_equal_ulps_and_abs( const double a, const double b,
|
||||||
|
const double maxAbsDiff, const int maxUlpsDiff );
|
||||||
|
|
||||||
|
} // namespace math
|
||||||
|
|
||||||
|
} // namespace myx
|
||||||
|
|
||||||
|
#endif // MYX_MATH_ALMOST_EQUAL_ULPS_HPP_
|
54
src/myx/math/float_cmp_types.hpp
Normal file
54
src/myx/math/float_cmp_types.hpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#ifndef MYX_MATH_FLOAT_CMP_TYPES_HPP_
|
||||||
|
#define MYX_MATH_FLOAT_CMP_TYPES_HPP_
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Объединение для получения знака аргумента типа float.
|
||||||
|
*/
|
||||||
|
union float_cmp_t
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
float f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализация.
|
||||||
|
*/
|
||||||
|
float_cmp_t( float num = 0.0f ) : f( num )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Функция, возращающая true, если значение отрицательное
|
||||||
|
*/
|
||||||
|
bool negative() const
|
||||||
|
{
|
||||||
|
return( i < 0 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Объединение для получения знака аргумента типа double.
|
||||||
|
*/
|
||||||
|
union double_cmp_t
|
||||||
|
{
|
||||||
|
int64_t i;
|
||||||
|
double d;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализация.
|
||||||
|
*/
|
||||||
|
double_cmp_t( double num = 0.0l ) : d( num )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Функция, возращающая true, если значение отрицательное
|
||||||
|
*/
|
||||||
|
bool negative() const
|
||||||
|
{
|
||||||
|
return( i < 0 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MYX_MATH_FLOAT_CMP_TYPES_HPP_
|
Loading…
Reference in New Issue
Block a user