[poincare] Implementation of shallowReduce for Complex: when replacing

the ans symbol, we might introduce a Complex expression in the input
This commit is contained in:
Émilie Feral
2018-01-09 14:30:35 +01:00
committed by EmilieNumworks
parent 785c6a7329
commit 02b15035fa
5 changed files with 52 additions and 9 deletions

View File

@@ -14,6 +14,8 @@ class Addition : public DynamicHierarchy {
friend class Multiplication;
friend class Subtraction;
friend class Power;
friend class Complex<float>;
friend class Complex<double>;
public:
Type type() const override;
Expression * clone() const override;

View File

@@ -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<float>(context, angleUnit); }
Expression * privateApproximate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename U> Complex<U> * templatedApproximate(Context& context, Expression::AngleUnit angleUnit) const;

View File

@@ -75,6 +75,8 @@ class Expression {
friend class ApproximationEngine;
friend class SimplificationEngine;
friend class LayoutEngine;
friend class Complex<float>;
friend class Complex<double>;
public:
enum class Type : uint8_t {

View File

@@ -16,6 +16,8 @@ class Multiplication : public DynamicHierarchy {
friend class Power;
friend class Subtraction;
friend class Symbol;
friend class Complex<float>;
friend class Complex<double>;
public:
Type type() const override;
Expression * clone() const override;

View File

@@ -1,4 +1,9 @@
#include <poincare/complex.h>
#include <poincare/undefined.h>
#include <poincare/decimal.h>
#include <poincare/addition.h>
#include <poincare/multiplication.h>
#include <poincare/symbol.h>
extern "C" {
#include <assert.h>
#include <stdlib.h>
@@ -12,6 +17,17 @@ extern "C" {
namespace Poincare {
template<typename T>
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<T>::privateCreateLayout(Expression::FloatDisplayMode
return createCartesianLayout(floatDisplayMode);
}
template <class T>
Expression * Complex<T>::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 <class T>
Expression * Complex<T>::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<typename T>
template<typename U>
Complex<U> * Complex<T>::templatedApproximate(Context& context, Expression::AngleUnit angleUnit) const {
@@ -333,13 +371,7 @@ int Complex<T>::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) {