mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-24 16:20:49 +01:00
[poincare] Make addition a binary operation
Change-Id: I70df98ca8e84b3653b9e41f257deeb613a078de0
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user