[poincare] Move 'complexToExpression' to Evaluation class

This commit is contained in:
Émilie Feral
2018-05-08 17:29:19 +02:00
parent 0c61e74675
commit 042beb1028
16 changed files with 120 additions and 103 deletions

View File

@@ -2,6 +2,7 @@
#define POINCARE_APPROXIMATION_H
#include <poincare/expression.h>
#include <poincare/evaluation.h>
namespace Poincare {

View File

@@ -1,6 +1,7 @@
#ifndef POINCARE_BINOMIAL_COEFFICIENT_H
#define POINCARE_BINOMIAL_COEFFICIENT_H
#include <poincare/evaluation.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>

View File

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

View File

@@ -3,6 +3,7 @@
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation.h>
namespace Poincare {

View File

@@ -3,6 +3,7 @@
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation.h>
namespace Poincare {

View File

@@ -5,6 +5,7 @@
extern "C" {
#include <stdint.h>
}
#include <poincare/expression.h>
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<T> createTrace() const = 0;
virtual std::complex<T> 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<T> createTrace() const override { return *this; }
std::complex<T> createDeterminant() const override { return *this; }
Complex<T> * 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<T> createTrace() const override;
std::complex<T> createDeterminant() const override;
MatrixComplex<T> * createInverse() const override;

View File

@@ -3,7 +3,6 @@
#include <poincare/expression_layout.h>
#include <poincare/print_float.h>
#include <poincare/evaluation.h>
#include <complex>
extern "C" {
#include <assert.h>
@@ -13,6 +12,7 @@ namespace Poincare {
class Context;
class Rational;
template<class T> class Evaluation;
class Expression {
template<typename T> friend class Complex;
@@ -326,8 +326,6 @@ private:
return nullptr;
}
/* Evaluation Engine */
template<typename T> static Expression * CreateDecimal(T f);
template<typename T> static Expression * complexToExpression(std::complex<T> c, ComplexFormat complexFormat);
virtual Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0;
virtual Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0;

View File

@@ -2,6 +2,7 @@
#define POINCARE_GREAT_COMMON_DIVISOR_H
#include <poincare/layout_engine.h>
#include <poincare/evaluation.h>
#include <poincare/static_hierarchy.h>
namespace Poincare {

View File

@@ -3,6 +3,7 @@
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation.h>
namespace Poincare {

View File

@@ -3,6 +3,7 @@
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation.h>
namespace Poincare {

View File

@@ -3,6 +3,7 @@
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation.h>
namespace Poincare {

View File

@@ -2,6 +2,7 @@
#define POINCARE_RANDOM_H
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation.h>
#include <poincare/layout_engine.h>
namespace Poincare {

View File

@@ -3,6 +3,7 @@
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation.h>
namespace Poincare {

View File

@@ -5,6 +5,7 @@
#include <poincare/symbol.h>
#include <poincare/static_hierarchy.h>
#include <poincare/layout_engine.h>
#include <poincare/evaluation.h>
namespace Poincare {

View File

@@ -7,6 +7,16 @@ extern "C" {
#include <poincare/division.h>
#include <poincare/matrix.h>
#include <poincare/expression.h>
#include <poincare/undefined.h>
#include <poincare/decimal.h>
#include <poincare/multiplication.h>
#include <poincare/opposite.h>
#include <poincare/addition.h>
#include <poincare/subtraction.h>
#include <poincare/matrix.h>
#include <poincare/power.h>
#include <poincare/symbol.h>
#include <ion.h>
#include <cmath>
namespace Poincare {
@@ -19,6 +29,87 @@ T Complex<T>::toScalar() const {
return NAN;
}
template <typename T>
static Expression * CreateDecimal(T f) {
if (std::isnan(f) || std::isinf(f)) {
return new Undefined();
}
return new Decimal(f);
}
template<typename T>
Expression * Complex<T>::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<typename T>
Complex<T> * Complex<T>::createInverse() const {
return new Complex<T>(Division::compute(std::complex<T>(1.0), *this));
@@ -81,6 +172,17 @@ MatrixComplex<T>::MatrixComplex(std::complex<T> * operands, int numberOfRows, in
}
}
template<typename T>
Expression * MatrixComplex<T>::complexToExpression(Expression::ComplexFormat complexFormat) const {
Expression ** operands = new Expression * [numberOfComplexOperands()];
for (int i = 0; i < numberOfComplexOperands(); i++) {
operands[i] = Complex<T>(complexOperand(i)).complexToExpression(complexFormat);
}
Expression * result = new Matrix(operands, numberOfRows(), numberOfColumns(), false);
delete[] operands;
return result;
}
template<typename T>
std::complex<T> MatrixComplex<T>::createTrace() const {
if (numberOfRows() != numberOfColumns()) {

View File

@@ -7,17 +7,10 @@
#include <poincare/matrix_data.h>
#include <poincare/undefined.h>
#include <poincare/simplification_root.h>
#include <poincare/rational.h>
#include <poincare/matrix.h>
#include <poincare/evaluation.h>
#include <poincare/opposite.h>
#include <poincare/variable_context.h>
#include <poincare/decimal.h>
#include <poincare/ieee754.h>
#include <poincare/addition.h>
#include <poincare/multiplication.h>
#include <poincare/subtraction.h>
#include <poincare/power.h>
#include <poincare/opposite.h>
#include <ion.h>
#include <cmath>
#include <float.h>
@@ -420,19 +413,8 @@ Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) {
/* Evaluation */
template<typename T> Expression * Expression::approximate(Context& context, AngleUnit angleUnit, ComplexFormat complexFormat) const {
Expression * result = nullptr;
Evaluation<T> * e = privateApproximate(T(), context, angleUnit);
if (e->type() == Evaluation<T>::Type::Complex) {
result = complexToExpression(*(static_cast<Complex<T> *>(e)), complexFormat);
} else {
MatrixComplex<T> * matrix = static_cast<MatrixComplex<T> *>(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 <typename T>
Expression * Expression::CreateDecimal(T f) {
if (std::isnan(f) || std::isinf(f)) {
return new Undefined();
}
return new Decimal(f);
}
template<typename T> Expression * Expression::complexToExpression(std::complex<T> 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<double>(Context& context, AngleUnit angleUnit, ComplexFormat complexFormat) const;