Skip to content

Commit

Permalink
Merge pull request letscontrolit#5194 from tonhuisman/bugfix/Math-com…
Browse files Browse the repository at this point in the history
…pare-dont-apply-epsilon-estimation-twice

[Math] Fix double estimation of epsilon in compare functions
  • Loading branch information
TD-er authored Dec 28, 2024
2 parents b32e519 + 3233b14 commit e450177
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 30 deletions.
68 changes: 48 additions & 20 deletions src/src/Helpers/ESPEasy_math.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
#include "../Helpers/ESPEasy_math.h"
#ifndef BUILD_NO_DEBUG
#include "../ESPEasyCore/ESPEasy_Log.h"
#include "../Helpers/StringConverter.h"
#endif // ifndef BUILD_NO_DEBUG

#include <Arduino.h>
// Need to include Arduino.h first, then cmath
// See: https://github.com/esp8266/Arduino/issues/8922#issuecomment-1542301697
#include <cmath>

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
constexpr double ESPEASY_DOUBLE_EPSILON = ESPEASY_DOUBLE_EPSILON_FACTOR * std::numeric_limits<double>::epsilon();
constexpr double ESPEASY_DOUBLE_EPSILON_NEG = -1.0 * ESPEASY_DOUBLE_EPSILON_FACTOR * std::numeric_limits<double>::epsilon();
constexpr double ESPEASY_DOUBLE_EPSILON = ESPEASY_DOUBLE_EPSILON_FACTOR * std::numeric_limits<double>::epsilon();
constexpr double ESPEASY_DOUBLE_EPSILON_NEG = -1.0 * ESPEASY_DOUBLE_EPSILON_FACTOR * std::numeric_limits<double>::epsilon();
#endif
constexpr float ESPEASY_FLOAT_EPSILON = std::numeric_limits<float>::epsilon();
constexpr float ESPEASY_FLOAT_EPSILON_NEG = -1.0f * std::numeric_limits<float>::epsilon();
constexpr float ESPEASY_FLOAT_EPSILON = ESPEASY_FLOAT_EPSILON_FACTOR * std::numeric_limits<float>::epsilon();
constexpr float ESPEASY_FLOAT_EPSILON_NEG = -1.0f * ESPEASY_FLOAT_EPSILON_FACTOR * std::numeric_limits<float>::epsilon();

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
int maxNrDecimals_fpType(const double& value)
Expand Down Expand Up @@ -70,15 +74,15 @@ bool approximatelyEqual(const float& a, const float& b) {
}

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
bool approximatelyEqual(const double& a, const double& b, double epsilon)
bool approximatelyEqual(const double& a, const double& b, double estimatedEpsilon)
{
return std::abs(a - b) <= ((std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a)) * epsilon);
return std::abs(a - b) <= estimatedEpsilon;
}
#endif

bool approximatelyEqual(const float& a, const float& b, float epsilon)
bool approximatelyEqual(const float& a, const float& b, float estimatedEpsilon)
{
return std::abs(a - b) <= ((std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a)) * epsilon);
return std::abs(a - b) <= estimatedEpsilon;
}

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
Expand All @@ -92,15 +96,27 @@ bool definitelyGreaterThan(const float& a, const float& b) {
}

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
bool definitelyGreaterThan(const double& a, const double& b, double epsilon)
bool definitelyGreaterThan(const double& a, const double& b, double estimatedEpsilon)
{
return (a - b) > ((std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a)) * epsilon);
#ifndef BUILD_NO_DEBUG
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
addLog(LOG_LEVEL_DEBUG, strformat(F("definitelyGreaterThan double a:%f b:%f ep:%.8g"),
a, b, estimatedEpsilon));
}
#endif // ifndef BUILD_NO_DEBUG
return (a - b) > estimatedEpsilon;
}
#endif

bool definitelyGreaterThan(const float& a, const float& b, float epsilon)
bool definitelyGreaterThan(const float& a, const float& b, float estimatedEpsilon)
{
return (a - b) > ((std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a)) * epsilon);
#ifndef BUILD_NO_DEBUG
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
addLog(LOG_LEVEL_DEBUG, strformat(F("definitelyGreaterThan float a:%f b:%f ep:%.8g"),
a, b, estimatedEpsilon));
}
#endif // ifndef BUILD_NO_DEBUG
return (a - b) > estimatedEpsilon;
}

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
Expand All @@ -114,15 +130,27 @@ bool definitelyLessThan(const float& a, const float& b) {
}

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
bool definitelyLessThan(const double& a, const double& b, double epsilon)
bool definitelyLessThan(const double& a, const double& b, double estimatedEpsilon)
{
return (b - a) > ((std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a)) * epsilon);
#ifndef BUILD_NO_DEBUG
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
addLog(LOG_LEVEL_DEBUG, strformat(F("definitelyLessThan double a:%f b:%f ep:%.8g"),
a, b, estimatedEpsilon));
}
#endif // ifndef BUILD_NO_DEBUG
return (b - a) > estimatedEpsilon;
}
#endif

