[poincare] Implement getVariables on Expression

This commit is contained in:
Émilie Feral
2018-05-25 13:28:31 +02:00
parent bcdc5c895c
commit 1cac2693c3
6 changed files with 70 additions and 1 deletions

View File

@@ -21,7 +21,7 @@ private:
return emptyModel();
}
void setModelAtIndex(Shared::ExpressionModel * f, int i) override;
static constexpr int k_maxNumberOfEquations = 6;
static constexpr int k_maxNumberOfEquations = Poincare::Expression::k_maxNumberOfVariables; // Enable the same number of equations as the number of unknown variables
Equation m_equations[k_maxNumberOfEquations];;
};

View File

@@ -215,6 +215,17 @@ public:
* - (-1) if the expression is not a polynome
* - the degree of the polynome otherwise */
virtual int polynomialDegree(char symbolName) const;
/* 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 = ['x', 'y', 'w'] and would return 3. If the final number of
* variables would overflow the maxNumberOfVariables, getVariables return -1 */
static constexpr int k_maxNumberOfVariables = 6;
virtual int getVariables(char * variables) const;
/* getPolynomialCoefficients fill the table coefficients with the expressions
* of the first 4 polynomial coefficients. coefficients is null-terminated
* and has up to 4 entries. */
//virtual void getPolynomialCoefficients(char symbolName, Expression ** coefficients) const;
/* Comparison */
/* isIdenticalTo is the "easy" equality, it returns true if both trees have

View File

@@ -36,6 +36,7 @@ public:
Type type() const override;
Expression * clone() const override;
int polynomialDegree(char symbolName) const override;
int getVariables(char * variables) const override;
Sign sign() const override;
bool isMatrixSymbol() const;
bool isScalarSymbol() const;

View File

@@ -207,6 +207,18 @@ int Expression::polynomialDegree(char symbolName) const {
return 0;
}
int Expression::getVariables(char * variables) const {
int numberOfVariables = 0;
for (int i = 0; i < numberOfOperands(); i++) {
int n = operand(i)->getVariables(variables);
if (n < 0) {
return -1;
}
numberOfVariables = n > numberOfVariables ? n : numberOfVariables;
}
return numberOfVariables;
}
bool Expression::isOfType(Type * types, int length) const {
for (int i = 0; i < length; i++) {
if (type() == types[i]) {

View File

@@ -113,6 +113,26 @@ int Symbol::polynomialDegree(char symbol) const {
return 0;
}
int Symbol::getVariables(char * variables) const {
size_t variablesLength = strlen(variables);
if (m_name >= 'a' && m_name <= 'z') {
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;
}
Expression * Symbol::replaceSymbolWithExpression(char symbol, Expression * expression) {
if (m_name == symbol) {
Expression * value = expression->clone();

View File

@@ -77,3 +77,28 @@ QUIZ_CASE(poincare_characteristic_range) {
assert_parsed_expression_has_characteristic_range("log(cos(40*x))", 9.0f);
assert_parsed_expression_has_characteristic_range("cos(cos(x))", 360.0f);
}
void assert_parsed_expression_has_variables(const char * expression, const char * variables) {
Expression * e = parse_expression(expression);
char variableBuffer[Expression::k_maxNumberOfVariables+1] = {0};
int numberOfVariables = e->getVariables(variableBuffer);
if (variables == nullptr) {
assert(numberOfVariables == -1);
} else {
assert(numberOfVariables == strlen(variables));
char * currentChar = variableBuffer;
while (*variables != 0) {
assert(*currentChar++ == *variables++);
}
}
delete e;
}
QUIZ_CASE(poincare_get_variables) {
assert_parsed_expression_has_variables("x+y", "xy");
assert_parsed_expression_has_variables("x+y+z+2*t", "xyzt");
assert_parsed_expression_has_variables("abcdef", "abcdef");
assert_parsed_expression_has_variables("abcdefg", nullptr);
assert_parsed_expression_has_variables("abcde", "abcde");
assert_parsed_expression_has_variables("x^2+2*y+k!*A+w", "xykw");
}