[poincare] Move IsApproximatelyEqual to a better helper

Change-Id: I056a96b3721005e01c6ef3f166a80a08195ff338
This commit is contained in:
Hugo Saint-Vignes
2020-06-24 14:42:29 +02:00
committed by Émilie Feral
parent 9f4aafd6b6
commit 3db1cad18b
6 changed files with 31 additions and 28 deletions

View File

@@ -6,6 +6,7 @@
#include "../regression_context.h"
#include "../store.h"
#include <poincare/helpers.h>
#include <poincare/test/helper.h>
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) {

View File

@@ -4,6 +4,7 @@
#include <cmath>
#include "../store.h"
#include <poincare/helpers.h>
#include <poincare/test/helper.h>
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) {

View File

@@ -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);
}

View File

@@ -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;
}
}
}

View File

@@ -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<typename T>
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;

View File

@@ -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<typename T>
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);