[apps/stats] Compute the number of values to fill in with the formula

This commit is contained in:
Léa Saviot
2018-06-01 11:22:46 +02:00
parent 5da90b5160
commit 79435ff3fb
6 changed files with 71 additions and 9 deletions

View File

@@ -13,7 +13,7 @@ void SeriesContext::setExpressionForSymbolName(const Expression * expression, co
}
const Expression * SeriesContext::expressionForSymbol(const Symbol * symbol) {
if (symbol->isSeriesSymbol()) {
if (Symbol::isSeriesSymbol(symbol->name())) {
const char * seriesName = Symbol::textForSpecialSymbols(symbol->name());
assert(strlen(seriesName) == 2);

View File

@@ -21,12 +21,30 @@ StoreController::StoreController(Responder * parentResponder, Store * store, But
void StoreController::fillColumnWithFormula(Expression * formula) {
int currentColumn = selectedColumn();
// Fetch the series used in the formula to:
// - Make sure the current filled column is not inside
// - Compute the size of the filled in series
// Fetch the series used in the formula to compute the size of the filled in series
char variables[7] = {0, 0, 0, 0, 0, 0, 0};
int numberOfVariables = formula->getVariables(Symbol::isSeriesSymbol, variables);
assert(numberOfVariables >= 0);
int numberOfValuesToCompute = -1;
int index = 0;
while (variables[index] != 0) {
const char * seriesName = Symbol::textForSpecialSymbols(variables[index]);
assert(strlen(seriesName) == 2);
int series = (int)(seriesName[1] - '0') - 1;
assert(series >= 0 && series < FloatPairStore::k_numberOfSeries);
if (numberOfValuesToCompute == -1) {
numberOfValuesToCompute = m_store->numberOfPairsOfSeries(series);
} else {
numberOfValuesToCompute = min(numberOfValuesToCompute, m_store->numberOfPairsOfSeries(series));
}
index++;
}
if (numberOfValuesToCompute == -1) {
numberOfValuesToCompute = m_store->numberOfPairsOfSeries(selectedColumn()/FloatPairStore::k_numberOfColumnsPerSeries);
}
SeriesContext seriesContext(m_store, const_cast<AppsContainer *>(static_cast<const AppsContainer *>(app()->container()))->globalContext());
for (int j = 0; j < 2; j++) {
for (int j = 0; j < numberOfValuesToCompute; j++) {
// Set the context
seriesContext.setSeriesPairIndex(j);
// Compute the new value using the formula

View File

@@ -238,6 +238,15 @@ public:
template<typename T> Expression * approximate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const;
template<typename T> T approximateToScalar(Context& context, AngleUnit angleUnit = AngleUnit::Default) const;
template<typename T> static T approximateToScalar(const char * text, Context& context, AngleUnit angleUnit = AngleUnit::Default);
/* getVariables fills the table variables with the variable present in the
* expression and returns the number of entries in filled in variables.
* For instance getVariables('x+y+2*w/cos(4)') would result in
* variables = « xyw » and would return 3. If the final number of
* variables would overflow the maxNumberOfVariables, getVariables return -1 */
static constexpr int k_maxNumberOfVariables = 6;
typedef bool (*isVariableTest)(char c);
virtual int getVariables(isVariableTest isVariable, char * variables) const;
protected:
/* Constructor */
Expression() : m_parent(nullptr) {}

View File

@@ -45,11 +45,12 @@ public:
Sign sign() const override;
bool isMatrixSymbol() const;
bool isScalarSymbol() const;
bool isSeriesSymbol() const;
static bool isSeriesSymbol(char c);
bool isApproximate(Context & context) const;
float characteristicXRange(Context & context, AngleUnit angleUnit = AngleUnit::Default) const override;
bool hasAnExactRepresentation(Context & context) const;
static const char * textForSpecialSymbols(char name);
int getVariables(isVariableTest isVariable, char * variables) const override;
private:
Expression * replaceSymbolWithExpression(char symbol, Expression * expression) override;
/* Simplification */

View File

@@ -371,6 +371,20 @@ template<typename T> T Expression::epsilon() {
return epsilon;
}
/* Get variables */
int Expression::getVariables(isVariableTest isVariable, char * variables) const {
int numberOfVariables = 0;
for (int i = 0; i < numberOfOperands(); i++) {
int n = operand(i)->getVariables(isVariable, variables);
if (n < 0) {
return -1;
}
numberOfVariables = n > numberOfVariables ? n : numberOfVariables;
}
return numberOfVariables;
}
}
template Poincare::Expression * Poincare::Expression::approximate<double>(Context& context, AngleUnit angleUnit) const;

View File

@@ -71,6 +71,26 @@ const char * Symbol::textForSpecialSymbols(char name) {
}
}
int Symbol::getVariables(isVariableTest isVariable, char * variables) const {
size_t variablesLength = strlen(variables);
if (isVariable(m_name)) {
char * currentChar = variables;
while (*currentChar != 0) {
if (*currentChar == m_name) {
return variablesLength;
}
currentChar++;
}
if (variablesLength < k_maxNumberOfVariables) {
variables[variablesLength] = m_name;
variables[variablesLength+1] = 0;
return variablesLength+1;
}
return -1;
}
return variablesLength;
}
Symbol::SpecialSymbols Symbol::matrixSymbol(char index) {
switch (index - '0') {
case 0:
@@ -244,7 +264,7 @@ ExpressionLayout * Symbol::privateCreateLayout(PrintFloat::Mode floatDisplayMode
false),
false);
}
if (isMatrixSymbol() || isSeriesSymbol()) {
if (isMatrixSymbol() || isSeriesSymbol(m_name)) {
return LayoutEngine::createStringLayout(textForSpecialSymbols(m_name), 2);
}
return LayoutEngine::createStringLayout(&m_name, 1);
@@ -281,8 +301,8 @@ bool Symbol::isScalarSymbol() const {
return false;
}
bool Symbol::isSeriesSymbol() const {
if (m_name >= (char)SpecialSymbols::V1 && m_name <= (char)SpecialSymbols::N3) {
bool Symbol::isSeriesSymbol(char c) {
if (c >= (char)SpecialSymbols::V1 && c <= (char)SpecialSymbols::N3) {
return true;
}
return false;