[poincare/zoom] Ignore imprecise float value

When looking for extrema in a function, we need to discard results where
the function growth rate is smaller than the precision of the float type
itself : these results are likely to be too noisy, and can cause false
positives.
e.g. : The sqrt(x^2+1)-x function

Change-Id: I6e2c002d7308b41a4c226d274cbb5d9efe4ea7db
This commit is contained in:
Gabriel Ozouf
2020-11-19 17:05:21 +01:00
committed by EmilieNumworks
parent adf28345b1
commit 291b400595

View File

@@ -22,6 +22,16 @@ constexpr float
Zoom::k_largeUnitMantissa,
Zoom::k_minimalRangeLength;
static bool DoesNotOverestimatePrecision(float dx, float y1, float y2, float y3) {
/* The float type looses precision surprisingly fast, and cannot confidently
* hold more than 6.6 digits of precision. Results more precise than that are
* too noisy to be be of any value. */
float yMin = std::min(y1, std::min(y2, y3));
float yMax = std::max(y1, std::max(y2, y3));
constexpr float maxPrecision = 2.4e-7f; // 2^-22 ~ 10^-6.6
return (yMax - yMin) / std::fabs(dx) > maxPrecision;
}
bool Zoom::InterestingRangesForDisplay(ValueAtAbscissa evaluation, float * xMin, float * xMax, float * yMin, float * yMax, float tMin, float tMax, Context * context, const void * auxiliary) {
assert(xMin && xMax && yMin && yMax);
@@ -84,7 +94,7 @@ bool Zoom::InterestingRangesForDisplay(ValueAtAbscissa evaluation, float * xMin,
/* Check for a change in the profile. */
const PointOfInterest variation = BoundOfIntervalOfDefinitionIsReached(yPrev, yNext) ? PointOfInterest::Bound :
RootExistsOnInterval(yPrev, yNext) ? PointOfInterest::Root :
ExtremumExistsOnInterval(yOld, yPrev, yNext) ? PointOfInterest::Extremum :
(ExtremumExistsOnInterval(yOld, yPrev, yNext) && DoesNotOverestimatePrecision(dXNext, yOld, yPrev, yNext)) ? PointOfInterest::Extremum :
PointOfInterest::None;
switch (static_cast<uint8_t>(variation)) {
/* The fallthrough is intentional, as we only want to update the Y