Files
Upsilon/poincare/src/multiplication.cpp
Émilie Feral fa2ee9e624 [poincare] Never return nullptr when creating a expression to avoid
nullptr dereference

Change-Id: Ie7976a8ee86c82283ebcbffc28fe902ddfb7a952
2017-03-29 11:35:30 +02:00

78 lines
3.4 KiB
C++

extern "C" {
#include <assert.h>
#include <stdlib.h>
#include <math.h>
}
#include <poincare/multiplication.h>
#include "layout/string_layout.h"
#include "layout/horizontal_layout.h"
#include "layout/parenthesis_layout.h"
namespace Poincare {
Expression::Type Multiplication::type() const {
return Expression::Type::Multiplication;
}
ExpressionLayout * Multiplication::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const {
assert(floatDisplayMode != FloatDisplayMode::Default);
assert(complexFormat != ComplexFormat::Default);
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);
return new HorizontalLayout(children_layouts, 3);
}
float Multiplication::privateApproximate(Context& context, AngleUnit angleUnit) const {
assert(angleUnit != AngleUnit::Default);
return m_operands[0]->approximate(context, angleUnit)*m_operands[1]->approximate(context, angleUnit);;
}
Expression * Multiplication::cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands) const {
assert(numberOfOperands == 2);
assert(newOperands != nullptr);
return new Multiplication(newOperands, cloneOperands);
}
Expression * Multiplication::evaluateOnComplex(Complex * c, Complex * d, Context& context, AngleUnit angleUnit) const {
return new Complex(Complex::Cartesian(c->a()*d->a()-c->b()*d->b(), c->b()*d->a() + c->a()*d->b()));
}
Expression * Multiplication::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const {
if (m->numberOfColumns() != n->numberOfRows()) {
return new Complex(Complex::Float(NAN));
}
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;
float b = 0.0f;
for (int k = 0; k < m->numberOfColumns(); k++) {
Expression * mEvaluation = m->operand(i*m->numberOfColumns()+k)->evaluate(context, angleUnit);
Expression * nEvaluation = n->operand(k*n->numberOfColumns()+j)->evaluate(context, angleUnit);
assert(mEvaluation->type() == Type::Matrix || mEvaluation->type() == Type::Complex);
assert(nEvaluation->type() == Type::Matrix || nEvaluation->type() == Type::Complex);
if (mEvaluation->type() == Type::Matrix ||nEvaluation->type() == Type::Matrix) {
operands[i] = new Complex(Complex::Float(NAN));
delete mEvaluation;
delete nEvaluation;
continue;
}
a += ((Complex *)mEvaluation)->a()*((Complex *)nEvaluation)->a() - ((Complex *)mEvaluation)->b()*((Complex *)nEvaluation)->b();
b += ((Complex *)mEvaluation)->b()*((Complex *)nEvaluation)->a() + ((Complex *)mEvaluation)->a()*((Complex *)nEvaluation)->b();
delete mEvaluation;
delete nEvaluation;
}
operands[i*n->numberOfColumns()+j] = new Complex(Complex::Cartesian(a, b));
}
}
Expression * matrix = new Matrix(operands, m->numberOfRows() * n->numberOfColumns(), m->numberOfRows(), n->numberOfColumns(), false);
free(operands);
return matrix;
}
}