From 112bf400f6e90f492d98818eaa3946806da3b6c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 9 Mar 2017 11:22:28 +0100 Subject: [PATCH 1/2] [poincare] Parse arithmetic functions (gcd, lcm, rem, quo) Change-Id: Ia557927c149760cc0e23488094f8021a39a8b3d7 --- apps/math_toolbox.cpp | 2 +- poincare/Makefile | 4 ++ poincare/include/poincare.h | 4 ++ poincare/include/poincare/division_quotient.h | 21 ++++++++ .../include/poincare/division_remainder.h | 21 ++++++++ poincare/include/poincare/expression.h | 4 ++ .../include/poincare/great_common_divisor.h | 21 ++++++++ .../include/poincare/least_common_multiple.h | 21 ++++++++ poincare/src/division_quotient.cpp | 39 ++++++++++++++ poincare/src/division_remainder.cpp | 39 ++++++++++++++ poincare/src/expression_lexer.l | 4 ++ poincare/src/great_common_divisor.cpp | 52 ++++++++++++++++++ poincare/src/least_common_multiple.cpp | 53 +++++++++++++++++++ 13 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 poincare/include/poincare/division_quotient.h create mode 100644 poincare/include/poincare/division_remainder.h create mode 100644 poincare/include/poincare/great_common_divisor.h create mode 100644 poincare/include/poincare/least_common_multiple.h create mode 100644 poincare/src/division_quotient.cpp create mode 100644 poincare/src/division_remainder.cpp create mode 100644 poincare/src/great_common_divisor.cpp create mode 100644 poincare/src/least_common_multiple.cpp diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 6b23bd5bb..49a909309 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -10,7 +10,7 @@ const ToolboxNode calculChildren[4] = {ToolboxNode("diff(,)", "Nombre derive"), ToolboxNode("int(,,)", "Integrale"), ToolboxNode("sum(,,)", "Somme"), ToolboxNode("product(,,)", "Produit")}; const ToolboxNode complexChildren[5] = {ToolboxNode("abs()", "Module"), ToolboxNode("arg()", "Argument"), ToolboxNode("re()", "Partie reelle"), ToolboxNode("im()", "Partie imaginaire"), ToolboxNode("conj()", "Conjugue")}; const ToolboxNode probabilityChildren[2] = {ToolboxNode("binomial(,)", "Combinaison"), ToolboxNode("permute(,)", "Arrangement")}; -const ToolboxNode arithmeticChildren[4] = {ToolboxNode("gcd()", "PGCD"), ToolboxNode("lcm()", "PPCM"), ToolboxNode("rem()", "Reste division euclidienne"), ToolboxNode("quo()","Quotien division euclidienne")}; +const ToolboxNode arithmeticChildren[4] = {ToolboxNode("gcd(,)", "PGCD"), ToolboxNode("lcm(,)", "PPCM"), ToolboxNode("rem(,)", "Reste division euclidienne"), ToolboxNode("quo(,)","Quotien division euclidienne")}; const ToolboxNode matricesChildren[5] = {ToolboxNode("inverse()", "Inverse"), ToolboxNode("det()", "Determinant"), ToolboxNode("transpose()", "Transposee"), ToolboxNode("trace()", "Trace"), ToolboxNode("dim()", "Taille")}; const ToolboxNode listesChildren[5] = {ToolboxNode("sort<()", "Tri croissant"), ToolboxNode("sort>()", "Tri decroissant"), ToolboxNode("max()", "Maximum"), ToolboxNode("min()", "Minimum"), ToolboxNode("dim()", "Taille")}; const ToolboxNode approximationChildren[4] = {ToolboxNode("floor()", "Partie entiere"), ToolboxNode("frac()", "Partie fractionnaire"), ToolboxNode("ceil()", "Plafond"), ToolboxNode("round(,)", "Arrondi")}; diff --git a/poincare/Makefile b/poincare/Makefile index 350a9caed..83e493a8e 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -13,12 +13,15 @@ objs += $(addprefix poincare/src/,\ cosine.o\ derivative.o\ determinant.o\ + division_quotient.o\ + division_remainder.o\ expression.o\ expression_lexer.o\ expression_parser.o\ fraction.o\ function.o\ global_context.o\ + great_common_divisor.o\ hyperbolic_cosine.o\ hyperbolic_sine.o\ hyperbolic_tangent.o\ @@ -27,6 +30,7 @@ objs += $(addprefix poincare/src/,\ integral.o\ list_data.o\ leaf_expression.o\ + least_common_multiple.o\ logarithm.o\ matrix.o\ matrix_data.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index dbf11fcb5..32ad7129a 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -11,10 +11,13 @@ #include #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -22,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h new file mode 100644 index 000000000..7892ae39b --- /dev/null +++ b/poincare/include/poincare/division_quotient.h @@ -0,0 +1,21 @@ +#ifndef POINCARE_DIVISION_QUOTIENT_H +#define POINCARE_DIVISION_QUOTIENT_H + +#include + +namespace Poincare { + +class DivisionQuotient : public Function { +public: + DivisionQuotient(); + Type type() const override; + Expression * cloneWithDifferentOperands(Expression ** newOperands, + int numberOfOperands, bool cloneOperands = true) const override; +private: + float privateApproximate(Context & context, AngleUnit angleUnit) const override; +}; + +} + +#endif + diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h new file mode 100644 index 000000000..651f75cdd --- /dev/null +++ b/poincare/include/poincare/division_remainder.h @@ -0,0 +1,21 @@ +#ifndef POINCARE_DIVISION_REMAINDER_H +#define POINCARE_DIVISION_REMAINDER_H + +#include + +namespace Poincare { + +class DivisionRemainder : public Function { +public: + DivisionRemainder(); + Type type() const override; + Expression * cloneWithDifferentOperands(Expression ** newOperands, + int numberOfOperands, bool cloneOperands = true) const override; +private: + float privateApproximate(Context & context, AngleUnit angleUnit) const override; +}; + +} + +#endif + diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index c6ba69510..2e3ff4565 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -20,7 +20,10 @@ public: Cosine, Derivative, Determinant, + DivisionQuotient, + DivisionRemainder, Float, + GreatCommonDivisor, HyperbolicCosine, HyperbolicSine, HyperbolicTangent, @@ -28,6 +31,7 @@ public: Integer, Integral, Logarithm, + LeastCommonMultiple, Matrix, MatrixInverse, Multiplication, diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h new file mode 100644 index 000000000..99ff761d0 --- /dev/null +++ b/poincare/include/poincare/great_common_divisor.h @@ -0,0 +1,21 @@ +#ifndef POINCARE_GREAT_COMMON_DIVISOR_H +#define POINCARE_GREAT_COMMON_DIVISOR_H + +#include + +namespace Poincare { + +class GreatCommonDivisor : public Function { +public: + GreatCommonDivisor(); + Type type() const override; + Expression * cloneWithDifferentOperands(Expression ** newOperands, + int numberOfOperands, bool cloneOperands = true) const override; +private: + float privateApproximate(Context & context, AngleUnit angleUnit) const override; +}; + +} + +#endif + diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h new file mode 100644 index 000000000..8ee3bfdf8 --- /dev/null +++ b/poincare/include/poincare/least_common_multiple.h @@ -0,0 +1,21 @@ +#ifndef POINCARE_LEAST_COMMON_MULTIPLE_H +#define POINCARE_LEAST_COMMON_MULTIPLE_H + +#include + +namespace Poincare { + +class LeastCommonMultiple : public Function { +public: + LeastCommonMultiple(); + Type type() const override; + Expression * cloneWithDifferentOperands(Expression ** newOperands, + int numberOfOperands, bool cloneOperands = true) const override; +private: + float privateApproximate(Context & context, AngleUnit angleUnit) const override; +}; + +} + +#endif + diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp new file mode 100644 index 000000000..21ac1e501 --- /dev/null +++ b/poincare/src/division_quotient.cpp @@ -0,0 +1,39 @@ +#include + +extern "C" { +#include +#include +} + +namespace Poincare { + +DivisionQuotient::DivisionQuotient() : + Function("quo") +{ +} + +Expression::Type DivisionQuotient::type() const { + return Type::DivisionQuotient; +} + +Expression * DivisionQuotient::cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands) const { + assert(numberOfOperands == 1); + assert(newOperands != nullptr); + DivisionQuotient * dq = new DivisionQuotient(); + dq->setArgument(newOperands, numberOfOperands, cloneOperands); + return dq; +} + +float DivisionQuotient::privateApproximate(Context& context, AngleUnit angleUnit) const { + assert(angleUnit != AngleUnit::Default); + float f1 = m_args[0]->approximate(context, angleUnit); + float f2 = m_args[1]->approximate(context, angleUnit); + if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { + return NAN; + } + return floorf(f1/f2); +} + +} + diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp new file mode 100644 index 000000000..f495affc7 --- /dev/null +++ b/poincare/src/division_remainder.cpp @@ -0,0 +1,39 @@ +#include + +extern "C" { +#include +#include +} + +namespace Poincare { + +DivisionRemainder::DivisionRemainder() : + Function("rem") +{ +} + +Expression::Type DivisionRemainder::type() const { + return Type::DivisionRemainder; +} + +Expression * DivisionRemainder::cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands) const { + assert(numberOfOperands == 1); + assert(newOperands != nullptr); + DivisionRemainder * dr = new DivisionRemainder(); + dr->setArgument(newOperands, numberOfOperands, cloneOperands); + return dr; +} + +float DivisionRemainder::privateApproximate(Context& context, AngleUnit angleUnit) const { + assert(angleUnit != AngleUnit::Default); + float f1 = m_args[0]->approximate(context, angleUnit); + float f2 = m_args[1]->approximate(context, angleUnit); + if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { + return NAN; + } + return roundf(f1-f2*floorf(f1/f2)); +} + +} + diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index c2a402517..1658bf97c 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -98,14 +98,18 @@ det { poincare_expression_yylval.expression = new Determinant(); return FUNCTION conj { poincare_expression_yylval.expression = new Conjugate(); return FUNCTION; } cos { poincare_expression_yylval.expression = new Cosine(); return FUNCTION; } cosh { poincare_expression_yylval.expression = new HyperbolicCosine(); return FUNCTION; } +gcd { poincare_expression_yylval.expression = new GreatCommonDivisor(); return FUNCTION; } im { poincare_expression_yylval.expression = new ImaginaryPart(); return FUNCTION; } int { poincare_expression_yylval.expression = new Integral(); return FUNCTION; } inverse { poincare_expression_yylval.expression = new MatrixInverse(); return FUNCTION; } +lcm { poincare_expression_yylval.expression = new LeastCommonMultiple(); return FUNCTION; } ln { poincare_expression_yylval.expression = new NaperianLogarithm(); return FUNCTION; } log { poincare_expression_yylval.expression = new Logarithm(); return FUNCTION; } permute { poincare_expression_yylval.expression = new PermuteCoefficient(); return FUNCTION; } product { poincare_expression_yylval.expression = new Product(); return FUNCTION; } +quo { poincare_expression_yylval.expression = new DivisionQuotient(); return FUNCTION; } re { poincare_expression_yylval.expression = new ReelPart(); return FUNCTION; } +rem { poincare_expression_yylval.expression = new DivisionRemainder(); return FUNCTION; } root { poincare_expression_yylval.expression = new NthRoot(); return FUNCTION; } sin { poincare_expression_yylval.expression = new Sine(); return FUNCTION; } sinh { poincare_expression_yylval.expression = new HyperbolicSine(); return FUNCTION; } diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp new file mode 100644 index 000000000..874e62fe7 --- /dev/null +++ b/poincare/src/great_common_divisor.cpp @@ -0,0 +1,52 @@ +#include +#include + +extern "C" { +#include +#include +} + +namespace Poincare { + +GreatCommonDivisor::GreatCommonDivisor() : + Function("gcd") +{ +} + +Expression::Type GreatCommonDivisor::type() const { + return Type::GreatCommonDivisor; +} + +Expression * GreatCommonDivisor::cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands) const { + assert(numberOfOperands == 1); + assert(newOperands != nullptr); + GreatCommonDivisor * gcd = new GreatCommonDivisor(); + gcd->setArgument(newOperands, numberOfOperands, cloneOperands); + return gcd; +} + +float GreatCommonDivisor::privateApproximate(Context& context, AngleUnit angleUnit) const { + assert(angleUnit != AngleUnit::Default); + float f1 = m_args[0]->approximate(context, angleUnit); + float f2 = m_args[1]->approximate(context, angleUnit); + if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { + return NAN; + } + int a = (int)f2; + int b = (int)f1; + if (f1 > f2) { + b = a; + a = (int)f1; + } + int r = 0; + while((int)b!=0){ + r = a - ((int)(a/b))*b; + a = b; + b = r; + } + return roundf((float)a); +} + +} + diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp new file mode 100644 index 000000000..c284660a2 --- /dev/null +++ b/poincare/src/least_common_multiple.cpp @@ -0,0 +1,53 @@ +#include +#include + +extern "C" { +#include +#include +} + +namespace Poincare { + +LeastCommonMultiple::LeastCommonMultiple() : + Function("lcm") +{ +} + +Expression::Type LeastCommonMultiple::type() const { + return Type::LeastCommonMultiple; +} + +Expression * LeastCommonMultiple::cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands) const { + assert(numberOfOperands == 1); + assert(newOperands != nullptr); + LeastCommonMultiple * lcm = new LeastCommonMultiple(); + lcm->setArgument(newOperands, numberOfOperands, cloneOperands); + return lcm; +} + +float LeastCommonMultiple::privateApproximate(Context& context, AngleUnit angleUnit) const { + assert(angleUnit != AngleUnit::Default); + float f1 = m_args[0]->approximate(context, angleUnit); + float f2 = m_args[1]->approximate(context, angleUnit); + if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { + return NAN; + } + int a = (int)f2; + int b = (int)f1; + if (f1 > f2) { + b = a; + a = (int)f1; + } + int product = a*b; + int r = 0; + while((int)b!=0){ + r = a - ((int)(a/b))*b; + a = b; + b = r; + } + return roundf((float)(product/a)); +} + +} + From 6da1fb2ae8f66ec08d89679d9de09a8fb9b3995f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 9 Mar 2017 14:16:26 +0100 Subject: [PATCH 2/2] [poincare] Fix memory leak Change-Id: I10f860eeb2fa4a7a1c6e358b208cc33f7d5d9d75 --- apps/sequence/graph/term_sum_controller.cpp | 2 +- poincare/include/poincare/matrix.h | 3 ++- poincare/include/poincare/matrix_data.h | 4 +-- poincare/src/addition.cpp | 4 ++- poincare/src/binary_operation.cpp | 13 ++++++--- poincare/src/binomial_coefficient.cpp | 2 +- poincare/src/expression_parser.y | 6 ++--- poincare/src/function.cpp | 3 ++- poincare/src/integral.cpp | 2 +- poincare/src/layout/grid_layout.cpp | 3 ++- poincare/src/layout/horizontal_layout.cpp | 4 ++- poincare/src/logarithm.cpp | 2 +- poincare/src/matrix.cpp | 30 ++++++++++++++++----- poincare/src/matrix_data.cpp | 16 ++++++++--- poincare/src/matrix_inverse.cpp | 2 +- poincare/src/multiplication.cpp | 8 +++--- poincare/src/opposite.cpp | 8 +++--- poincare/src/product.cpp | 2 +- poincare/src/subtraction.cpp | 2 +- poincare/src/sum.cpp | 2 +- 20 files changed, 80 insertions(+), 38 deletions(-) diff --git a/apps/sequence/graph/term_sum_controller.cpp b/apps/sequence/graph/term_sum_controller.cpp index 6e1e0770a..2c03ee42a 100644 --- a/apps/sequence/graph/term_sum_controller.cpp +++ b/apps/sequence/graph/term_sum_controller.cpp @@ -227,7 +227,7 @@ void TermSumController::ContentView::LegendView::setSumSuperscript(float start, } void TermSumController::ContentView::LegendView::setSequenceName(const char * sequenceName) { - ExpressionLayout ** childrenLayouts = (ExpressionLayout **)malloc(2*sizeof(ExpressionLayout *)); + ExpressionLayout * childrenLayouts[2]; childrenLayouts[1] = new BaselineRelativeLayout(new StringLayout(sequenceName, 1, KDText::FontSize::Small), new StringLayout("n", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); childrenLayouts[0] = m_sumLayout; m_sumLayout = new HorizontalLayout(childrenLayouts, 2); diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index 54e15a0b2..b71b4b4c0 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -24,7 +24,8 @@ public: * buffer size */ int writeTextInBuffer(char * buffer, int bufferSize) override; float determinant(Context& context, AngleUnit angleUnit) const; - Expression * inverse(Context& context, AngleUnit angleUnit) const; + Expression * createInverse(Context& context, AngleUnit angleUnit) const; + Expression * createTranspose(Context& context, AngleUnit angleUnit) const; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; float privateApproximate(Context& context, AngleUnit angleUnit) const override; diff --git a/poincare/include/poincare/matrix_data.h b/poincare/include/poincare/matrix_data.h index 8aa14dae5..928ad57af 100644 --- a/poincare/include/poincare/matrix_data.h +++ b/poincare/include/poincare/matrix_data.h @@ -9,10 +9,10 @@ namespace Poincare { class MatrixData { public: - MatrixData(ListData * listData); + MatrixData(ListData * listData, bool clone); MatrixData(Expression ** newOperands, int numberOfOperands, int m_numberOfColumns, int m_numberOfRows, bool cloneOperands); ~MatrixData(); - void pushListData(ListData * listData); + void pushListData(ListData * listData, bool clone); int numberOfRows(); int numberOfColumns(); Expression ** operands() const; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 1a7e2eb8d..ceaad643b 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -20,7 +20,9 @@ ExpressionLayout * Addition::privateCreateLayout(FloatDisplayMode floatDisplayMo children_layouts[0] = m_operands[0]->createLayout(floatDisplayMode, complexFormat); children_layouts[1] = new StringLayout("+", 1); children_layouts[2] = m_operands[1]->type() == Type::Opposite ? new ParenthesisLayout(m_operands[1]->createLayout(floatDisplayMode, complexFormat)) : m_operands[1]->createLayout(floatDisplayMode, complexFormat); - return new HorizontalLayout(children_layouts, 3); + ExpressionLayout * layout = new HorizontalLayout(children_layouts, 3); + free(children_layouts); + return layout; } float Addition::privateApproximate(Context& context, AngleUnit angleUnit) const { diff --git a/poincare/src/binary_operation.cpp b/poincare/src/binary_operation.cpp index 2b257f1ff..664003187 100644 --- a/poincare/src/binary_operation.cpp +++ b/poincare/src/binary_operation.cpp @@ -2,6 +2,7 @@ extern "C" { #include #include +#include } namespace Poincare { @@ -64,7 +65,7 @@ Expression * BinaryOperation::privateEvaluate(Context& context, AngleUnit angleU } Expression * BinaryOperation::evaluateOnMatrixAndComplex(Matrix * m, Complex * c, Context& context, AngleUnit angleUnit) const { - Expression * operands[m->numberOfRows() * m->numberOfColumns()]; + Expression ** operands = (Expression **)malloc(m->numberOfRows() * m->numberOfColumns()*sizeof(Expression *)); for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) { Expression * evaluation = m->operand(i)->evaluate(context, angleUnit); assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); @@ -76,7 +77,9 @@ Expression * BinaryOperation::evaluateOnMatrixAndComplex(Matrix * m, Complex * c operands[i] = evaluateOnComplex((Complex *)evaluation, c, context, angleUnit); delete evaluation; } - return new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false); + Expression * result = new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false); + free(operands); + return result; } Expression * BinaryOperation::evaluateOnComplexAndMatrix(Complex * c, Matrix * m, Context& context, AngleUnit angleUnit) const { @@ -87,7 +90,7 @@ Expression * BinaryOperation::evaluateOnMatrices(Matrix * m, Matrix * n, Context if (m->numberOfColumns() != n->numberOfColumns() || m->numberOfRows() != n->numberOfRows()) { return nullptr; } - Expression * operands[m->numberOfRows() * m->numberOfColumns()]; + Expression ** operands = (Expression **)malloc(m->numberOfRows() * m->numberOfColumns()*sizeof(Expression *)); for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) { Expression * mEvaluation = m->operand(i)->evaluate(context, angleUnit); Expression * nEvaluation = n->operand(i)->evaluate(context, angleUnit); @@ -103,7 +106,9 @@ Expression * BinaryOperation::evaluateOnMatrices(Matrix * m, Matrix * n, Context delete mEvaluation; delete nEvaluation; } - return new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false); + Expression * result = new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false); + free(operands); + return result; } } diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 35e51bb00..cca96d75e 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -46,7 +46,7 @@ float BinomialCoefficient::privateApproximate(Context& context, AngleUnit angleU ExpressionLayout * BinomialCoefficient::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout ** childrenLayouts = (ExpressionLayout **)malloc(2*sizeof(ExpressionLayout *)); + ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = m_args[0]->createLayout(floatDisplayMode, complexFormat); childrenLayouts[1] = m_args[1]->createLayout(floatDisplayMode, complexFormat); return new ParenthesisLayout(new GridLayout(childrenLayouts, 2, 1)); diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 0ca1d60d5..d595a1dd8 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -107,8 +107,8 @@ lstData: | lstData COMMA exp { $$ = $1; $$->pushExpression($3); } mtxData: - LEFT_BRACKET lstData RIGHT_BRACKET { $$ = new Poincare::MatrixData($2); } - | mtxData LEFT_BRACKET lstData RIGHT_BRACKET { $$ = $1; $$->pushListData($3); } + LEFT_BRACKET lstData RIGHT_BRACKET { $$ = new Poincare::MatrixData($2, true); delete $2; } + | mtxData LEFT_BRACKET lstData RIGHT_BRACKET { $$ = $1; $$->pushListData($3, true); delete $3; } number: DIGITS { $$ = new Poincare::Integer($1.address, false); } @@ -131,7 +131,7 @@ exp: | MINUS exp { $$ = new Poincare::Opposite($2, false); } | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Poincare::Parenthesis($2, false); } | LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Poincare::Matrix($2); } - | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; $1->setArgument($3, false);} + | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; $1->setArgument($3, true); delete $3; } ; %% diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index 66eede4e5..1f891f86a 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -78,7 +78,8 @@ ExpressionLayout * Function::privateCreateLayout(FloatDisplayMode floatDisplayMo grandChildrenLayouts[layoutIndex++] = m_args[i]->createLayout(floatDisplayMode, complexFormat); } ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*m_numberOfArguments-1); - ExpressionLayout ** childrenLayouts = (ExpressionLayout **)malloc(2*sizeof(ExpressionLayout *)); + free(grandChildrenLayouts); + ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = new StringLayout(m_name, strlen(m_name)); childrenLayouts[1] = new ParenthesisLayout(argumentLayouts); return new HorizontalLayout(childrenLayouts, 2); diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 831769a8a..a8d5db86d 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -50,7 +50,7 @@ float Integral::privateApproximate(Context& context, AngleUnit angleUnit) const ExpressionLayout * Integral::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout ** childrenLayouts = (ExpressionLayout **)malloc(2*sizeof(ExpressionLayout *)); + ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = m_args[0]->createLayout(floatDisplayMode, complexFormat); childrenLayouts[1] = new StringLayout("dx", 2); return new IntegralLayout(m_args[1]->createLayout(floatDisplayMode, complexFormat), m_args[2]->createLayout(floatDisplayMode, complexFormat), new HorizontalLayout(childrenLayouts, 2)); diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 7b4f34ddf..4564f613d 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -8,11 +8,12 @@ namespace Poincare { GridLayout::GridLayout(ExpressionLayout ** entryLayouts, int numberOfRows, int numberOfColumns) : ExpressionLayout(), - m_entryLayouts(entryLayouts), m_numberOfRows(numberOfRows), m_numberOfColumns(numberOfColumns) { + m_entryLayouts = (ExpressionLayout **)malloc(numberOfColumns*numberOfRows*sizeof(ExpressionLayout *)); for (int i = 0; i < m_numberOfRows*m_numberOfColumns; i++) { + m_entryLayouts[i] = entryLayouts[i]; m_entryLayouts[i]->setParent(this); } m_baseline = height()/2 + KDText::stringSize(" ").height()/2; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 90632eb05..8caa71655 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -9,9 +9,11 @@ extern "C" { namespace Poincare { HorizontalLayout::HorizontalLayout(ExpressionLayout ** children_layouts, int number_of_children) : - ExpressionLayout(), m_number_of_children(number_of_children), m_children_layouts(children_layouts) { + ExpressionLayout(), m_number_of_children(number_of_children) { assert(number_of_children > 0); + m_children_layouts = (ExpressionLayout **)malloc(number_of_children*sizeof(ExpressionLayout *)); for (int i=0; isetParent(this); if (m_children_layouts[i]->baseline() > m_baseline) { m_baseline = m_children_layouts[i]->baseline(); diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 665570f4e..b0c0e40a4 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -43,7 +43,7 @@ ExpressionLayout * Logarithm::privateCreateLayout(FloatDisplayMode floatDisplayM if (m_numberOfArguments == 1) { return Function::privateCreateLayout(floatDisplayMode, complexFormat); } - ExpressionLayout ** childrenLayouts = (ExpressionLayout **)malloc(2*sizeof(ExpressionLayout *)); + ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = new BaselineRelativeLayout(new StringLayout(m_name, strlen(m_name)), m_args[0]->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript); childrenLayouts[1] = new ParenthesisLayout(m_args[1]->createLayout(floatDisplayMode, complexFormat)); return new HorizontalLayout(childrenLayouts, 2); diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 9f359a6a9..acc7dfd44 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -52,7 +52,9 @@ ExpressionLayout * Matrix::privateCreateLayout(FloatDisplayMode floatDisplayMode for (int i = 0; i < numberOfOperands(); i++) { childrenLayouts[i] = operand(i)->createLayout(floatDisplayMode, complexFormat); } - return new BracketLayout(new GridLayout(childrenLayouts, numberOfRows(), numberOfColumns())); + ExpressionLayout * layout = new BracketLayout(new GridLayout(childrenLayouts, numberOfRows(), numberOfColumns())); + free(childrenLayouts); + return layout; } float Matrix::privateApproximate(Context& context, AngleUnit angleUnit) const { @@ -62,7 +64,7 @@ float Matrix::privateApproximate(Context& context, AngleUnit angleUnit) const { Expression * Matrix::privateEvaluate(Context& context, AngleUnit angleUnit) const { assert(angleUnit != AngleUnit::Default); - Expression * operands[numberOfOperands()]; + Expression ** operands = (Expression **)malloc(numberOfOperands()*sizeof(Expression *)); for (int i = 0; i < numberOfOperands(); i++) { operands[i] = operand(i)->evaluate(context, angleUnit); assert(operands[i]->type() == Type::Matrix || operands[i]->type() == Type::Complex); @@ -72,7 +74,9 @@ Expression * Matrix::privateEvaluate(Context& context, AngleUnit angleUnit) cons continue; } } - return new Matrix(new MatrixData(operands, numberOfOperands(), numberOfColumns(), numberOfRows(), false)); + Expression * matrix = new Matrix(new MatrixData(operands, numberOfOperands(), numberOfColumns(), numberOfRows(), false)); + free(operands); + return matrix; } Expression::Type Matrix::type() const { @@ -200,7 +204,7 @@ float Matrix::determinant(Context& context, AngleUnit angleUnit) const { return det; } -Expression * Matrix::inverse(Context& context, AngleUnit angleUnit) const { +Expression * Matrix::createInverse(Context& context, AngleUnit angleUnit) const { if (numberOfColumns() != numberOfRows()) { return nullptr; } @@ -259,7 +263,7 @@ Expression * Matrix::inverse(Context& context, AngleUnit angleUnit) const { } } } - Expression * operands[numberOfOperands()]; + Expression ** operands = (Expression **)malloc(numberOfOperands()*sizeof(Expression *)); for (int i = 0; i < numberOfRows(); i++) { for (int j = 0; j < numberOfColumns(); j++) { operands[i*dim+j] = new Complex(Complex::Float(inv[i][j+dim])); @@ -269,7 +273,21 @@ Expression * Matrix::inverse(Context& context, AngleUnit angleUnit) const { free(inv[i]); } free(inv); - return new Matrix(new MatrixData(operands, numberOfOperands(), numberOfColumns(), numberOfRows(), false)); + Expression * matrix = new Matrix(new MatrixData(operands, numberOfOperands(), numberOfColumns(), numberOfRows(), false)); + free(operands); + return matrix; +} + +Expression * Matrix::createTranspose(Context& context, AngleUnit angleUnit) const { + Expression ** operands = (Expression **)malloc(numberOfOperands()*sizeof(Expression *)); + for (int i = 0; i < numberOfRows(); i++) { + for (int j = 0; j < numberOfColumns(); j++) { + operands[j*numberOfRows()+i] = m_matrixData->operands()[i*numberOfColumns()+j]->clone(); + } + } + Expression * matrix = new Matrix(new MatrixData(operands, numberOfOperands(), numberOfRows(), numberOfColumns(), false)); + free(operands); + return matrix; } } diff --git a/poincare/src/matrix_data.cpp b/poincare/src/matrix_data.cpp index 8536e183a..49a89c001 100644 --- a/poincare/src/matrix_data.cpp +++ b/poincare/src/matrix_data.cpp @@ -7,7 +7,7 @@ extern "C" { namespace Poincare { -MatrixData::MatrixData(ListData * listData) : +MatrixData::MatrixData(ListData * listData, bool clone) : m_numberOfRows(1), m_numberOfColumns(0) { @@ -15,7 +15,11 @@ MatrixData::MatrixData(ListData * listData) : m_numberOfColumns = listData->numberOfOperands(); m_operands = (Expression **)malloc(m_numberOfColumns*sizeof(Expression *)); for (int i = 0; i < m_numberOfColumns; i++) { - m_operands[i] = (Expression *)listData->operand(i); + if (clone) { + m_operands[i] = (Expression *)listData->operand(i)->clone(); + } else { + m_operands[i] = (Expression *)listData->operand(i); + } } } @@ -49,14 +53,18 @@ MatrixData::~MatrixData() { free(m_operands); } -void MatrixData::pushListData(ListData * listData) { +void MatrixData::pushListData(ListData * listData, bool clone) { Expression ** newOperands = (Expression **)malloc(((m_numberOfRows+1)*m_numberOfColumns)*sizeof(Expression *)); for (int i = 0; i < m_numberOfRows*m_numberOfColumns; i++) { newOperands[i] = m_operands[i]; } for (int i = 0; i < m_numberOfColumns; i++) { int max = listData->numberOfOperands(); - newOperands[m_numberOfRows*m_numberOfColumns+i] = i < max ? (Expression *)listData->operand(i) : defaultExpression(); + if (clone) { + newOperands[m_numberOfRows*m_numberOfColumns+i] = i < max ? (Expression *)listData->operand(i)->clone() : defaultExpression(); + } else { + newOperands[m_numberOfRows*m_numberOfColumns+i] = i < max ? (Expression *)listData->operand(i) : defaultExpression(); + } } free(m_operands); m_operands = newOperands; diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index dcbaea8c3..2090dfef6 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -47,7 +47,7 @@ Expression * MatrixInverse::privateEvaluate(Context& context, AngleUnit angleUni delete result; return resultEvaluation; } - Expression * inverse = ((Matrix *)evaluation)->inverse(context, angleUnit); + Expression * inverse = ((Matrix *)evaluation)->createInverse(context, angleUnit); delete evaluation; return inverse; } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index f912aed86..52b4181ed 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -18,7 +18,7 @@ Expression::Type Multiplication::type() const { ExpressionLayout * Multiplication::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout** children_layouts = (ExpressionLayout **)malloc(3*sizeof(ExpressionLayout *)); + ExpressionLayout * children_layouts[3]; children_layouts[0] = m_operands[0]->createLayout(floatDisplayMode, complexFormat); children_layouts[1] = new StringLayout("*", 1); children_layouts[2] = m_operands[1]->type() == Type::Opposite ? new ParenthesisLayout(m_operands[1]->createLayout(floatDisplayMode, complexFormat)) : m_operands[1]->createLayout(floatDisplayMode, complexFormat); @@ -45,7 +45,7 @@ Expression * Multiplication::evaluateOnMatrices(Matrix * m, Matrix * n, Context& if (m->numberOfColumns() != n->numberOfRows()) { return nullptr; } - Expression * operands[m->numberOfRows() * n->numberOfColumns()]; + Expression ** operands = (Expression **)malloc(m->numberOfRows() * n->numberOfColumns()*sizeof(Expression *)); for (int i = 0; i < m->numberOfRows(); i++) { for (int j = 0; j < n->numberOfColumns(); j++) { float a = 0.0f; @@ -69,7 +69,9 @@ Expression * Multiplication::evaluateOnMatrices(Matrix * m, Matrix * n, Context& operands[i*n->numberOfColumns()+j] = new Complex(Complex::Cartesian(a, b)); } } - return new Matrix(operands, m->numberOfRows() * n->numberOfColumns(), m->numberOfRows(), n->numberOfColumns(), false); + Expression * matrix = new Matrix(operands, m->numberOfRows() * n->numberOfColumns(), m->numberOfRows(), n->numberOfColumns(), false); + free(operands); + return matrix; } } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 7493cfc33..92018ecd3 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -56,7 +56,7 @@ Expression * Opposite::privateEvaluate(Context& context, AngleUnit angleUnit) co ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout** children_layouts = (ExpressionLayout **)malloc(2*sizeof(ExpressionLayout *)); + ExpressionLayout * children_layouts[2]; char string[2] = {'-', '\0'}; children_layouts[0] = new StringLayout(string, 1); children_layouts[1] = m_operand->type() == Type::Opposite ? new ParenthesisLayout(m_operand->createLayout(floatDisplayMode, complexFormat)) : m_operand->createLayout(floatDisplayMode, complexFormat); @@ -80,7 +80,7 @@ Expression * Opposite::cloneWithDifferentOperands(Expression** newOperands, } Expression * Opposite::evaluateOnMatrix(Matrix * m, Context& context, AngleUnit angleUnit) const { - Expression * operands[m->numberOfRows() * m->numberOfColumns()]; + Expression ** operands = (Expression **)malloc(m->numberOfRows() * m->numberOfColumns()*sizeof(Expression *)); for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) { Expression * evaluation = m->operand(i)->evaluate(context, angleUnit); assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); @@ -92,7 +92,9 @@ Expression * Opposite::evaluateOnMatrix(Matrix * m, Context& context, AngleUnit operands[i] = new Complex(Complex::Cartesian(-((Complex *)evaluation)->a(), -((Complex *)evaluation)->b())); delete evaluation; } - return new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false); + Expression * matrix = new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false); + free(operands); + return matrix; } } diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index 50bb30893..a8371d418 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -50,7 +50,7 @@ float Product::privateApproximate(Context& context, AngleUnit angleUnit) const { ExpressionLayout * Product::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout ** childrenLayouts = (ExpressionLayout **)malloc(2*sizeof(ExpressionLayout *)); + ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = new StringLayout("n=", 2); childrenLayouts[1] = m_args[1]->createLayout(floatDisplayMode, complexFormat); return new ProductLayout(new HorizontalLayout(childrenLayouts, 2), m_args[2]->createLayout(floatDisplayMode, complexFormat), m_args[0]->createLayout(floatDisplayMode, complexFormat)); diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index a95d61fd0..09d4308c2 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -30,7 +30,7 @@ Expression::Type Subtraction::type() const { ExpressionLayout * Subtraction::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout** children_layouts = (ExpressionLayout **)malloc(3*sizeof(ExpressionLayout *)); + ExpressionLayout * children_layouts[3]; children_layouts[0] = m_operands[0]->createLayout(floatDisplayMode, complexFormat); char string[2] = {'-', '\0'}; children_layouts[1] = new StringLayout(string, 1); diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index ef77a73cb..31e0fbe16 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -50,7 +50,7 @@ float Sum::privateApproximate(Context& context, AngleUnit angleUnit) const { ExpressionLayout * Sum::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout ** childrenLayouts = (ExpressionLayout **)malloc(2*sizeof(ExpressionLayout *)); + ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = new StringLayout("n=", 2); childrenLayouts[1] = m_args[1]->createLayout(floatDisplayMode, complexFormat); return new SumLayout(new HorizontalLayout(childrenLayouts, 2), m_args[2]->createLayout(floatDisplayMode, complexFormat), m_args[0]->createLayout(floatDisplayMode, complexFormat));