mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[apps/graph] Limited number of cached functions
The caches used for function values memoization are now stored in ContinuousFunctionStore : there are now only a fixed number, instead of one per function. This effectively enables caching only for the first few functions on screen, while reducing the memory usage. Change-Id: I2ade091717f73a14a756fe527c773db8e8627be7
This commit is contained in:
committed by
Émilie Feral
parent
95fef86ec0
commit
42fcf557b8
@@ -16,6 +16,7 @@ public:
|
||||
return recordSatisfyingTestAtIndex(i, &isFunctionActiveOfType, &plotType);
|
||||
}
|
||||
Shared::ExpiringPointer<Shared::ContinuousFunction> modelForRecord(Ion::Storage::Record record) const { return Shared::ExpiringPointer<Shared::ContinuousFunction>(static_cast<Shared::ContinuousFunction *>(privateModelForRecord(record))); }
|
||||
Shared::ExpiringPointer<Shared::ContinuousFunctionCache> cacheAtIndex(int i) const { return (i < Shared::ContinuousFunctionCache::k_numberOfAvailableCaches) ? Shared::ExpiringPointer<Shared::ContinuousFunctionCache>(k_functionCaches + i) : nullptr; }
|
||||
Ion::Storage::Record::ErrorStatus addEmptyModel() override;
|
||||
private:
|
||||
const char * modelExtension() const override { return Ion::Storage::funcExtension; }
|
||||
@@ -26,6 +27,8 @@ private:
|
||||
return isFunctionActive(model, context) && plotType == static_cast<Shared::ContinuousFunction *>(model)->plotType();
|
||||
}
|
||||
mutable Shared::ContinuousFunction m_functions[k_maxNumberOfMemoizedModels];
|
||||
mutable Shared::ContinuousFunctionCache k_functionCaches[Shared::ContinuousFunctionCache::k_numberOfAvailableCaches];
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
const int activeFunctionsCount = functionStore->numberOfActiveFunctions();
|
||||
for (int i = 0; i < activeFunctionsCount ; i++) {
|
||||
Ion::Storage::Record record = functionStore->activeRecordAtIndex(i);
|
||||
ExpiringPointer<ContinuousFunction> f = functionStore->modelForRecord(record);;
|
||||
ExpiringPointer<ContinuousFunction> f = functionStore->modelForRecord(record);
|
||||
ExpiringPointer<ContinuousFunctionCache> cch = functionStore->cacheAtIndex(i);
|
||||
Shared::ContinuousFunction::PlotType type = f->plotType();
|
||||
Poincare::Expression e = f->expressionReduced(context());
|
||||
if (e.isUndefined() || (
|
||||
@@ -63,7 +64,7 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
Poincare::Context * c = (Poincare::Context *)context;
|
||||
return f->evaluateXYAtParameter(t, c);
|
||||
},
|
||||
&ContinuousFunctionCache::PrepareCache);
|
||||
&ContinuousFunctionCache::PrepareCache, cch.operator->());
|
||||
/* Draw tangent */
|
||||
if (m_tangent && record == m_selectedRecord) {
|
||||
float tangentParameterA = f->approximateDerivative(m_curveViewCursor->x(), context());
|
||||
@@ -86,7 +87,7 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
return f->evaluateXYAtParameter(t, c);
|
||||
}, f.operator->(), context(), false, f->color(),
|
||||
true, false, 0.0f, 0.0f, /* drawCurve's default arguments */
|
||||
&ContinuousFunctionCache::PrepareCache);
|
||||
&ContinuousFunctionCache::PrepareCache, cch.operator->());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ void ContinuousFunction::setPlotType(PlotType newPlotType, Poincare::Preferences
|
||||
|
||||
recordData()->setPlotType(newPlotType);
|
||||
|
||||
cache()->clear();
|
||||
clearCache();
|
||||
|
||||
// Recompute the layouts
|
||||
m_model.tidy();
|
||||
@@ -253,12 +253,12 @@ float ContinuousFunction::tMax() const {
|
||||
|
||||
void ContinuousFunction::setTMin(float tMin) {
|
||||
recordData()->setTMin(tMin);
|
||||
cache()->clear();
|
||||
clearCache();
|
||||
}
|
||||
|
||||
void ContinuousFunction::setTMax(float tMax) {
|
||||
recordData()->setTMax(tMax);
|
||||
cache()->clear();
|
||||
clearCache();
|
||||
}
|
||||
|
||||
void * ContinuousFunction::Model::expressionAddress(const Ion::Storage::Record * record) const {
|
||||
@@ -353,7 +353,7 @@ Poincare::Expression ContinuousFunction::sumBetweenBounds(double start, double e
|
||||
|
||||
Poincare::Coordinate2D<float> ContinuousFunction::checkForCacheHitAndEvaluate(float t, Poincare::Context * context) const {
|
||||
Poincare::Coordinate2D<float> res(NAN, NAN);
|
||||
if (cache()->filled()) {
|
||||
if (cacheIsFilled()) {
|
||||
res = cache()->valueForParameter(this, t);
|
||||
}
|
||||
if (std::isnan(res.x1()) || std::isnan(res.x2())) {
|
||||
@@ -364,7 +364,7 @@ Poincare::Coordinate2D<float> ContinuousFunction::checkForCacheHitAndEvaluate(fl
|
||||
}
|
||||
|
||||
Ion::Storage::Record::ErrorStatus ContinuousFunction::setContent(const char * c, Poincare::Context * context) {
|
||||
cache()->clear();
|
||||
clearCache();
|
||||
return ExpressionModelHandle::setContent(c, context);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,10 @@ public:
|
||||
Poincare::Expression sumBetweenBounds(double start, double end, Poincare::Context * context) const override;
|
||||
|
||||
// Cache
|
||||
ContinuousFunctionCache * cache() const { return const_cast<ContinuousFunctionCache *>(&m_cache); }
|
||||
ContinuousFunctionCache * cache() const { return m_cache; }
|
||||
void setCache(ContinuousFunctionCache * v) { m_cache = v; }
|
||||
void clearCache() { m_cache = nullptr; }
|
||||
bool cacheIsFilled() const { return cache() && cache()->filled(); }
|
||||
Ion::Storage::Record::ErrorStatus setContent(const char * c, Poincare::Context * context) override;
|
||||
private:
|
||||
constexpr static float k_polarParamRangeSearchNumberOfPoints = 100.0f; // This is ad hoc, no special justification
|
||||
@@ -125,7 +128,7 @@ private:
|
||||
RecordDataBuffer * recordData() const;
|
||||
template<typename T> Poincare::Coordinate2D<T> templatedApproximateAtParameter(T t, Poincare::Context * context) const;
|
||||
Model m_model;
|
||||
ContinuousFunctionCache m_cache;
|
||||
ContinuousFunctionCache * m_cache;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -5,20 +5,28 @@ namespace Shared {
|
||||
|
||||
constexpr int ContinuousFunctionCache::k_sizeOfCache;
|
||||
constexpr float ContinuousFunctionCache::k_cacheHitTolerance;
|
||||
constexpr int ContinuousFunctionCache::k_numberOfAvailableCaches;
|
||||
|
||||
// public
|
||||
void ContinuousFunctionCache::PrepareCache(void * f, void * c, float tMin, float tStep) {
|
||||
void ContinuousFunctionCache::PrepareCache(void * f, void * ctx, void * cch, float tMin, float tStep) {
|
||||
if (!cch) {
|
||||
return;
|
||||
}
|
||||
ContinuousFunction * function = (ContinuousFunction *)f;
|
||||
Poincare::Context * context = (Poincare::Context *)c;
|
||||
ContinuousFunctionCache * functionCache = function->cache();
|
||||
if (functionCache->filled() && tStep / StepFactor(function) == functionCache->step()) {
|
||||
Poincare::Context * context = (Poincare::Context *)ctx;
|
||||
if (!function->cache()) {
|
||||
ContinuousFunctionCache * cache = (ContinuousFunctionCache *)cch;
|
||||
cache->clear();
|
||||
function->setCache(cache);
|
||||
}
|
||||
if (function->cache()->filled() && tStep / StepFactor(function) == function->cache()->step()) {
|
||||
if (function->plotType() == ContinuousFunction::PlotType::Cartesian) {
|
||||
function->cache()->pan(function, context, tMin);
|
||||
}
|
||||
return;
|
||||
}
|
||||
functionCache->setRange(function, tMin, tStep);
|
||||
functionCache->memoize(function, context);
|
||||
function->cache()->setRange(function, tMin, tStep);
|
||||
function->cache()->memoize(function, context);
|
||||
}
|
||||
|
||||
void ContinuousFunctionCache::clear() {
|
||||
|
||||
@@ -11,7 +11,11 @@ class ContinuousFunction;
|
||||
|
||||
class ContinuousFunctionCache {
|
||||
public:
|
||||
static void PrepareCache(void * f, void * c, float tMin, float tStep);
|
||||
/* The size of the cache is chosen to optimize the display of cartesian
|
||||
* function */
|
||||
static constexpr int k_numberOfAvailableCaches = 2;
|
||||
|
||||
static void PrepareCache(void * f, void * ctx, void * cch, float tMin, float tStep);
|
||||
|
||||
float step() const { return m_tStep; }
|
||||
bool filled() const { return m_filled; }
|
||||
|
||||
@@ -602,8 +602,8 @@ const uint8_t thickStampMask[(thickStampSize+1)*(thickStampSize+1)] = {
|
||||
|
||||
constexpr static int k_maxNumberOfIterations = 10;
|
||||
|
||||
void CurveView::drawCurve(KDContext * ctx, KDRect rect, float tStart, float tEnd, float tStep, EvaluateXYForFloatParameter xyFloatEvaluation, void * model, void * context, bool drawStraightLinesEarly, KDColor color, bool thick, bool colorUnderCurve, float colorLowerBound, float colorUpperBound, EvaluateXYForDoubleParameter xyDoubleEvaluation, PrepareContinuousFunction functionPreparator) const {
|
||||
functionPreparator(model, context, tStart, tStep);
|
||||
void CurveView::drawCurve(KDContext * ctx, KDRect rect, float tStart, float tEnd, float tStep, EvaluateXYForFloatParameter xyFloatEvaluation, void * model, void * context, bool drawStraightLinesEarly, KDColor color, bool thick, bool colorUnderCurve, float colorLowerBound, float colorUpperBound, EvaluateXYForDoubleParameter xyDoubleEvaluation, PrepareContinuousFunction functionPreparator, void * cache) const {
|
||||
functionPreparator(model, context, cache, tStart, tStep);
|
||||
float previousT = NAN;
|
||||
float t = NAN;
|
||||
float previousX = NAN;
|
||||
@@ -635,7 +635,7 @@ void CurveView::drawCurve(KDContext * ctx, KDRect rect, float tStart, float tEnd
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void CurveView::drawCartesianCurve(KDContext * ctx, KDRect rect, float xMin, float xMax, EvaluateXYForFloatParameter xyFloatEvaluation, void * model, void * context, KDColor color, bool thick, bool colorUnderCurve, float colorLowerBound, float colorUpperBound, EvaluateXYForDoubleParameter xyDoubleEvaluation, PrepareContinuousFunction functionPreparator) const {
|
||||
void CurveView::drawCartesianCurve(KDContext * ctx, KDRect rect, float xMin, float xMax, EvaluateXYForFloatParameter xyFloatEvaluation, void * model, void * context, KDColor color, bool thick, bool colorUnderCurve, float colorLowerBound, float colorUpperBound, EvaluateXYForDoubleParameter xyDoubleEvaluation, PrepareContinuousFunction functionPreparator, void * cache) const {
|
||||
float rectLeft = pixelToFloat(Axis::Horizontal, rect.left() - k_externRectMargin);
|
||||
float rectRight = pixelToFloat(Axis::Horizontal, rect.right() + k_externRectMargin);
|
||||
float tStart = std::isnan(rectLeft) ? xMin : std::max(xMin, rectLeft);
|
||||
@@ -645,7 +645,7 @@ void CurveView::drawCartesianCurve(KDContext * ctx, KDRect rect, float xMin, flo
|
||||
return;
|
||||
}
|
||||
float tStep = pixelWidth();
|
||||
drawCurve(ctx, rect, tStart, tEnd, tStep, xyFloatEvaluation, model, context, true, color, thick, colorUnderCurve, colorLowerBound, colorUpperBound, xyDoubleEvaluation, functionPreparator);
|
||||
drawCurve(ctx, rect, tStart, tEnd, tStep, xyFloatEvaluation, model, context, true, color, thick, colorUnderCurve, colorLowerBound, colorUpperBound, xyDoubleEvaluation, functionPreparator, cache);
|
||||
}
|
||||
|
||||
void CurveView::drawHistogram(KDContext * ctx, KDRect rect, EvaluateYForX yEvaluation, void * model, void * context, float firstBarAbscissa, float barWidth,
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
typedef Poincare::Coordinate2D<float> (*EvaluateXYForFloatParameter)(float t, void * model, void * context);
|
||||
typedef Poincare::Coordinate2D<double> (*EvaluateXYForDoubleParameter)(double t, void * model, void * context);
|
||||
typedef float (*EvaluateYForX)(float x, void * model, void * context);
|
||||
typedef void (* PrepareContinuousFunction)(void * model, void * context, float xMin, float xStep);
|
||||
typedef void (* PrepareContinuousFunction)(void * model, void * context, void * cache, float xMin, float xStep);
|
||||
enum class Axis {
|
||||
Horizontal = 0,
|
||||
Vertical = 1
|
||||
@@ -108,8 +108,8 @@ protected:
|
||||
void drawGrid(KDContext * ctx, KDRect rect) const;
|
||||
void drawAxes(KDContext * ctx, KDRect rect) const;
|
||||
void drawAxis(KDContext * ctx, KDRect rect, Axis axis) const;
|
||||
void drawCurve(KDContext * ctx, KDRect rect, float tStart, float tEnd, float tStep, EvaluateXYForFloatParameter xyFloatEvaluation, void * model, void * context, bool drawStraightLinesEarly, KDColor color, bool thick = true, bool colorUnderCurve = false, float colorLowerBound = 0.0f, float colorUpperBound = 0.0f, EvaluateXYForDoubleParameter xyDoubleEvaluation = nullptr, PrepareContinuousFunction functionPreparator = [](void * model, void * context, float xMin, float xStep) {}) const;
|
||||
void drawCartesianCurve(KDContext * ctx, KDRect rect, float xMin, float xMax, EvaluateXYForFloatParameter xyFloatEvaluation, void * model, void * context, KDColor color, bool thick = true, bool colorUnderCurve = false, float colorLowerBound = 0.0f, float colorUpperBound = 0.0f, EvaluateXYForDoubleParameter xyDoubleEvaluation = nullptr, PrepareContinuousFunction functionPreparator = [](void * model, void * context, float xMin, float xStep) {}) const;
|
||||
void drawCurve(KDContext * ctx, KDRect rect, float tStart, float tEnd, float tStep, EvaluateXYForFloatParameter xyFloatEvaluation, void * model, void * context, bool drawStraightLinesEarly, KDColor color, bool thick = true, bool colorUnderCurve = false, float colorLowerBound = 0.0f, float colorUpperBound = 0.0f, EvaluateXYForDoubleParameter xyDoubleEvaluation = nullptr,PrepareContinuousFunction functionPreparator = [](void * model, void * context, void * cache, float xMin, float xStep) {}, void * cache = nullptr) const;
|
||||
void drawCartesianCurve(KDContext * ctx, KDRect rect, float xMin, float xMax, EvaluateXYForFloatParameter xyFloatEvaluation, void * model, void * context, KDColor color, bool thick = true, bool colorUnderCurve = false, float colorLowerBound = 0.0f, float colorUpperBound = 0.0f, EvaluateXYForDoubleParameter xyDoubleEvaluation = nullptr, PrepareContinuousFunction functionPreparator = [](void * model, void * context, void * cache, float xMin, float xStep) {}, void * cache = nullptr) const;
|
||||
void drawHistogram(KDContext * ctx, KDRect rect, EvaluateYForX yEvaluation, void * model, void * context, float firstBarAbscissa, float barWidth,
|
||||
bool fillBar, KDColor defaultColor, KDColor highlightColor, float highlightLowerBound = INFINITY, float highlightUpperBound = -INFINITY) const;
|
||||
void computeLabels(Axis axis);
|
||||
|
||||
Reference in New Issue
Block a user