[poincare] Create a class opposite

Change-Id: Ib903a31d7ba76cd76b95464f701ea2605ff7392d
This commit is contained in:
Émilie Feral
2017-01-13 13:34:38 +01:00
parent 6319d08fc9
commit 3ccd7417bb
6 changed files with 110 additions and 4 deletions

View File

@@ -23,6 +23,7 @@ objs += $(addprefix poincare/src/,\
matrix.o\
matrix_data.o\
nth_root.o\
opposite.o\
parenthesis.o\
power.o\
product.o\

View File

@@ -18,6 +18,7 @@
#include <poincare/matrix.h>
#include <poincare/matrix_data.h>
#include <poincare/nth_root.h>
#include <poincare/opposite.h>
#include <poincare/parenthesis.h>
#include <poincare/power.h>
#include <poincare/product.h>

View File

@@ -19,6 +19,7 @@ class Expression {
Logarithm,
Matrix,
NthRoot,
Opposite,
Fraction,
Parenthesis,
Power,

View File

@@ -0,0 +1,26 @@
#ifndef POINCARE_OPPOSITE_H
#define POINCARE_OPPOSITE_H
#include <poincare/expression.h>
#include <poincare/matrix.h>
#include <poincare/float.h>
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

View File

@@ -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);}

80
poincare/src/opposite.cpp Normal file
View File

@@ -0,0 +1,80 @@
#include <poincare/opposite.h>
extern "C" {
#include <assert.h>
#include <stdlib.h>
}
#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);
}