Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Math] Fix double estimation of epsilon in compare functions #5194

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading