From 3ccd7417bb7dd52173278853a5a7c2bfebaeda41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Jan 2017 13:34:38 +0100 Subject: [PATCH] [poincare] Create a class opposite Change-Id: Ib903a31d7ba76cd76b95464f701ea2605ff7392d --- poincare/Makefile | 1 + poincare/include/poincare.h | 1 + poincare/include/poincare/expression.h | 1 + poincare/include/poincare/opposite.h | 26 +++++++++ poincare/src/expression_parser.y | 5 +- poincare/src/opposite.cpp | 80 ++++++++++++++++++++++++++ 6 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 poincare/include/poincare/opposite.h create mode 100644 poincare/src/opposite.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 20436b40b..964bd4a95 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -23,6 +23,7 @@ objs += $(addprefix poincare/src/,\ matrix.o\ matrix_data.o\ nth_root.o\ + opposite.o\ parenthesis.o\ power.o\ product.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 8074a4bba..64961d0d7 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index d2f5872c5..ae9043ad8 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -19,6 +19,7 @@ class Expression { Logarithm, Matrix, NthRoot, + Opposite, Fraction, Parenthesis, Power, diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h new file mode 100644 index 000000000..e17796cec --- /dev/null +++ b/poincare/include/poincare/opposite.h @@ -0,0 +1,26 @@ +#ifndef POINCARE_OPPOSITE_H +#define POINCARE_OPPOSITE_H + +#include +#include +#include + +class Opposite : public Expression { + public: + Opposite(Expression * operand, bool cloneOperands = true); + ~Opposite(); + const Expression * operand(int i) const override; + int numberOfOperands() const override; + Expression * clone() const override; + Expression * evaluate(Context& context) const override; + ExpressionLayout * createLayout() const override; + float approximate(Context& context) const override; + Type type() const override; + Expression * cloneWithDifferentOperands(Expression** newOperands, + int numnerOfOperands, bool cloneOperands = true) const override; + protected: + Expression * m_operand; + Expression * evaluateOnMatrix(Matrix * m, Context& context) const; +}; + +#endif diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index d663cc4a9..26ac384fb 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -112,13 +112,9 @@ mtxData: number: DIGITS { $$ = new Integer($1.address, false); } - | MINUS DIGITS { $$ = new Integer($2.address, true); } | DIGITS DOT DIGITS { $$ = new Float($1.address, $1.length, false, $3.address, $3.length, nullptr, 0, false); } - | MINUS DIGITS DOT DIGITS { $$ = new Float($2.address, $2.length, true, $4.address, $4.length, nullptr, 0, false); } | DIGITS DOT DIGITS EE DIGITS { $$ = new Float($1.address, $1.length, false, $3.address, $3.length, $5.address, $5.length, false); } - | MINUS DIGITS DOT DIGITS EE DIGITS { $$ = new Float($2.address, $2.length, true, $4.address, $4.length, $6.address, $6.length, false); } | DIGITS DOT DIGITS EE MINUS DIGITS { $$ = new Float($1.address, $1.length, false, $3.address, $3.length, $6.address, $6.length, true); } - | MINUS DIGITS DOT DIGITS EE MINUS DIGITS { $$ = new Float($2.address, $2.length, true, $4.address, $4.length, $7.address, $7.length, true); } exp: number { $$ = $1; } @@ -128,6 +124,7 @@ exp: | exp MULTIPLY exp { Expression * terms[2] = {$1,$3}; $$ = new Product(terms, false); } | exp DIVIDE exp { Expression * terms[2] = {$1,$3}; $$ = new Fraction(terms, false); } | exp POW exp { Expression * terms[2] = {$1,$3}; $$ = new Power(terms, false); } + | MINUS exp { $$ = new Opposite($2, false); } | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Parenthesis($2, false); } | LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Matrix($2); } | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; $1->setArgument($3, false);} diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp new file mode 100644 index 000000000..2a090ebc1 --- /dev/null +++ b/poincare/src/opposite.cpp @@ -0,0 +1,80 @@ +#include +extern "C" { +#include +#include +} +#include "layout/horizontal_layout.h" +#include "layout/string_layout.h" + +Opposite::Opposite(Expression * operand, bool cloneOperands) { + assert(operand != nullptr); + if (cloneOperands) { + m_operand = operand->clone(); + } else { + m_operand = operand; + } +} + +Opposite::~Opposite() { + delete m_operand; +} + +const Expression * Opposite::operand(int i) const { + assert(i == 0); + return m_operand; +} + +int Opposite::numberOfOperands() const { + return 1; +} + +Expression * Opposite::clone() const { + return this->cloneWithDifferentOperands((Expression**)&m_operand, 1, true); +} + +Expression * Opposite::evaluate(Context& context) const { + Expression * operandEvalutation = m_operand->evaluate(context); + if (operandEvalutation == nullptr) { + return nullptr; + } + Expression * result = nullptr; + if (operandEvalutation->type() == Type::Float) { + result = new Float(this->approximate(context)); + } + if (operandEvalutation->type() == Type::Matrix) { + result = evaluateOnMatrix((Matrix *)operandEvalutation, context); + } + delete operandEvalutation; + return result; +} + +ExpressionLayout * Opposite::createLayout() const { + ExpressionLayout** children_layouts = (ExpressionLayout **)malloc(2*sizeof(ExpressionLayout *)); + char string[2] = {'-', '\0'}; + children_layouts[0] = new StringLayout(string, 1); + children_layouts[1] = m_operand->createLayout(); + return new HorizontalLayout(children_layouts, 2); +} + +float Opposite::approximate(Context& context) const { + return -m_operand->approximate(context); +} + +Expression::Type Opposite::type() const { + return Expression::Type::Opposite; +} + +Expression * Opposite::cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands) const { + assert(newOperands != nullptr); + assert(numberOfOperands == 1); + return new Opposite(newOperands[0], cloneOperands); +} + +Expression * Opposite::evaluateOnMatrix(Matrix * m, Context& context) const { + Expression * operands[m->numberOfRows() * m->numberOfColumns()]; + for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) { + operands[i] = new Float(- m->operand(i)->approximate(context)); + } + return new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false); +}