bool definitelyLessThan(const float& a, const float& b, float epsilon)
bool definitelyLessThan(const float& a, const float& b, float estimatedEpsilon)
{
return (b - a) > ((std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a)) * epsilon);
#ifndef BUILD_NO_DEBUG
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
addLog(LOG_LEVEL_DEBUG, strformat(F("definitelyLessThan float a:%f b:%f ep:%.8g"),
a, b, estimatedEpsilon));
}
#endif // ifndef BUILD_NO_DEBUG
return (b - a) > estimatedEpsilon;
}

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
Expand All @@ -136,15 +164,15 @@ bool essentiallyEqual(const float& a, const float& b) {
}

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
bool essentiallyEqual(const double& a, const double& b, double epsilon)
bool essentiallyEqual(const double& a, const double& b, double estimatedEpsilon)
{
return std::abs(a - b) <= ((std::abs(a) > std::abs(b) ? std::abs(b) : std::abs(a)) * epsilon);
return std::abs(a - b) <= estimatedEpsilon;
}
#endif

bool essentiallyEqual(const float& a, const float& b, float epsilon)
bool essentiallyEqual(const float& a, const float& b, float estimatedEpsilon)
{
return std::abs(a - b) <= ((std::abs(a) > std::abs(b) ? std::abs(b) : std::abs(a)) * epsilon);
return std::abs(a - b) <= estimatedEpsilon;
}

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
Expand Down
20 changes: 10 additions & 10 deletions src/src/Helpers/ESPEasy_math.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

// Internal ESPEasy representation of double values
#define ESPEASY_DOUBLE_NR_DECIMALS 14
#define ESPEASY_DOUBLE_EPSILON_FACTOR 1000
#define ESPEASY_DOUBLE_EPSILON_FACTOR 2.0
#define ESPEASY_FLOAT_NR_DECIMALS 6
#define ESPEASY_FLOAT_EPSILON_FACTOR 1000
#define ESPEASY_FLOAT_EPSILON_FACTOR 2.0

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
int maxNrDecimals_fpType(const double& value);
Expand All @@ -23,36 +23,36 @@ bool approximatelyEqual(const double& a, const double& b);
#endif
bool approximatelyEqual(const float& a, const float& b);
#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
bool approximatelyEqual(const double& a, const double& b, double epsilon);
bool approximatelyEqual(const double& a, const double& b, double estimatedEpsilon);
#endif
bool approximatelyEqual(const float& a, const float& b, float epsilon);
bool approximatelyEqual(const float& a, const float& b, float estimatedEpsilon);

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
bool definitelyGreaterThan(const double& a, const double& b);
#endif
bool definitelyGreaterThan(const float& a, const float& b);
#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
bool definitelyGreaterThan(const double& a, const double& b, double epsilon);
bool definitelyGreaterThan(const double& a, const double& b, double estimatedEpsilon);
#endif
bool definitelyGreaterThan(const float& a, const float& b, float epsilon);
bool definitelyGreaterThan(const float& a, const float& b, float estimatedEpsilon);

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
bool definitelyLessThan(const double& a, const double& b);
#endif
bool definitelyLessThan(const float& a, const float& b);
#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
bool definitelyLessThan(const double& a, const double& b, double epsilon);
bool definitelyLessThan(const double& a, const double& b, double estimatedEpsilon);
#endif
bool definitelyLessThan(const float& a, const float& b, float epsilon);
bool definitelyLessThan(const float& a, const float& b, float estimatedEpsilon);

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
bool essentiallyEqual(const double& a, const double& b);
#endif
bool essentiallyEqual(const float& a, const float& b);
#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
bool essentiallyEqual(const double& a, const double& b, double epsilon);
bool essentiallyEqual(const double& a, const double& b, double estimatedEpsilon);
#endif
bool essentiallyEqual(const float& a, const float& b, float epsilon);
bool essentiallyEqual(const float& a, const float& b, float estimatedEpsilon);

#if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
bool essentiallyZero(const double& a);
Expand Down

0 comments on commit e450177

Please sign in to comment.