From 3db1cad18b5e9c1ddbf67c14511d890c5b807fc0 Mon Sep 17 00:00:00 2001 From: Hugo Saint-Vignes Date: Wed, 24 Jun 2020 14:42:29 +0200 Subject: [PATCH] [poincare] Move IsApproximatelyEqual to a better helper Change-Id: I056a96b3721005e01c6ef3f166a80a08195ff338 --- apps/regression/test/model.cpp | 21 +++++++++++---------- apps/statistics/test/store.cpp | 3 ++- poincare/include/poincare/helpers.h | 1 - poincare/src/helpers.cpp | 16 ---------------- poincare/test/helper.cpp | 15 +++++++++++++++ poincare/test/helper.h | 3 +++ 6 files changed, 31 insertions(+), 28 deletions(-) diff --git a/apps/regression/test/model.cpp b/apps/regression/test/model.cpp index 16b216114..4148288c3 100644 --- a/apps/regression/test/model.cpp +++ b/apps/regression/test/model.cpp @@ -6,6 +6,7 @@ #include "../regression_context.h" #include "../store.h" #include +#include using namespace Poincare; using namespace Regression; @@ -39,13 +40,13 @@ void assert_regression_is(double * xi, double * yi, int numberOfPoints, Model::T double * coefficients = store.coefficientsForSeries(series, &context); int numberOfCoefs = store.modelForSeries(series)->numberOfCoefficients(); for (int i = 0; i < numberOfCoefs; i++) { - quiz_assert(Helpers::IsApproximatelyEqual(coefficients[i], trueCoefficients[i], precision, reference)); + quiz_assert(IsApproximatelyEqual(coefficients[i], trueCoefficients[i], precision, reference)); } // Compute and check r2 value and sign double r2 = store.determinationCoefficientForSeries(series, &globalContext); quiz_assert(r2 >= 0.0); - quiz_assert(Helpers::IsApproximatelyEqual(r2, trueR2, precision, reference)); + quiz_assert(IsApproximatelyEqual(r2, trueR2, precision, reference)); } QUIZ_CASE(linear_regression) { @@ -190,15 +191,15 @@ void assert_column_calculations_is(double * xi, int numberOfPoints, double trueM // The least likely value to be null is trueSquaredSum double reference = trueSquaredSum; - quiz_assert(Helpers::IsApproximatelyEqual(variance, trueVariance, precision, reference)); - quiz_assert(Helpers::IsApproximatelyEqual(squaredSum, trueSquaredSum, precision, reference)); + quiz_assert(IsApproximatelyEqual(variance, trueVariance, precision, reference)); + quiz_assert(IsApproximatelyEqual(squaredSum, trueSquaredSum, precision, reference)); // adapt the reference reference = std::sqrt(trueSquaredSum); - quiz_assert(Helpers::IsApproximatelyEqual(mean, trueMean, precision, reference)); - quiz_assert(Helpers::IsApproximatelyEqual(sum, trueSum, precision, reference)); - quiz_assert(Helpers::IsApproximatelyEqual(standardDeviation, trueStandardDeviation, precision, reference)); + quiz_assert(IsApproximatelyEqual(mean, trueMean, precision, reference)); + quiz_assert(IsApproximatelyEqual(sum, trueSum, precision, reference)); + quiz_assert(IsApproximatelyEqual(standardDeviation, trueStandardDeviation, precision, reference)); } QUIZ_CASE(column_calculation) { @@ -236,8 +237,8 @@ void assert_regression_calculations_is(double * xi, double * yi, int numberOfPoi // trueProductSum and trueCovariance are using each other as reference // By construction, they often have a close value with a numberOfPoints factor - quiz_assert(Helpers::IsApproximatelyEqual(covariance, trueCovariance, precision, trueProductSum / numberOfPoints)); - quiz_assert(Helpers::IsApproximatelyEqual(productSum, trueProductSum, precision, trueCovariance * numberOfPoints)); + quiz_assert(IsApproximatelyEqual(covariance, trueCovariance, precision, trueProductSum / numberOfPoints)); + quiz_assert(IsApproximatelyEqual(productSum, trueProductSum, precision, trueCovariance * numberOfPoints)); // When trueR = 0, a DBL_EPSILON reference ensures that the only accepted errors are due to double approximations // sqrt is used because the R is computed from sqrt(V1*V0) @@ -245,7 +246,7 @@ void assert_regression_calculations_is(double * xi, double * yi, int numberOfPoi double r = store.correlationCoefficient(series); quiz_assert(r >= 0.0); - quiz_assert(Helpers::IsApproximatelyEqual(r, trueR, precision, reference)); + quiz_assert(IsApproximatelyEqual(r, trueR, precision, reference)); } QUIZ_CASE(regression_calculation) { diff --git a/apps/statistics/test/store.cpp b/apps/statistics/test/store.cpp index 1126dd8d9..24c43f4c6 100644 --- a/apps/statistics/test/store.cpp +++ b/apps/statistics/test/store.cpp @@ -4,6 +4,7 @@ #include #include "../store.h" #include +#include using namespace Poincare; @@ -12,7 +13,7 @@ namespace Statistics { void assert_value_approximately_equal_to(double d1, double d2, double precision, double reference) { quiz_assert((std::isnan(d1) && std::isnan(d2)) || (std::isinf(d1) && std::isinf(d2) && d1 * d2 > 0.0 /*same sign*/) - || Helpers::IsApproximatelyEqual(d1, d2, precision, reference)); + || IsApproximatelyEqual(d1, d2, precision, reference)); } void assert_data_statictics_equal_to(double v[], double n[], int numberOfData, double trueSumOfOccurrences, double trueMaxValue, double trueMinValue, double trueRange, double trueMean, double trueVariance, double trueStandardDeviation, double trueSampleStandardDeviation, double trueFirstQuartile, double trueThirdQuartile, double trueQuartileRange, double trueMedian, double trueSum, double trueSquaredValueSum) { diff --git a/poincare/include/poincare/helpers.h b/poincare/include/poincare/helpers.h index dab8dd8c7..517a64d2a 100644 --- a/poincare/include/poincare/helpers.h +++ b/poincare/include/poincare/helpers.h @@ -11,7 +11,6 @@ namespace Helpers { size_t AlignedSize(size_t realSize, size_t alignment); size_t Gcd(size_t a, size_t b); bool Rotate(uint32_t * dst, uint32_t * src, size_t len); -bool IsApproximatelyEqual(double observedValue, double expectedValue, double precision, double reference); } diff --git a/poincare/src/helpers.cpp b/poincare/src/helpers.cpp index a412693f8..577817248 100644 --- a/poincare/src/helpers.cpp +++ b/poincare/src/helpers.cpp @@ -98,21 +98,5 @@ bool Rotate(uint32_t * dst, uint32_t * src, size_t len) { return true; } -bool IsApproximatelyEqual(double observedValue, double expectedValue, double precision, double reference) { - /* Return true if observedValue and expectedValue are approximately equal, according to precision and reference parameters */ - if (expectedValue != 0.0) { - double relativeError = std::fabs((observedValue - expectedValue) / expectedValue); - // The relative error must be smaller than the precision - return relativeError <= precision; - } - if (reference != 0.0) { - double referenceRatio = std::fabs(observedValue / reference); - // The observedValue must be negligible against the reference - return referenceRatio <= precision; - } - // The observedValue must exactly match the expectedValue - return observedValue == expectedValue; -} - } } diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index 399cb589f..d940dd108 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -103,6 +103,21 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * }); } +bool IsApproximatelyEqual(double observedValue, double expectedValue, double precision, double reference) { + if (expectedValue != 0.0) { + double relativeError = std::fabs((observedValue - expectedValue) / expectedValue); + // The relative error must be smaller than the precision + return relativeError <= precision; + } + if (reference != 0.0) { + double referenceRatio = std::fabs(observedValue / reference); + // The observedValue must be negligible against the reference + return referenceRatio <= precision; + } + // The observedValue must exactly match the expectedValue + return observedValue == expectedValue; +} + template void assert_expression_approximates_to(const char * expression, const char * approximation, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat, int numberOfSignificantDigits) { int numberOfDigits = sizeof(T) == sizeof(double) ? PrintFloat::k_numberOfStoredSignificantDigits : PrintFloat::k_numberOfPrintedSignificantDigits; diff --git a/poincare/test/helper.h b/poincare/test/helper.h index afb122eb1..841a5bc11 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -47,6 +47,9 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * // Approximation +/* Return true if observedValue and expectedValue are approximately equal, + * according to precision and reference parameters */ +bool IsApproximatelyEqual(double observedValue, double expectedValue, double precision, double reference); template void assert_expression_approximates_to(const char * expression, const char * approximation, Poincare::Preferences::AngleUnit angleUnit = Degree, Poincare::Preferences::ComplexFormat complexFormat = Cartesian, int numberOfSignificantDigits = -1); void assert_expression_simplifies_and_approximates_to(const char * expression, const char * approximation, Poincare::Preferences::AngleUnit angleUnit = Degree, Poincare::Preferences::ComplexFormat complexFormat = Cartesian, int numberOfSignificantDigits = -1);