From 0fcec0f62a33e953b33a911ad1215e20dec69095 Mon Sep 17 00:00:00 2001 From: paulhoux Date: Wed, 27 Dec 2023 12:50:18 +0100 Subject: [PATCH 1/5] Added comparison functions for floats and doubles, providing a safer way to do things like `double value; if( value == 0.0 ){}`. --- include/cinder/CinderMath.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/include/cinder/CinderMath.h b/include/cinder/CinderMath.h index 9de0fb53bc..509162bb86 100644 --- a/include/cinder/CinderMath.h +++ b/include/cinder/CinderMath.h @@ -126,6 +126,40 @@ struct CI_API math const double EPSILON_VALUE = 4.37114e-05; #define EPSILON EPSILON_VALUE +CI_API inline bool approxZero( float n, float epsilon = float(EPSILON) ) +{ + return std::abs( n ) < epsilon; +} + +CI_API inline bool approxZero( double n, double epsilon = EPSILON ) +{ + return std::abs( n ) < epsilon; +} + +CI_API inline float roundToZero( float n, float epsilon = float(EPSILON) ) +{ + if( std::abs( n ) < epsilon ) + return 0.0f; + return n; +} + +CI_API inline float roundToZero( double n, double epsilon = EPSILON ) +{ + if( std::abs( n ) < epsilon ) + return 0.0f; + return n; +} + +CI_API inline bool approxEqual( float a, float b, float epsilon = float(EPSILON) ) +{ + return std::abs( b - a ) < epsilon; +} + +CI_API inline bool approxEqual( double a, double b, double epsilon = EPSILON ) +{ + return std::abs( b - a ) < epsilon; +} + inline float toRadians( float x ) { return x * 0.017453292519943295769f; // ( x * PI / 180 ) From 7e9a6ec0772eef7ae8b55b9b04670e99ab31cdbe Mon Sep 17 00:00:00 2001 From: paulhoux Date: Wed, 27 Dec 2023 12:56:33 +0100 Subject: [PATCH 2/5] Fixed a stupid oversight. --- include/cinder/CinderMath.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/cinder/CinderMath.h b/include/cinder/CinderMath.h index 509162bb86..b608dcca66 100644 --- a/include/cinder/CinderMath.h +++ b/include/cinder/CinderMath.h @@ -143,10 +143,10 @@ CI_API inline float roundToZero( float n, float epsilon = float(EPSILON) ) return n; } -CI_API inline float roundToZero( double n, double epsilon = EPSILON ) +CI_API inline double roundToZero( double n, double epsilon = EPSILON ) { if( std::abs( n ) < epsilon ) - return 0.0f; + return 0.0; return n; } From 4e8916a2359d5406611ab8bf0446d181d197f58f Mon Sep 17 00:00:00 2001 From: paulhoux Date: Wed, 27 Dec 2023 17:09:12 +0100 Subject: [PATCH 3/5] Added approxEqualRelative() functions and removed the custom epsilon in favor of FLT_EPSILON and DBL_EPSILON. --- include/cinder/CinderMath.h | 51 ++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/include/cinder/CinderMath.h b/include/cinder/CinderMath.h index b608dcca66..7eb9791ecb 100644 --- a/include/cinder/CinderMath.h +++ b/include/cinder/CinderMath.h @@ -123,43 +123,76 @@ struct CI_API math #define M_PI 3.14159265358979323846 #endif -const double EPSILON_VALUE = 4.37114e-05; -#define EPSILON EPSILON_VALUE - -CI_API inline bool approxZero( float n, float epsilon = float(EPSILON) ) +CI_API inline bool approxZero( float n, float epsilon = FLT_EPSILON ) { return std::abs( n ) < epsilon; } -CI_API inline bool approxZero( double n, double epsilon = EPSILON ) +CI_API inline bool approxZero( double n, double epsilon = DBL_EPSILON ) { return std::abs( n ) < epsilon; } -CI_API inline float roundToZero( float n, float epsilon = float(EPSILON) ) +CI_API inline float roundToZero( float n, float epsilon = FLT_EPSILON ) { if( std::abs( n ) < epsilon ) return 0.0f; return n; } -CI_API inline double roundToZero( double n, double epsilon = EPSILON ) +CI_API inline double roundToZero( double n, double epsilon = DBL_EPSILON ) { if( std::abs( n ) < epsilon ) return 0.0; return n; } -CI_API inline bool approxEqual( float a, float b, float epsilon = float(EPSILON) ) +CI_API inline bool approxEqual( float a, float b, float epsilon = FLT_EPSILON ) { return std::abs( b - a ) < epsilon; } -CI_API inline bool approxEqual( double a, double b, double epsilon = EPSILON ) +CI_API inline bool approxEqual( double a, double b, double epsilon = DBL_EPSILON ) { return std::abs( b - a ) < epsilon; } +CI_API inline bool approxEqualRelative( float a, float b, float maxRelDiff = FLT_EPSILON ) +{ + // See: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ + + // Calculate the difference. + float diff = std::abs( a - b ); + a = std::abs( a ); + b = std::abs( b ); + + // Find the largest. + float largest = ( b > a ) ? b : a; + + if( diff <= largest * maxRelDiff ) + return true; + + return false; +} + +CI_API inline bool approxEqualRelative( double a, double b, double maxRelDiff = DBL_EPSILON ) +{ + // See: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ + + // Calculate the difference. + double diff = std::abs( a - b ); + a = std::abs( a ); + b = std::abs( b ); + + // Find the largest. + double largest = ( b > a ) ? b : a; + + if( diff <= largest * maxRelDiff ) + return true; + + return false; +} + inline float toRadians( float x ) { return x * 0.017453292519943295769f; // ( x * PI / 180 ) From f2eb0c610a826f45fe3c5c02ac475a5de79bf6f7 Mon Sep 17 00:00:00 2001 From: paulhoux Date: Fri, 29 Dec 2023 12:34:54 +0100 Subject: [PATCH 4/5] Reverted the removal of EPSILON_VALUE, because it broke older code that relied on it. Also reverted back to using this defined EPSILON_VALUE, because it's larger and more appropriate than FLT_EPSILON or DBL_EPSILON in most cases, specifically the cases for which these functions were added to Cinder. --- include/cinder/CinderMath.h | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/include/cinder/CinderMath.h b/include/cinder/CinderMath.h index 7eb9791ecb..d9cf19efbc 100644 --- a/include/cinder/CinderMath.h +++ b/include/cinder/CinderMath.h @@ -123,41 +123,44 @@ struct CI_API math #define M_PI 3.14159265358979323846 #endif -CI_API inline bool approxZero( float n, float epsilon = FLT_EPSILON ) +constexpr double EPSILON_VALUE = 4.37114e-05; +#define EPSILON EPSILON_VALUE + +CI_API inline bool approxZero( float n, float epsilon = float(EPSILON_VALUE) ) { return std::abs( n ) < epsilon; } -CI_API inline bool approxZero( double n, double epsilon = DBL_EPSILON ) +CI_API inline bool approxZero( double n, double epsilon = EPSILON_VALUE ) { return std::abs( n ) < epsilon; } -CI_API inline float roundToZero( float n, float epsilon = FLT_EPSILON ) +CI_API inline float roundToZero( float n, float epsilon = float(EPSILON_VALUE) ) { - if( std::abs( n ) < epsilon ) + if( approxZero( n, epsilon ) ) return 0.0f; return n; } -CI_API inline double roundToZero( double n, double epsilon = DBL_EPSILON ) +CI_API inline double roundToZero( double n, double epsilon = EPSILON_VALUE ) { - if( std::abs( n ) < epsilon ) + if( approxZero( n, epsilon ) ) return 0.0; return n; } -CI_API inline bool approxEqual( float a, float b, float epsilon = FLT_EPSILON ) +CI_API inline bool approxEqual( float a, float b, float epsilon = float(EPSILON_VALUE) ) { return std::abs( b - a ) < epsilon; } -CI_API inline bool approxEqual( double a, double b, double epsilon = DBL_EPSILON ) +CI_API inline bool approxEqual( double a, double b, double epsilon = EPSILON_VALUE ) { return std::abs( b - a ) < epsilon; } -CI_API inline bool approxEqualRelative( float a, float b, float maxRelDiff = FLT_EPSILON ) +CI_API inline bool approxEqualRelative( float a, float b, float maxRelDiff = float(EPSILON_VALUE) ) { // See: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ @@ -175,7 +178,7 @@ CI_API inline bool approxEqualRelative( float a, float b, float maxRelDiff = FLT return false; } -CI_API inline bool approxEqualRelative( double a, double b, double maxRelDiff = DBL_EPSILON ) +CI_API inline bool approxEqualRelative( double a, double b, double maxRelDiff = EPSILON_VALUE ) { // See: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ From b98f807e5baba05eda731a569d5172d20ca1e7d6 Mon Sep 17 00:00:00 2001 From: paulhoux Date: Fri, 29 Dec 2023 12:44:39 +0100 Subject: [PATCH 5/5] Tidying up. --- include/cinder/CinderMath.h | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/include/cinder/CinderMath.h b/include/cinder/CinderMath.h index d9cf19efbc..e8e9c1bab7 100644 --- a/include/cinder/CinderMath.h +++ b/include/cinder/CinderMath.h @@ -138,16 +138,12 @@ CI_API inline bool approxZero( double n, double epsilon = EPSILON_VALUE ) CI_API inline float roundToZero( float n, float epsilon = float(EPSILON_VALUE) ) { - if( approxZero( n, epsilon ) ) - return 0.0f; - return n; + return approxZero( n, epsilon ) ? 0.0f : n; } CI_API inline double roundToZero( double n, double epsilon = EPSILON_VALUE ) { - if( approxZero( n, epsilon ) ) - return 0.0; - return n; + return approxZero( n, epsilon ) ? 0.0 : n; } CI_API inline bool approxEqual( float a, float b, float epsilon = float(EPSILON_VALUE) ) @@ -165,12 +161,12 @@ CI_API inline bool approxEqualRelative( float a, float b, float maxRelDiff = flo // See: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ // Calculate the difference. - float diff = std::abs( a - b ); - a = std::abs( a ); - b = std::abs( b ); + const float diff = std::abs( a - b ); // Find the largest. - float largest = ( b > a ) ? b : a; + a = std::abs( a ); + b = std::abs( b ); + const float largest = ( b > a ) ? b : a; if( diff <= largest * maxRelDiff ) return true; @@ -183,12 +179,12 @@ CI_API inline bool approxEqualRelative( double a, double b, double maxRelDiff = // See: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ // Calculate the difference. - double diff = std::abs( a - b ); - a = std::abs( a ); - b = std::abs( b ); + const double diff = std::abs( a - b ); // Find the largest. - double largest = ( b > a ) ? b : a; + a = std::abs( a ); + b = std::abs( b ); + const double largest = ( b > a ) ? b : a; if( diff <= largest * maxRelDiff ) return true;