diff --git a/apps/shared/continuous_function_cache.cpp b/apps/shared/continuous_function_cache.cpp index df24141a9..a2fac0c01 100644 --- a/apps/shared/continuous_function_cache.cpp +++ b/apps/shared/continuous_function_cache.cpp @@ -19,6 +19,14 @@ void ContinuousFunctionCache::PrepareForCaching(void * fun, ContinuousFunctionCa } ContinuousFunction * function = static_cast(fun); + if (tStep < 3 * k_cacheHitTolerance) { + /* If tStep is lower than twice the tolerance, we risk shifting the index + * by 1 for cache hits. As an added safety, we add another buffer of + * k_cacheHitTolerance, raising the threshold for caching to three times + * the tolerance. */ + function->clearCache(); + return; + } if (function->cache() != cache) { cache->clear(); function->setCache(cache); diff --git a/apps/shared/continuous_function_cache.h b/apps/shared/continuous_function_cache.h index ee5bf598d..60faca9b8 100644 --- a/apps/shared/continuous_function_cache.h +++ b/apps/shared/continuous_function_cache.h @@ -27,7 +27,15 @@ public: void clear(); Poincare::Coordinate2D valueForParameter(const ContinuousFunction * function, Poincare::Context * context, float t); private: - static constexpr float k_cacheHitTolerance = 1e-3; + /* We need a certain amount of tolerance since we try to evaluate the + * equality of floats. But the value has to be chosen carefully. Too high of + * a tolerance causes false positives, which lead to errors in curves + * (ex : 1/x with a vertical line at 0). Too low of a tolerance causes false + * negatives, which slows down the drawing. + * + * The value 128*FLT_EPSILON has been found to be the lowest for which all + * indices verify indexForParameter(tMin + index * tStep) = index. */ + static constexpr float k_cacheHitTolerance = 128 * FLT_EPSILON; void invalidateBetween(int iInf, int iSup); void setRange(ContinuousFunction * function, float tMin, float tStep);