[poincare] Make addition a binary operation

Change-Id: I70df98ca8e84b3653b9e41f257deeb613a078de0
This commit is contained in:
Émilie Feral
2017-02-02 10:33:05 +01:00
parent d59d31a6d8
commit 02d30fdcd5
4 changed files with 23 additions and 112 deletions

View File

@@ -1,31 +1,23 @@
#ifndef POINCARE_ADDITION_H
#define POINCARE_ADDITION_H
#include <poincare/expression.h>
#include <poincare/binary_operation.h>
#include <poincare/float.h>
#include <poincare/matrix.h>
class Addition : public Expression {
class Addition : public BinaryOperation {
using BinaryOperation::BinaryOperation;
public:
Addition(Expression ** operands, int numberOfOperands, bool cloneOperands = true);
~Addition();
const Expression * operand(int i) const override;
int numberOfOperands() const override;
Type type() const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Expression * clone() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
ExpressionLayout * createLayout(DisplayMode displayMode = DisplayMode::Auto) const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numnerOfOperands, bool cloneOperands = true) const override;
bool isCommutative() const override;
private:
float operateApproximatevelyOn(float a, float b) const;
Expression * evaluateOn(Expression * a, Expression * b, Context& context, AngleUnit angleUnit) const;
Expression * evaluateOnFloatAndMatrix(Float * a, Matrix * m, Context& context, AngleUnit angleUnit) const;
Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const;
const int m_numberOfOperands;
Expression ** m_operands;
Expression * evaluateOnMatrixAndFloat(Matrix * m, Float * f, Context& context, AngleUnit angleUnit) const override;
Expression * evaluateOnFloatAndMatrix(Float * f, Matrix * m, Context& context, AngleUnit angleUnit) const override;
Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const override;
};
#endif

View File

