From 02b15035fad59db901c65a385e629bbe67cb9822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 9 Jan 2018 14:30:35 +0100 Subject: [PATCH] [poincare] Implementation of shallowReduce for Complex: when replacing the ans symbol, we might introduce a Complex expression in the input --- poincare/include/poincare/addition.h | 2 + poincare/include/poincare/complex.h | 9 ++++- poincare/include/poincare/expression.h | 2 + poincare/include/poincare/multiplication.h | 2 + poincare/src/complex.cpp | 46 ++++++++++++++++++---- 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 8e23ed505..a8d2e02db 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -14,6 +14,8 @@ class Addition : public DynamicHierarchy { friend class Multiplication; friend class Subtraction; friend class Power; + friend class Complex; + friend class Complex; public: Type type() const override; Expression * clone() const override; diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index 021f679eb..7b5b57f15 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -64,8 +64,8 @@ public: int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification: complex does not implement simplificationOrderSameType - * because Complex expressions do not appear before evaluation. The sorting - * step is part of simplificaiton process which thus handles no complex. */ + * because Complex expressions are always transformed into an addition of + * Decimal and I symbol before compared with another Expression. */ /* The parameter 'DisplayMode' refers to the way to display float 'scientific' * or 'auto'. The scientific mode returns float with style -1.2E2 whereas @@ -81,7 +81,12 @@ public: static int convertFloatToText(T d, char * buffer, int bufferSize, int numberOfSignificantDigits, Expression::FloatDisplayMode mode = Expression::FloatDisplayMode::Default); private: Complex(T a, T b); + /* Layout */ ExpressionLayout * privateCreateLayout(Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat) const override; + /* Simplification */ + static Expression * CreateDecimal(T f); + Expression * shallowReduce(Context & context, AngleUnit angleUnit) override; + /* Evaluation */ Expression * privateApproximate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Expression * privateApproximate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } template Complex * templatedApproximate(Context& context, Expression::AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 94e82b015..0eb2862f1 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -75,6 +75,8 @@ class Expression { friend class ApproximationEngine; friend class SimplificationEngine; friend class LayoutEngine; + friend class Complex; + friend class Complex; public: enum class Type : uint8_t { diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 8f264aaff..58f01672a 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -16,6 +16,8 @@ class Multiplication : public DynamicHierarchy { friend class Power; friend class Subtraction; friend class Symbol; + friend class Complex; + friend class Complex; public: Type type() const override; Expression * clone() const override; diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index b11787250..dcc4f5ca4 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -1,4 +1,9 @@ #include +#include +#include +#include +#include +#include extern "C" { #include #include @@ -12,6 +17,17 @@ extern "C" { namespace Poincare { +template +int exponent(T f) { + T logBase10 = f != 0 ? std::log10(std::fabs(f)) : 0; + int exponentInBase10 = std::floor(logBase10); + /* Correct the exponent in base 10: sometines the exact log10 of f is 6.999999 + * but is stored as 7 in hardware. We catch these cases here. */ + if (f != 0 && logBase10 == (int)logBase10 && std::fabs(f) < std::pow(10, logBase10)) { + exponentInBase10--; + } + return exponentInBase10; +} void PrintFloat::printBase10IntegerWithDecimalMarker(char * buffer, int bufferLength, Integer i, int decimalMarkerPosition) { /* The decimal marker position is always preceded by a char, thus, it is never @@ -243,6 +259,28 @@ ExpressionLayout * Complex::privateCreateLayout(Expression::FloatDisplayMode return createCartesianLayout(floatDisplayMode); } +template +Expression * Complex::CreateDecimal(T f) { + if (std::isnan(f) || std::isinf(f)) { + return new Undefined(); + } + int e = exponent(f); + int64_t mantissaf = f * std::pow((T)10, -e+PrintFloat::k_numberOfStoredSignificantDigits+1); + return new Decimal(Integer(mantissaf), e); +} + +template +Expression * Complex::shallowReduce(Context & context, AngleUnit angleUnit) { + Expression * a = CreateDecimal(m_a); + Expression * b = CreateDecimal(m_b); + Multiplication * m = new Multiplication(new Symbol(Ion::Charset::IComplex), b, false); + Addition * add = new Addition(a, m, false); + a->shallowReduce(context, angleUnit); + b->shallowReduce(context, angleUnit); + m->shallowReduce(context, angleUnit); + return replaceWith(add, true)->shallowReduce(context, angleUnit); +} + template template Complex * Complex::templatedApproximate(Context& context, Expression::AngleUnit angleUnit) const { @@ -333,13 +371,7 @@ int Complex::convertFloatToTextPrivate(T f, char * buffer, int numberOfSignif return currentChar; } - T logBase10 = f != 0 ? std::log10(std::fabs(f)) : 0; - int exponentInBase10 = std::floor(logBase10); - /* Correct the exponent in base 10: sometines the exact log10 of f is 6.999999 - * but is stored as 7 in hardware. We catch these cases here. */ - if (f != 0 && logBase10 == (int)logBase10 && std::fabs(f) < std::pow(10, logBase10)) { - exponentInBase10--; - } + int exponentInBase10 = exponent(f); Expression::FloatDisplayMode displayMode = mode; if ((exponentInBase10 >= numberOfSignificantDigits || exponentInBase10 <= -numberOfSignificantDigits) && mode == Expression::FloatDisplayMode::Decimal) {