diff --git a/poincare/include/poincare/approximation.h b/poincare/include/poincare/approximation.h index 7eec62425..a408bb99a 100644 --- a/poincare/include/poincare/approximation.h +++ b/poincare/include/poincare/approximation.h @@ -2,6 +2,7 @@ #define POINCARE_APPROXIMATION_H #include +#include namespace Poincare { diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index 843d05ad5..8131d1b56 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -1,6 +1,7 @@ #ifndef POINCARE_BINOMIAL_COEFFICIENT_H #define POINCARE_BINOMIAL_COEFFICIENT_H +#include #include #include diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 48b74af93..fda3ebcab 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -12,7 +12,6 @@ namespace Poincare { */ class Decimal : public StaticHierarchy<0> { - friend class Expression; public: static int exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative); static Integer mantissa(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative); diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 688b9fb8d..343ae0455 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index 85a3877d8..807202a93 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { diff --git a/poincare/include/poincare/evaluation.h b/poincare/include/poincare/evaluation.h index 59bdd0f07..e127f99a1 100644 --- a/poincare/include/poincare/evaluation.h +++ b/poincare/include/poincare/evaluation.h @@ -5,6 +5,7 @@ extern "C" { #include } +#include namespace Poincare { @@ -29,6 +30,7 @@ public: virtual ~Evaluation() {} virtual bool isUndefined() const = 0; virtual T toScalar() const { return NAN; } + virtual Expression * complexToExpression(Expression::ComplexFormat complexFormat) const = 0; virtual std::complex createTrace() const = 0; virtual std::complex createDeterminant() const = 0; virtual Evaluation * createInverse() const = 0; @@ -59,6 +61,7 @@ public: return (std::isnan(this->real()) && std::isnan(this->imag())); } T toScalar() const override; + Expression * complexToExpression(Expression::ComplexFormat complexFormat) const override; std::complex createTrace() const override { return *this; } std::complex createDeterminant() const override { return *this; } Complex * createInverse() const override; @@ -97,6 +100,7 @@ public: bool isUndefined() const override { return (numberOfRows() == 1 && numberOfColumns() == 1 && std::isnan(complexOperand(0).real()) && std::isnan(complexOperand(0).imag())); } + Expression * complexToExpression(Expression::ComplexFormat complexFormat) const override; std::complex createTrace() const override; std::complex createDeterminant() const override; MatrixComplex * createInverse() const override; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index ea49264e3..78f6dc33a 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -3,7 +3,6 @@ #include #include -#include #include extern "C" { #include @@ -13,6 +12,7 @@ namespace Poincare { class Context; class Rational; +template class Evaluation; class Expression { template friend class Complex; @@ -326,8 +326,6 @@ private: return nullptr; } /* Evaluation Engine */ - template static Expression * CreateDecimal(T f); - template static Expression * complexToExpression(std::complex c, ComplexFormat complexFormat); virtual Evaluation * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateApproximate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index cbfd48a89..38984f8b6 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -2,6 +2,7 @@ #define POINCARE_GREAT_COMMON_DIVISOR_H #include +#include #include namespace Poincare { diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 5169df5e8..2ce7b1410 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 96203cda6..c2d629851 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 0f201a890..4f78b8940 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index 19dfc36aa..05797ee56 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -2,6 +2,7 @@ #define POINCARE_RANDOM_H #include +#include #include namespace Poincare { diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index dd63cb878..7a8403048 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index 06bd23747..1eaa6bbeb 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace Poincare { diff --git a/poincare/src/evaluation.cpp b/poincare/src/evaluation.cpp index a65477ddd..9ce1534c3 100644 --- a/poincare/src/evaluation.cpp +++ b/poincare/src/evaluation.cpp @@ -7,6 +7,16 @@ extern "C" { #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include namespace Poincare { @@ -19,6 +29,87 @@ T Complex::toScalar() const { return NAN; } +template +static Expression * CreateDecimal(T f) { + if (std::isnan(f) || std::isinf(f)) { + return new Undefined(); + } + return new Decimal(f); +} + +template +Expression * Complex::complexToExpression(Expression::ComplexFormat complexFormat) const { + if (std::isnan(this->real()) || std::isnan(this->imag()) || std::isinf(this->real()) || std::isinf(this->imag())) { + return new Poincare::Undefined(); + } + + switch (complexFormat) { + case Expression::ComplexFormat::Cartesian: + { + Expression * real = nullptr; + Expression * imag = nullptr; + if (this->real() != 0 || this->imag() == 0) { + real = CreateDecimal(this->real()); + } + if (this->imag() != 0) { + if (this->imag() == 1.0 || this->imag() == -1) { + imag = new Symbol(Ion::Charset::IComplex); + } else if (this->imag() > 0) { + imag = new Multiplication(CreateDecimal(this->imag()), new Symbol(Ion::Charset::IComplex), false); + } else { + imag = new Multiplication(CreateDecimal(-this->imag()), new Symbol(Ion::Charset::IComplex), false); + } + } + if (imag == nullptr) { + return real; + } else if (real == nullptr) { + if (this->imag() > 0) { + return imag; + } else { + return new Opposite(imag, false); + } + return imag; + } else if (this->imag() > 0) { + return new Addition(real, imag, false); + } else { + return new Subtraction(real, imag, false); + } + } + default: + { + assert(complexFormat == Expression::ComplexFormat::Polar); + Expression * norm = nullptr; + Expression * exp = nullptr; + T r = std::abs(*this); + T th = std::arg(*this); + if (r != 1 || th == 0) { + norm = CreateDecimal(r); + } + if (r != 0 && th != 0) { + Expression * arg = nullptr; + if (th == 1.0) { + arg = new Symbol(Ion::Charset::IComplex); + } else if (th == -1.0) { + arg = new Opposite(new Symbol(Ion::Charset::IComplex), false); + } else if (th > 0) { + arg = new Multiplication(CreateDecimal(th), new Symbol(Ion::Charset::IComplex), false); + } else { + arg = new Opposite(new Multiplication(CreateDecimal(-th), new Symbol(Ion::Charset::IComplex), false), false); + } + exp = new Power(new Symbol(Ion::Charset::Exponential), arg, false); + } + if (exp == nullptr) { + return norm; + } else if (norm == nullptr) { + return exp; + } else { + return new Multiplication(norm, exp, false); + } + } + } +} + + template Complex * Complex::createInverse() const { return new Complex(Division::compute(std::complex(1.0), *this)); @@ -81,6 +172,17 @@ MatrixComplex::MatrixComplex(std::complex * operands, int numberOfRows, in } } +template +Expression * MatrixComplex::complexToExpression(Expression::ComplexFormat complexFormat) const { + Expression ** operands = new Expression * [numberOfComplexOperands()]; + for (int i = 0; i < numberOfComplexOperands(); i++) { + operands[i] = Complex(complexOperand(i)).complexToExpression(complexFormat); + } + Expression * result = new Matrix(operands, numberOfRows(), numberOfColumns(), false); + delete[] operands; + return result; +} + template std::complex MatrixComplex::createTrace() const { if (numberOfRows() != numberOfColumns()) { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 5235f0d68..7d6d94bb3 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -7,17 +7,10 @@ #include #include #include -#include -#include +#include #include #include #include -#include -#include -#include -#include -#include -#include #include #include #include @@ -420,19 +413,8 @@ Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) { /* Evaluation */ template Expression * Expression::approximate(Context& context, AngleUnit angleUnit, ComplexFormat complexFormat) const { - Expression * result = nullptr; Evaluation * e = privateApproximate(T(), context, angleUnit); - if (e->type() == Evaluation::Type::Complex) { - result = complexToExpression(*(static_cast *>(e)), complexFormat); - } else { - MatrixComplex * matrix = static_cast *>(e); - Expression ** operands = new Expression * [matrix->numberOfComplexOperands()]; - for (int i = 0; i < matrix->numberOfComplexOperands(); i++) { - operands[i] = complexToExpression(matrix->complexOperand(i), complexFormat); - } - result = new Matrix(operands, matrix->numberOfRows(), matrix->numberOfColumns(), false); - delete[] operands; - } + Expression * result = e->complexToExpression(complexFormat); delete e; return result; } @@ -790,85 +772,6 @@ T Expression::approximateWithValueForSymbol(char symbol, T x, Context & context, return value; } -template -Expression * Expression::CreateDecimal(T f) { - if (std::isnan(f) || std::isinf(f)) { - return new Undefined(); - } - return new Decimal(f); -} - -template Expression * Expression::complexToExpression(std::complex c, ComplexFormat complexFormat) { - if (std::isnan(c.real()) || std::isnan(c.imag()) || std::isinf(c.real()) || std::isinf(c.imag())) { - return new Undefined(); - } - - switch (complexFormat) { - case ComplexFormat::Cartesian: - { - Expression * real = nullptr; - Expression * imag = nullptr; - if (c.real() != 0 || c.imag() == 0) { - real = CreateDecimal(c.real()); - } - if (c.imag() != 0) { - if (c.imag() == 1.0 || c.imag() == -1) { - imag = new Symbol(Ion::Charset::IComplex); - } else if (c.imag() > 0) { - imag = new Multiplication(CreateDecimal(c.imag()), new Symbol(Ion::Charset::IComplex), false); - } else { - imag = new Multiplication(CreateDecimal(-c.imag()), new Symbol(Ion::Charset::IComplex), false); - } - } - if (imag == nullptr) { - return real; - } else if (real == nullptr) { - if (c.imag() > 0) { - return imag; - } else { - return new Opposite(imag, false); - } - return imag; - } else if (c.imag() > 0) { - return new Addition(real, imag, false); - } else { - return new Subtraction(real, imag, false); - } - } - default: - { - assert(complexFormat == ComplexFormat::Polar); - Expression * norm = nullptr; - Expression * exp = nullptr; - T r = std::abs(c); - T th = std::arg(c); - if (r != 1 || th == 0) { - norm = CreateDecimal(r); - } - if (r != 0 && th != 0) { - Expression * arg = nullptr; - if (th == 1.0) { - arg = new Symbol(Ion::Charset::IComplex); - } else if (th == -1.0) { - arg = new Opposite(new Symbol(Ion::Charset::IComplex), false); - } else if (th > 0) { - arg = new Multiplication(CreateDecimal(th), new Symbol(Ion::Charset::IComplex), false); - } else { - arg = new Opposite(new Multiplication(CreateDecimal(-th), new Symbol(Ion::Charset::IComplex), false), false); - } - exp = new Power(new Symbol(Ion::Charset::Exponential), arg, false); - } - if (exp == nullptr) { - return norm; - } else if (norm == nullptr) { - return exp; - } else { - return new Multiplication(norm, exp, false); - } - } - } -} - } template Poincare::Expression * Poincare::Expression::approximate(Context& context, AngleUnit angleUnit, ComplexFormat complexFormat) const;