@@ -1,5 +1,4 @@
#include <poincare/addition.h>
#include <poincare/expression.h>
extern "C" {
#include <assert.h>
#include <stdlib.h>
@@ -8,113 +7,33 @@ extern "C" {
#include "layout/string_layout.h"
#include "layout/parenthesis_layout.h"
Addition::Addition(Expression ** operands,
int numberOfOperands,
bool cloneOperands) : m_numberOfOperands(numberOfOperands) {
assert(operands != nullptr);
assert(numberOfOperands >= 2);
m_operands = (Expression **)malloc(numberOfOperands*sizeof(Expression *));
for (int i=0; i<numberOfOperands; i++) {
assert(operands[i] != nullptr);
if (cloneOperands) {
m_operands[i] = operands[i]->clone();
} else {
m_operands[i] = operands[i];
}
}
}
Addition::~Addition() {
for (int i=0; i<m_numberOfOperands; i++) {
delete m_operands[i];
}
free(m_operands);
}
int Addition::numberOfOperands() const {
return m_numberOfOperands;
}
const Expression * Addition::operand(int i) const {
assert(i >= 0);
assert(i < m_numberOfOperands);
return m_operands[i];
}
Expression::Type Addition::type() const {
return Type::Addition;
}
ExpressionLayout * Addition::createLayout(DisplayMode displayMode) const {
ExpressionLayout** children_layouts = (ExpressionLayout **)malloc(3*sizeof(ExpressionLayout *));
children_layouts[0] = m_operands[0]->createLayout(displayMode);
children_layouts[1] = new StringLayout("+", 1);
children_layouts[2] = m_operands[1]->type() == Type::Opposite ? new ParenthesisLayout(m_operands[1]->createLayout(displayMode)) : m_operands[1]->createLayout(displayMode);
return new HorizontalLayout(children_layouts, 3);
}
float Addition::approximate(Context& context, AngleUnit angleUnit) const {
float result = m_operands[0]->approximate(context, angleUnit);
for (int i=1; i<m_numberOfOperands; i++) {
float next = m_operands[i]->approximate(context, angleUnit);
result = this->operateApproximatevelyOn(result, next);
}
return result;
}
Expression * Addition::evaluate(Context& context, AngleUnit angleUnit) const {
Expression * result = m_operands[0]->evaluate(context, angleUnit);
for (int i=1; i<m_numberOfOperands; i++) {
Expression * next = m_operands[i]->evaluate(context, angleUnit);
Expression * newResult = this->evaluateOn(result, next, context, angleUnit);
delete result;
result = newResult;
delete next;
}
assert(result == nullptr || result->type() == Type::Float || result->type() == Type::Matrix);
return result;
}
Expression * Addition::clone() const {
return this->cloneWithDifferentOperands(m_operands, m_numberOfOperands, true);
return m_operands[0]->approximate(context, angleUnit)+m_operands[1]->approximate(context, angleUnit);;
}
Expression * Addition::cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands) const {
return new Addition(newOperands, numberOfOperands, cloneOperands);
}
ExpressionLayout * Addition::createLayout(DisplayMode displayMode) const {
int number_of_children = 2*m_numberOfOperands-1;
ExpressionLayout** children_layouts = (ExpressionLayout **)malloc(number_of_children*sizeof(ExpressionLayout *));
children_layouts[0] = m_operands[0]->createLayout(displayMode);
for (int i=1; i<m_numberOfOperands; i++) {
children_layouts[2*i-1] = new StringLayout("+", 1);
children_layouts[2*i] = m_operands[i]->type() == Type::Opposite ? new ParenthesisLayout(m_operands[i]->createLayout(displayMode)) : m_operands[i]->createLayout(displayMode);
}
return new HorizontalLayout(children_layouts, number_of_children);
return new Addition(newOperands, cloneOperands);
}
bool Addition::isCommutative() const {
return true;
}
float Addition::operateApproximatevelyOn(float a, float b) const {
return a + b;
}
Expression * Addition::evaluateOn(Expression * a, Expression * b, Context& context, AngleUnit angleUnit) const {
if (a == nullptr || b == nullptr) {
return nullptr;
}
assert(a->type() == Type::Float || a->type() == Type::Matrix);
assert(b->type() == Type::Float || b->type() == Type::Matrix);
Expression * result = nullptr;
if (a->type() == Type::Float && b->type() == Type::Float) {
result = new Float(a->approximate(context, angleUnit) + b->approximate(context, angleUnit));
}
if (a->type() == Type::Float && b->type() == Type::Matrix) {
result = evaluateOnFloatAndMatrix((Float *)a, (Matrix *)b, context, angleUnit);
}
if (b->type() == Type::Float && a->type() == Type::Matrix) {
result = evaluateOnFloatAndMatrix((Float *)b, (Matrix *)a, context, angleUnit);
}
if (b->type() == Type::Matrix && a->type() == Type::Matrix) {
result = evaluateOnMatrices((Matrix *)a, (Matrix *)b, context, angleUnit);
}
return result;
Expression * Addition::evaluateOnMatrixAndFloat(Matrix * m, Float * f, Context& context, AngleUnit angleUnit) const {
return evaluateOnFloatAndMatrix(f, m, context, angleUnit);
}
Expression * Addition::evaluateOnFloatAndMatrix(Float * a, Matrix * m, Context& context, AngleUnit angleUnit) const {

View File

@@ -119,7 +119,7 @@ number:
exp:
number { $$ = $1; }
| SYMBOL { $$ = new Symbol($1); }
| exp PLUS exp { Expression * terms[2] = {$1,$3}; $$ = new Addition(terms, 2, false); }
| exp PLUS exp { Expression * terms[2] = {$1,$3}; $$ = new Addition(terms, false); }
| exp MINUS exp { Expression * terms[2] = {$1,$3}; $$ = new Subtraction(terms, false); }
| exp MULTIPLY exp { Expression * terms[2] = {$1,$3}; $$ = new Multiplication(terms, false); }
| exp DIVIDE exp { Expression * terms[2] = {$1,$3}; $$ = new Fraction(terms, false); }

View File

@@ -34,7 +34,7 @@ Expression * ExpressionBuilder::build(ExpressionMatch matches[]) {
case Expression::Type::Addition:
/* The children do not need to be cloned as they already have been
* before. */
result = new Addition(children_expressions, numberOfChildrenExpressions, false);
result = new Addition(children_expressions, false);
break;
case Expression::Type::Multiplication:
/* The children do not need to be cloned as they already have been