mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
-No more limit to the number of calculations -All calculations are memoized -Added tests to test/calculation_store.cpp Change-Id: Ia10e2b009576eaf4496ba44a0c88f6e7e76f6cef
85 lines
3.8 KiB
C++
85 lines
3.8 KiB
C++
#ifndef CALCULATION_CALCULATION_STORE_H
|
|
#define CALCULATION_CALCULATION_STORE_H
|
|
|
|
#include "calculation.h"
|
|
#include <apps/shared/expiring_pointer.h>
|
|
#include <poincare/print_float.h>
|
|
|
|
namespace Calculation {
|
|
|
|
/*
|
|
To optimize the storage space, we use one big buffer for all calculations.
|
|
The calculations are stored one after another while pointers to the end of each
|
|
calculation are stored at the end of the buffer, in the opposite direction.
|
|
By doing so, we can memoize every calculation entered while not limiting
|
|
the number of calculation stored in the buffer.
|
|
|
|
If the remaining space is too small for storing a new calculation, we
|
|
delete the oldest one.
|
|
|
|
Memory layout :
|
|
<- Available space for new calculations ->
|
|
+--------------------------------------------------------------------------------------------------------------------+
|
|
| | | | | | | | | |
|
|
| Calculation 3 | Calculation 2 | Calculation 1 | Calculation O | |p0|p1|p2|p3|
|
|
| Oldest | | | | | | | | |
|
|
+--------------------------------------------------------------------------------------------------------------------+
|
|
^ ^ ^ ^ ^ ^
|
|
m_buffer p3 p2 p1 p0 a
|
|
|
|
m_calculationAreaEnd = p0
|
|
a = addressOfPointerToCalculation(0)
|
|
*/
|
|
|
|
class CalculationStore {
|
|
public:
|
|
CalculationStore();
|
|
CalculationStore(char * buffer, int size);
|
|
Shared::ExpiringPointer<Calculation> calculationAtIndex(int i);
|
|
typedef KDCoordinate (*HeightComputer)(Calculation * c, bool expanded);
|
|
Shared::ExpiringPointer<Calculation> push(const char * text, Poincare::Context * context, HeightComputer heightComputer);
|
|
void deleteCalculationAtIndex(int i);
|
|
void deleteAll();
|
|
int remainingBufferSize() const { assert(m_calculationAreaEnd >= m_buffer); return m_bufferSize - (m_calculationAreaEnd - m_buffer) - m_numberOfCalculations*sizeof(Calculation*); }
|
|
int numberOfCalculations() const { return m_numberOfCalculations; }
|
|
Poincare::Expression ansExpression(Poincare::Context * context);
|
|
int bufferSize() { return m_bufferSize; }
|
|
|
|
private:
|
|
|
|
class CalculationIterator {
|
|
public:
|
|
CalculationIterator(const char * c) : m_calculation(reinterpret_cast<Calculation *>(const_cast<char *>(c))) {}
|
|
Calculation * operator*() { return m_calculation; }
|
|
bool operator!=(const CalculationIterator& it) const { return (m_calculation != it.m_calculation); }
|
|
CalculationIterator & operator++() {
|
|
m_calculation = m_calculation->next();
|
|
return *this;
|
|
}
|
|
protected:
|
|
Calculation * m_calculation;
|
|
};
|
|
|
|
CalculationIterator begin() const { return CalculationIterator(m_buffer); }
|
|
CalculationIterator end() const { return CalculationIterator(m_calculationAreaEnd); }
|
|
|
|
bool pushSerializeExpression(Poincare::Expression e, char * location, char * * newCalculationsLocation, int numberOfSignificantDigits = Poincare::PrintFloat::k_numberOfStoredSignificantDigits);
|
|
Shared::ExpiringPointer<Calculation> emptyStoreAndPushUndef(Poincare::Context * context, HeightComputer heightComputer);
|
|
|
|
char * m_buffer;
|
|
int m_bufferSize;
|
|
const char * m_calculationAreaEnd;
|
|
int m_numberOfCalculations;
|
|
|
|
size_t deleteOldestCalculation();
|
|
char * addressOfPointerToCalculationOfIndex(int i) {return m_buffer + m_bufferSize - (m_numberOfCalculations - i)*sizeof(Calculation *);}
|
|
|
|
// Memoization
|
|
char * beginingOfMemoizationArea() {return addressOfPointerToCalculationOfIndex(0);};
|
|
void recomputeMemoizedPointersAfterCalculationIndex(int index);
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|