[poincare] Redesign of Expression: first attempt

This commit is contained in:
Émilie Feral
2018-08-02 15:46:31 +02:00
parent b07d20f8ee
commit 54f9ea2d46
162 changed files with 4102 additions and 2284 deletions

View File

@@ -40,7 +40,7 @@ Expression * Equation::standardForm(Context * context) const {
m_standardForm = static_cast<const Equal *>(e)->standardEquation(*context, Preferences::sharedPreferences()->angleUnit());
} else if (e->type() == Expression::Type::Rational && static_cast<Rational *>(e)->isOne()) {
// The equality was reduced which means the equality was always true.
m_standardForm = new Rational(0);
m_standardForm = RationalReference(0);
} else {
// The equality has an undefined operand
assert(e->type() == Expression::Type::Undefined);

View File

@@ -11,23 +11,22 @@ class AbsoluteValue : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
Sign sign() const override { return Sign::Positive; }
private:
Expression * setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override;
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "abs");
}
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit, computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -18,7 +18,6 @@ class Addition : public DynamicHierarchy {
friend class Complex<double>;
public:
Type type() const override;
Expression * clone() const override;
int polynomialDegree(char symbolName) const override;
int privateGetPolynomialCoefficients(char symbolName, Expression * coefficients[]) const override;
/* Evaluation */
@@ -31,7 +30,7 @@ public:
}
private:
/* Layout */
bool needParenthesisWithParent(const Expression * e) const override;
bool needsParenthesisWithParent(SerializableNode * parentNode) const override;
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
return LayoutEngine::createInfixLayout(this, floatDisplayMode, numberOfSignificantDigits, name());
}
@@ -41,7 +40,7 @@ private:
static const char * name() { return "+"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
Expression * shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override;
Expression * factorizeOnCommonDenominator(Context & context, Preferences::AngleUnit angleUnit);
void factorizeOperands(Expression * e1, Expression * e2, Context & context, Preferences::AngleUnit angleUnit);
@@ -51,10 +50,10 @@ private:
template<typename T> static MatrixComplex<T> computeOnMatrixAndComplex(const MatrixComplex<T> m, const std::complex<T> c) {
return ApproximationEngine::elementWiseOnMatrixComplexAndComplex(m, c, compute<T>);
}
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::mapReduce<float>(this, context, angleUnit, compute<float>, computeOnComplexAndMatrix<float>, computeOnMatrixAndComplex<float>, computeOnMatrices<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::mapReduce<double>(this, context, angleUnit, compute<double>, computeOnComplexAndMatrix<double>, computeOnMatrixAndComplex<double>, computeOnMatrices<double>);
}
};

View File

@@ -0,0 +1,39 @@
#ifndef POINCARE_ALLOCATION_FAILED_EVALUATION_H
#define POINCARE_ALLOCATION_FAILED_EVALUATION_H
#include <poincare/evaluation.h>
#include <poincare/complex.h>
namespace Poincare {
template<typename T>
class AllocationFailedEvaluationNode : public EvaluationNode<T> {
public:
// EvaluationNode
typename EvaluationNode<T>::Type type() const override { return EvaluationNode<T>::Type::AllocationFailure; }
bool isUndefined() const override { return true; }
T toScalar() const override{ return NAN; }
ExpressionReference complexToExpression(Preferences::Preferences::ComplexFormat complexFormat) const override;
std::complex<T> trace() const override { return std::complex<T>(NAN); }
std::complex<T> determinant() const override { return std::complex<T>(NAN); }
EvaluationReference<T> inverse() const override { return ComplexReference<T>::Undefined(); }
virtual EvaluationReference<T> transpose() const override { return ComplexReference<T>::Undefined(); }
// TreeNode
size_t size() const override { return sizeof(AllocationFailedEvaluationNode); }
const char * description() const override { return "Allocation Failed"; }
bool isAllocationFailure() const override { return true; }
};
template<typename T>
class AllocationFailedEvaluationReference : public EvaluationReference<T> {
public:
AllocationFailedEvaluationReference() : EvaluationReference<T>() {
TreeNode * node = TreePool::sharedPool()->createTreeNode<AllocationFailedEvaluationNode<T>>();
this->m_identifier = node->identifier();
}
AllocationFailedEvaluationReference(TreeNode * n) : EvaluationReference<T>(n) {}
};
}
#endif

View File

@@ -0,0 +1,38 @@
#ifndef POINCARE_ALLOCATION_FAILED_EXPRESSION_NODE_H
#define POINCARE_ALLOCATION_FAILED_EXPRESSION_NODE_H
#include <poincare/expression_node.h>
#include <poincare/expression_reference.h>
#include <poincare/complex.h>
#include <stdio.h>
namespace Poincare {
class AllocationFailedExpressionNode : public ExpressionNode {
public:
// ExpressionNode
Type type() const override { return Type::AllocationFailure; }
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference<float>::Undefined(); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference<double>::Undefined(); }
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override;
// TreeNode
size_t size() const override { return sizeof(AllocationFailedExpressionNode); }
const char * description() const override { return "Allocation Failed"; }
int numberOfChildren() const override { return 0; }
bool isAllocationFailure() const override { return true; }
};
class AllocationFailedExpressionRef : public ExpressionReference {
public:
AllocationFailedExpressionRef() : ExpressionReference() {
TreeNode * node = TreePool::sharedPool()->createTreeNode<AllocationFailedExpressionNode>();
m_identifier = node->identifier();
}
AllocationFailedExpressionRef(TreeNode * n) : ExpressionReference(n) {}
};
}
#endif

View File

@@ -1,61 +0,0 @@
#ifndef POINCARE_APPROXIMATION_H
#define POINCARE_APPROXIMATION_H
#include <poincare/expression.h>
#include <poincare/evaluation.h>
namespace Poincare {
/* Approximation reprensents an approximated complex. This class is
* theoritecally unecessary as it can be reprensented by an Addition of Decimals
* and I Symbol for example. However, performances are dramatically affected if
* we keep turning float/double into Decimal back and forth (for instance, when
* plotting a graph, we need to set a float/double value for a symbol and
* approximate an expression containing the symbol for each dot displayed). We
* thus use the Approximation class that hold an std::complex<T> and can only
* be approximated. Indeed, the usual methods of expression are not implemented
* to avoid code duplication with Decimal. */
template<typename T>
class Approximation : public Expression {
public:
Approximation(T a, T b = 0.0) :
Expression(),
m_complex(a, b)
{}
Type type() const override {
return Expression::Type::Approximation;
}
Expression * clone() const override {
return new Approximation(m_complex.real(), m_complex.imag());
}
const Expression * const * operands() const override {
assert(false);
return nullptr;
}
int numberOfOperands() const override {
assert(false);
return 0;
}
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
assert(false);
return 0;
}
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
assert(false);
return nullptr;
}
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename U> Complex<U> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const {
return new Complex<U>((U)m_complex.real(), (U)m_complex.imag());
}
std::complex<T> m_complex;
};
}
#endif

View File

@@ -1,8 +1,9 @@
#ifndef POINCARE_APPROXIMATION_ENGINE_H
#define POINCARE_APPROXIMATION_ENGINE_H
#include <poincare/evaluation.h>
#include <poincare/expression.h>
#include <poincare/complex.h>
#include <poincare/matrix_complex.h>
#include <poincare/expression_node.h>
#include <complex>
namespace Poincare {
@@ -11,17 +12,17 @@ class ApproximationEngine {
public:
template <typename T> static std::complex<T> truncateRealOrImaginaryPartAccordingToArgument(std::complex<T> c);
template <typename T> using ComplexCompute = std::complex<T>(*)(const std::complex<T>, Preferences::AngleUnit angleUnit);
template<typename T> static Evaluation<T> * map(const Expression * expression, Context& context, Preferences::AngleUnit angleUnit, ComplexCompute<T> compute);
template <typename T> using ComplexCompute = ComplexReference<T>(*)(const std::complex<T>, Preferences::AngleUnit angleUnit);
template<typename T> static EvaluationReference<T> map(const ExpressionNode * expression, Context& context, Preferences::AngleUnit angleUnit, ComplexCompute<T> compute);
template <typename T> using ComplexAndComplexReduction = std::complex<T>(*)(const std::complex<T>, const std::complex<T>);
template <typename T> using ComplexAndMatrixReduction = MatrixComplex<T>(*)(const std::complex<T> c, const MatrixComplex<T> m);
template <typename T> using MatrixAndComplexReduction = MatrixComplex<T>(*)(const MatrixComplex<T> m, const std::complex<T> c);
template <typename T> using MatrixAndMatrixReduction = MatrixComplex<T>(*)(const MatrixComplex<T> m, const MatrixComplex<T> n);
template<typename T> static Evaluation<T> * mapReduce(const Expression * expression, Context& context, Preferences::AngleUnit angleUnit, ComplexAndComplexReduction<T> computeOnComplexes, ComplexAndMatrixReduction<T> computeOnComplexAndMatrix, MatrixAndComplexReduction<T> computeOnMatrixAndComplex, MatrixAndMatrixReduction<T> computeOnMatrices);
template <typename T> using ComplexAndComplexReduction = ComplexReference<T>(*)(const std::complex<T>, const std::complex<T>);
template <typename T> using ComplexAndMatrixReduction = MatrixComplexReference<T>(*)(const std::complex<T> c, const MatrixComplexReference<T> m);
template <typename T> using MatrixAndComplexReduction = MatrixComplexReference<T>(*)(const MatrixComplexReference<T> m, const std::complex<T> c);
template <typename T> using MatrixAndMatrixReduction = MatrixComplexReference<T>(*)(const MatrixComplexReference<T> m, const MatrixComplexReference<T> n);
template<typename T> static EvaluationReference<T> mapReduce(const ExpressionNode * expression, Context& context, Preferences::AngleUnit angleUnit, ComplexAndComplexReduction<T> computeOnComplexes, ComplexAndMatrixReduction<T> computeOnComplexAndMatrix, MatrixAndComplexReduction<T> computeOnMatrixAndComplex, MatrixAndMatrixReduction<T> computeOnMatrices);
template<typename T> static MatrixComplex<T> elementWiseOnMatrixComplexAndComplex(const MatrixComplex<T> n, const std::complex<T> c, ComplexAndComplexReduction<T> computeOnComplexes);
template<typename T> static MatrixComplex<T> elementWiseOnComplexMatrices(const MatrixComplex<T> m, const MatrixComplex<T> n, ComplexAndComplexReduction<T> computeOnComplexes);
template<typename T> static MatrixComplexReference<T> elementWiseOnMatrixComplexAndComplex(const MatrixComplexReference<T> n, std::complex<T> c, ComplexAndComplexReduction<T> computeOnComplexes);
template<typename T> static MatrixComplexReference<T> elementWiseOnComplexMatrices(const MatrixComplexReference<T> m, const MatrixComplexReference<T> n, ComplexAndComplexReduction<T> computeOnComplexes);
};

View File

@@ -12,7 +12,6 @@ class ArcCosine : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -25,13 +24,13 @@ private:
return "acos";
}
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -12,7 +12,6 @@ class ArcSine : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -23,13 +22,13 @@ private:
}
const char * name() const { return "asin"; }
/* Simplification */
Expression * shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit, computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -12,7 +12,6 @@ class ArcTangent : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -23,13 +22,13 @@ private:
}
const char * name() const { return "atan"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -6,11 +6,11 @@ namespace Poincare {
class Arithmetic {
public:
static Integer LCM(const Integer * i, const Integer * j);
static Integer GCD(const Integer * i, const Integer * j);
static IntegerReference LCM(const IntegerReference i, const IntegerReference j);
static IntegerReference GCD(const IntegerReference i, const IntegerReference j);
/* When outputCoefficients[0] is set to -1, that indicates a special case:
* i could not be factorized. */
static void PrimeFactorization(const Integer * i, Integer * outputFactors, Integer * outputCoefficients, int outputLength);
static void PrimeFactorization(const IntegerReference i, IntegerReference outputFactors[], IntegerReference outputCoefficients[], int outputLength);
constexpr static int k_numberOfPrimeFactors = 1000;
constexpr static int k_maxNumberOfPrimeFactors = 32;
private:

View File

@@ -11,7 +11,6 @@ class BinomialCoefficient : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
template<typename T> static T compute(T k, T n);
private:
constexpr static int k_maxNValue = 300;
@@ -21,11 +20,11 @@ private:
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "binomial");
}
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -11,7 +11,6 @@ class Ceiling : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
@@ -20,13 +19,13 @@ private:
}
const char * name() const { return "ceil"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit, computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -0,0 +1,46 @@
#ifndef POINCARE_COMPLEX_H
#define POINCARE_COMPLEX_H
#include <poincare/evaluation.h>
namespace Poincare {
template<typename T>
class ComplexReference;
template<typename T>
class ComplexNode : public std::complex<T>, public EvaluationNode<T> {
public:
// TreeNode
size_t size() const override { return sizeof(ComplexNode<T>); }
const char * description() const override { return "Evaluation complex"; }
int numberOfChildren() const override { return 0; }
void setComplex(std::complex<T> c);
typename Poincare::EvaluationNode<T>::Type type() const override { return Poincare::EvaluationNode<T>::Type::Complex; }
bool isUndefined() const override {
return (std::isnan(this->real()) && std::isnan(this->imag()));
}
T toScalar() const override;
ExpressionReference complexToExpression(Preferences::Preferences::ComplexFormat complexFormat) const override;
std::complex<T> trace() const override { return *this; }
std::complex<T> determinant() const override { return *this; }
EvaluationReference<T> inverse() const override;
EvaluationReference<T> transpose() const override { return ComplexReference<T>(*this); }
};
template<typename T>
class ComplexReference : public std::complex<T>, public EvaluationReference<T> {
public:
ComplexReference(TreeNode * t) : EvaluationReference<T>(t) {}
ComplexReference(T a, T b = 0.0) : ComplexReference(std::complex<T>(a, b)) {}
ComplexReference(std::complex<T> c);
static ComplexReference<T> Undefined() {
return ComplexReference<T>(NAN, NAN);
}
};
}
#endif

View File

@@ -11,7 +11,6 @@ class ComplexArgument : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,13 +21,13 @@ private:
}
const char * name() const { return "arg"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -10,7 +10,6 @@ class ConfidenceInterval : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
int polynomialDegree(char symbolName) const override;
private:
/* Layout */
@@ -22,11 +21,11 @@ private:
}
virtual const char * name() const { return "confidence"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(Expression::SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<float> approximate(Expression::SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(Expression::DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
class SimplePredictionInterval : public ConfidenceInterval {

View File

@@ -11,7 +11,6 @@ class Conjugate : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
@@ -19,13 +18,13 @@ private:
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "conj");
}
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -1,15 +1,15 @@
#ifndef POINCARE_CONTEXT_H
#define POINCARE_CONTEXT_H
#include <poincare/expression.h>
#include <poincare/symbol.h>
namespace Poincare {
class ExpressionReference;
class SymbolReference;
class Context {
public:
virtual const Expression * expressionForSymbol(const Symbol * symbol) = 0;
virtual void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) = 0;
virtual const ExpressionReference expressionForSymbol(const SymbolReference symbol) = 0;
virtual void setExpressionForSymbolName(const ExpressionReference expression, const SymbolReference symbol, Context & context) = 0;
};
}

View File

@@ -14,7 +14,6 @@ class Cosine : public StaticHierarchy<1>::StaticHierarchy {
friend class Tangent;
public:
Type type() const override;
Expression * clone() const override;
float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override;
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian);
private:
@@ -27,12 +26,12 @@ private:
}
const char * name() const { return "cos"; }
/* Simplication */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -21,24 +21,24 @@ public:
Integer mantissa() const { return m_mantissa; }
// Expression subclassing
Type type() const override;
Expression * clone() const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
Sign sign() const override { return m_mantissa.isNegative() ? Sign::Negative : Sign::Positive; }
constexpr static int k_maxExponentLength = 4;
private:
constexpr static double k_biggestMantissaFromDouble = 999999999999999;
constexpr static int k_maxDoubleExponent = 308;
/* Comparison */
int simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const override;
int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override;
/* Layout */
bool needParenthesisWithParent(const Expression * e) const override;
bool needsParenthesisWithParent(SerializableNode * parentNode) const override;
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
Expression * shallowBeautify(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowBeautify(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
int convertToText(char * buffer, int bufferSize, Preferences::PrintFloatMode mode, int numberOfSignificantDigits) const;
// Worst case is -1.2345678901234E-1000

View File

@@ -11,7 +11,6 @@ class Derivative : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
int polynomialDegree(char symbolName) const override;
private:
/* Layout */
@@ -23,11 +22,11 @@ private:
}
const char * name() const { return "diff"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
template<typename T> T growthRateAroundAbscissa(T x, T h, Context & context, Preferences::AngleUnit angleUnit) const;
template<typename T> T riddersApproximation(Context & context, Preferences::AngleUnit angleUnit, T x, T h, T * error) const;
// TODO: Change coefficients?

View File

@@ -10,7 +10,6 @@ class Determinant : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -21,11 +20,11 @@ private:
}
const char * name() const { return "det"; }
/* Simplification */
Expression * shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -14,28 +14,27 @@ class Division : public StaticHierarchy<2> {
friend class Power;
public:
Type type() const override;
Expression * clone() const override;
template<typename T> static std::complex<T> compute(const std::complex<T> c, const std::complex<T> d);
int polynomialDegree(char symbolName) const override;
private:
/* Layout */
bool needParenthesisWithParent(const Expression * e) const override;
bool needsParenthesisWithParent(SerializableNode * parentNode) const override;
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "/");
}
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static MatrixComplex<T> computeOnMatrixAndComplex(const MatrixComplex<T> m, const std::complex<T> c) {
return ApproximationEngine::elementWiseOnMatrixComplexAndComplex(m, c, compute<T>);
}
template<typename T> static MatrixComplex<T> computeOnComplexAndMatrix(const std::complex<T> c, const MatrixComplex<T> n);
template<typename T> static MatrixComplex<T> computeOnMatrices(const MatrixComplex<T> m, const MatrixComplex<T> n);
virtual Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
virtual EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::mapReduce<float>(this, context, angleUnit, compute<float>, computeOnComplexAndMatrix<float>, computeOnMatrixAndComplex<float>, computeOnMatrices<float>);
}
virtual Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
virtual EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::mapReduce<double>(this, context, angleUnit, compute<double>, computeOnComplexAndMatrix<double>, computeOnMatrixAndComplex<double>, computeOnMatrices<double>);
}
};

View File

@@ -12,7 +12,6 @@ class DivisionQuotient : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -23,11 +22,11 @@ private:
}
const char * name() const { return "quo"; }
/* Simplification */
Expression * shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -11,7 +11,6 @@ class DivisionRemainder : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,11 +21,11 @@ private:
}
const char * name() const { return "rem"; }
/* Simplification */
Expression * shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -35,7 +35,7 @@ protected:
int m_numberOfOperands;
private:
void removeOperandAtIndex(int i, bool deleteAfterRemoval);
int simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const override;
int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override;
int simplificationOrderGreaterType(const Expression * e, bool canBeInterrupted) const override;
};

View File

@@ -13,15 +13,14 @@ public:
Type type() const override {
return Type::EmptyExpression;
}
Expression * clone() const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -11,22 +11,21 @@ class Equal : public StaticHierarchy<2> {
public:
using StaticHierarchy<2>::StaticHierarchy;
Type type() const override;
Expression * clone() const override;
int polynomialDegree(char symbolName) const override;
// For the equation A = B, create the reduced expression A-B
Expression * standardEquation(Context & context, Preferences::AngleUnit angleUnit) const;
private:
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "=");
}
/* Evalutation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -5,111 +5,58 @@
extern "C" {
#include <stdint.h>
}
#include <poincare/expression.h>
#include <poincare/preferences.h>
#include <poincare/tree_node.h>
#include <poincare/tree_reference.h>
namespace Poincare {
/* acos, asin, arctan, acosh, asinh, arctanh and log have branch cuts on the
* complex plan.
* - acos, asin, atanh: ]-inf, -1[U]1, +inf[
* - atan, asinh: ]-inf*i, -i[U]i, +inf*i[
* - acosh: ]-inf, 1]
* - log: ]-inf, 0]
* They are then multivalued on these cuts. We followed the convention chosen
* by the lib c++ of llvm but it might differ from a calculator to another
* (ie acos(2) = -1.3169578969248*I or 1.3169578969248*I). */
class ExpressionReference;
template<typename T>
class EvaluationReference;
template<typename T>
class Evaluation {
class EvaluationNode : public TreeNode {
public:
enum class Type : uint8_t {
AllocationFailure,
Complex,
MatrixComplex
};
EvaluationNode<T> * childAtIndex(int index) const override { return static_cast<EvaluationNode<T> *>(TreeNode::childAtIndex(index)); }
virtual Type type() const = 0;
virtual ~Evaluation() {}
virtual ~EvaluationNode() = default;
virtual bool isUndefined() const = 0;
virtual T toScalar() const { return NAN; }
virtual Expression * complexToExpression(Preferences::ComplexFormat complexFormat) const = 0;
virtual std::complex<T> createTrace() const = 0;
virtual std::complex<T> createDeterminant() const = 0;
virtual Evaluation * createInverse() const = 0;
virtual Evaluation * createTranspose() const = 0;
};
virtual ExpressionReference complexToExpression(Preferences::ComplexFormat complexFormat) const = 0;
virtual std::complex<T> trace() const = 0;
virtual std::complex<T> determinant() const = 0;
virtual EvaluationReference<T> inverse() const = 0;
virtual EvaluationReference<T> transpose() const = 0;
template <typename T>
using ComplexFunction = std::complex<T> (*)(const std::complex<T>&);
// TreeNode
static TreeNode * FailedAllocationStaticNode();
TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); }
template<typename T>
class Complex : public std::complex<T>, public Evaluation<T> {
public:
Complex(T a, T b = 0.0) : std::complex<T>(a, b) {}
Complex(std::complex<T> c) : std::complex<T>(c) {
if (this->real() == -0) {
this->real(0);
}
if (this->imag() == -0) {
this->imag(0);
}
}
static Complex Undefined() {
return Complex(NAN, NAN);
}
virtual ~Complex() {}
typename Poincare::Evaluation<T>::Type type() const override { return Poincare::Evaluation<T>::Type::Complex; }
bool isUndefined() const override {
return (std::isnan(this->real()) && std::isnan(this->imag()));
}
T toScalar() const override;
Expression * complexToExpression(Preferences::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;
Complex<T> * createTranspose() const override { return new Complex<T>(*this); }
/* Complex functions */
static std::complex<T> pow(const std::complex<T> &c, const std::complex<T> &d);
static std::complex<T> sqrt(const std::complex<T> &c) {
return approximate(c, std::sqrt);
}
static std::complex<T> cos(const std::complex<T> &c) {
return approximate(c, std::cos);
}
static std::complex<T> sin(const std::complex<T> &c) {
return approximate(c, std::sin);
}
static std::complex<T> tan(const std::complex<T> &c) {
return approximate(c, std::tan);
}
static std::complex<T> approximate(const std::complex<T>& c, ComplexFunction<T> approximation);
// Tree
//LayoutNode * childAtIndex(int i) { return static_cast<LayoutNode *>(TreeNode::childAtIndex(i)); }
};
template<typename T>
class MatrixComplex : public Evaluation<T> {
class EvaluationReference : public TreeReference {
public:
MatrixComplex(std::complex<T> * operands, int numberOfRows, int numberOfColumns);
static MatrixComplex Undefined() {
std::complex<T> undef = std::complex<T>(NAN, NAN);
return MatrixComplex<T>(&undef, 1, 1);
}
virtual ~MatrixComplex() {}
typename Poincare::Evaluation<T>::Type type() const override { return Poincare::Evaluation<T>::Type::MatrixComplex; }
const std::complex<T> complexOperand(int i) const { return m_operands[i]; }
int numberOfComplexOperands() const { return m_numberOfRows*m_numberOfColumns; }
int numberOfRows() const { return m_numberOfRows; }
int numberOfColumns() const { return m_numberOfColumns; }
bool isUndefined() const override {
return (numberOfRows() == 1 && numberOfColumns() == 1 && std::isnan(complexOperand(0).real()) && std::isnan(complexOperand(0).imag()));
}
Expression * complexToExpression(Preferences::ComplexFormat complexFormat) const override;
std::complex<T> createTrace() const override;
std::complex<T> createDeterminant() const override;
MatrixComplex<T> * createInverse() const override;
MatrixComplex<T> * createTranspose() const override;
static MatrixComplex<T> createIdentity(int dim);
private:
std::complex<T> * m_operands;
int m_numberOfRows;
int m_numberOfColumns;
EvaluationReference(TreeNode * t) : TreeReference(t) {}
EvaluationNode<T> * node() const override{ return static_cast<EvaluationNode<T> *>(TreeReference::node()); }
typename Poincare::EvaluationNode<T>::Type type() const { return node()->type(); }
bool isUndefined() const { return node()->isUndefined(); }
T toScalar() const { return node()->toScalar(); }
ExpressionReference complexToExpression(Preferences::ComplexFormat complexFormat) const;
std::complex<T> trace() const { return node()->trace(); }
std::complex<T> determinant() const { return node()->determinant(); }
EvaluationReference inverse() const { return node()->inverse(); }
EvaluationReference transpose() const { return node()->transpose(); }
protected:
EvaluationReference() : TreeReference() {}
};
}

View File

@@ -292,9 +292,9 @@ protected:
private:
virtual Expression * replaceSymbolWithExpression(char symbol, Expression * expression);
/* Properties */
virtual Expression * setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { assert(false); return nullptr; }
virtual ExpressionReference setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { assert(false); return nullptr; }
bool isOfType(Type * types, int length) const;
virtual bool needParenthesisWithParent(const Expression * e) const;
virtual bool needsParenthesisWithParent(SerializableNode * parentNode) const;
virtual int privateGetPolynomialCoefficients(char symbolName, Expression * coefficients[]) const;
/* Comparison */
/* In the simplification order, most expressions are compared by only
@@ -310,7 +310,7 @@ private:
Expression * deepBeautify(Context & context, Preferences::AngleUnit angleUnit);
Expression * deepReduce(Context & context, Preferences::AngleUnit angleUnit);
// TODO: should be virtual pure
virtual Expression * shallowReduce(Context & context, Preferences::AngleUnit angleUnit);
virtual ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit);
virtual Expression * shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { return this; };
// Private methods used in simplification process
@@ -318,8 +318,8 @@ private:
return nullptr;
}
/* Evaluation Engine */
virtual Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const = 0;
virtual Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const = 0;
virtual EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const = 0;
virtual EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const = 0;
/* Expression roots/extrema solver*/
constexpr static double k_solverPrecision = 1.0E-5;

View File

@@ -0,0 +1,165 @@
#ifndef POINCARE_EXPRESSION_NODE_H
#define POINCARE_EXPRESSION_NODE_H
#include <poincare/serializable_node.h>
#include <poincare/evaluation.h>
#include <poincare/layout_reference.h>
#include <poincare/context.h>
#include <stdint.h>
namespace Poincare {
/* Methods preceded by a '*!*' interfere with the expression pools which can
* make 'this' outdated. They should only be call only be call in a wrapper on
* ExpressionRef. */
class ExpressionNode : public SerializableNode {
friend class ApproximationEngine;
friend class SymbolNode;
friend class NAryExpressionNode;
public:
enum class Type : uint8_t {
AllocationFailure = 0,
Undefined = 1,
Integer = 2,
Rational,
Decimal,
Float,
Infinity,
Multiplication,
Power,
Addition,
Factorial,
Division,
Store,
Equal,
Sine,
Cosine,
Tangent,
AbsoluteValue,
ArcCosine,
ArcSine,
ArcTangent,
BinomialCoefficient,
Ceiling,
ComplexArgument,
Conjugate,
Derivative,
Determinant,
DivisionQuotient,
DivisionRemainder,
Factor,
Floor,
FracPart,
GreatCommonDivisor,
HyperbolicArcCosine,
HyperbolicArcSine,
HyperbolicArcTangent,
HyperbolicCosine,
HyperbolicSine,
HyperbolicTangent,
ImaginaryPart,
Integral,
LeastCommonMultiple,
Logarithm,
MatrixTrace,
NaperianLogarithm,
NthRoot,
Opposite,
Parenthesis,
PermuteCoefficient,
Product,
Random,
Randint,
RealPart,
Round,
SquareRoot,
Subtraction,
Sum,
Symbol,
Matrix,
ConfidenceInterval,
MatrixDimension,
MatrixInverse,
MatrixTranspose,
PredictionInterval,
EmptyExpression
};
/* Allocation failure */
static TreeNode * FailedAllocationStaticNode();
TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); }
/* Poor man's RTTI */
virtual Type type() const = 0;
/* Properties */
enum class Sign {
Negative = -1,
Unknown = 0,
Positive = 1
};
virtual Sign sign() const { return Sign::Unknown; }
virtual bool isNumber() const { return false; }
/*!*/ virtual ExpressionReference replaceSymbolWithExpression(char symbol, ExpressionReference expression);
/*!*/ virtual ExpressionReference setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit);
virtual int polynomialDegree(char symbolName) const;
/*!*/ virtual int getPolynomialCoefficients(char symbolName, ExpressionReference coefficients[]) const;
typedef bool (*isVariableTest)(char c);
virtual int getVariables(isVariableTest isVariable, char * variables) const;
virtual float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const;
bool isOfType(Type * types, int length) const;
// Useful to avoid parsing incorrect expressions as cos(2,3,4)
virtual bool hasValidNumberOfOperands(int numberOfOperands) const { return numberOfChildren() == numberOfOperands; }
/* Comparison */
/* Simplification */
/* SimplificationOrder returns:
* 1 if e1 > e2
* -1 if e1 < e2
* 0 if e1 == e
* The order groups like terms together to avoid quadratic complexity when
* factorizing addition or multiplication. For example, it groups terms with
* same bases together (ie Pi, Pi^3) and with same non-rational factors
* together (ie Pi, 2*Pi).
* Because SimplificationOrder is a recursive call, we sometimes enable its
* interruption to avoid freezing in the simplification process. */
static int SimplificationOrder(const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted = false);
/* In the simplification order, most expressions are compared by only
* comparing their types. However hierarchical expressions of same type would
* compare their operands and thus need to reimplement
* simplificationOrderSameType. Besides, operations that can be simplified
* (ie +, *, ^, !) have specific rules to group like terms together and thus
* reimplement simplificationOrderGreaterType. */
virtual int simplificationOrderGreaterType(const ExpressionNode * e, bool canBeInterrupted) const { return -1; }
//TODO: What should be the implementation for complex?
virtual int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const { return 0; }
/* Layout Engine */
virtual LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const = 0;
/* Evaluation Engine */
typedef float SinglePrecision;
typedef double DoublePrecision;
constexpr static int k_maxNumberOfSteps = 10000;
virtual EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const = 0;
virtual EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const = 0;
/* Simplification */
/*!*/ virtual ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit);
/*!*/ virtual ExpressionReference shallowBeautify(Context & context, Preferences::AngleUnit angleUnit);
protected:
// Private methods used in simplification process
/*!*/ virtual ExpressionReference cloneDenominator(Context & context, Preferences::AngleUnit angleUnit) const;
/* Hierarchy */
ExpressionNode * childAtIndex(int i) const override { return static_cast<ExpressionNode *>(SerializableNode::childAtIndex(i)); }
ExpressionNode * parent() const override { return static_cast<ExpressionNode *>(SerializableNode::parent()); }
};
}
#endif

View File

@@ -0,0 +1,234 @@
#ifndef POINCARE_EXPRESSION_REFERENCE_H
#define POINCARE_EXPRESSION_REFERENCE_H
#include <poincare/serializable_reference.h>
#include <poincare/preferences.h>
#include <poincare/print_float.h>
#include <poincare/expression_node.h>
#include <stdio.h>
namespace Poincare {
class Context;
class ExpressionReference : public SerializableReference {
friend class ExpressionNode;
friend class NAryExpressionNode;
friend class SymbolNode;
public:
using SerializableReference::SerializableReference;
/* Constructor & Destructor */
virtual ~ExpressionReference() = default;
static ExpressionReference parse(char const * string);
static void ReplaceSymbolWithExpression(ExpressionReference * expressionAddress, char symbol, ExpressionReference expression);
ExpressionReference clone() const;
/* Reference */
ExpressionNode * node() const override { return static_cast<ExpressionNode *>(SerializableReference::node()); }
/* Circuit breaker */
typedef bool (*CircuitBreaker)();
static void setCircuitBreaker(CircuitBreaker cb);
static bool shouldStopProcessing();
/* Properties */
ExpressionNode::Sign sign() const { return node()->sign(); }
ExpressionReference setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit) { return node()->setSign(s, context, angleUnit); }
bool isNumber() const { return node()->isNumber(); }
bool isRationalZero() const;
typedef bool (*ExpressionTest)(const ExpressionReference e, Context & context);
bool recursivelyMatches(ExpressionTest test, Context & context) const;
bool isApproximate(Context & context) const;
static bool IsMatrix(const ExpressionReference e, Context & context);
/* 'characteristicXRange' tries to assess the range on x where the expression
* (considered as a function on x) has an interesting evolution. For example,
* the period of the function on 'x' if it is periodic. If
* the function is x-independent, the return value is 0.0f (because any
* x-range is equivalent). If the function does not have an interesting range,
* the return value is NAN.
* NB: so far, we consider that the only way of building a periodic function
* is to use sin/tan/cos(f(x)) with f a linear function. */
float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const { return this->node()->characteristicXRange(context, angleUnit); }
/* polynomialDegree returns:
* - (-1) if the expression is not a polynome
* - the degree of the polynome otherwise */
int polynomialDegree(char symbolName) const { return this->node()->polynomialDegree(symbolName); }
/* getVariables fills the table variables with the variable present in the
* expression and returns the number of entries in filled in variables.
* For instance getVariables('x+y+2*w/cos(4)') would result in
* variables = « xyw » and would return 3. If the final number of
* variables would overflow the maxNumberOfVariables, getVariables return -1 */
static constexpr int k_maxNumberOfVariables = 6;
int getVariables(ExpressionNode::isVariableTest isVariable, char * variables) const { return this->node()->getVariables(isVariable, variables); }
/* getLinearCoefficients return false if the expression is not linear with
* the variables hold in 'variables'. Otherwise, it fills 'coefficients' with
* the coefficients of the variables hold in 'variables' (following the same
* order) and 'constant' with the constant of the expression. */
bool getLinearCoefficients(char * variables, ExpressionReference coefficients[], ExpressionReference constant[], Context & context, Preferences::AngleUnit angleUnit) const;
/* getPolynomialCoefficients fills the table coefficients with the expressions
* of the first 3 polynomial coefficients and return polynomialDegree.
* coefficients has up to 3 entries. It supposed to be called on Reduced
* expression. */
static constexpr int k_maxPolynomialDegree = 2;
static constexpr int k_maxNumberOfPolynomialCoefficients = k_maxPolynomialDegree+1;
int getPolynomialCoefficients(char symbolName, ExpressionReference coefficients[], Context & context, Preferences::AngleUnit angleUnit) const;
/* Comparison */
/* isIdenticalTo is the "easy" equality, it returns true if both trees have
* same structures and all their nodes have same types and values (ie,
* sqrt(pi^2) is NOT identical to pi). */
bool isIdenticalTo(const ExpressionReference e) const {
/* We use the simplification order only because it is a already-coded total
* order on expresssions. */
return ExpressionNode::SimplificationOrder(this->node(), e.node(), true) == 0;
}
bool isEqualToItsApproximationLayout(ExpressionReference approximation, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context);
/* Layout Engine */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return this->node()->createLayout(floatDisplayMode, numberOfSignificantDigits); }
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { return this->node()->writeTextInBuffer(buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits); }
/* Simplification */
static ExpressionReference ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit);
static void Simplify(ExpressionReference * expressionAddress, Context & context, Preferences::AngleUnit angleUnit);
/* Approximation Engine */
template<typename U> ExpressionReference approximate(Context& context, Preferences::AngleUnit angleUnit, Preferences::Preferences::ComplexFormat complexFormat) const;
template<typename U> U approximateToScalar(Context& context, Preferences::AngleUnit angleUnit) const;
template<typename U> static U approximateToScalar(const char * text, Context& context, Preferences::AngleUnit angleUnit);
template<typename U> U approximateWithValueForSymbol(char symbol, U x, Context & context, Preferences::AngleUnit angleUnit) const;
/* Expression roots/extrema solver*/
struct Coordinate2D {
double abscissa;
double value;
};
Coordinate2D nextMinimum(char symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit) const;
Coordinate2D nextMaximum(char symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit) const;
double nextRoot(char symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit) const;
Coordinate2D nextIntersection(char symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit, const ExpressionReference expression) const;
private:
/* Hierarchy */
ExpressionReference childAtIndex(int i) const {
return ExpressionReference(TreeReference::treeChildAtIndex(i).node());
}
/* Simplification */
ExpressionReference deepBeautify(Context & context, Preferences::AngleUnit angleUnit);
ExpressionReference deepReduce(Context & context, Preferences::AngleUnit angleUnit);
// TODO: should be virtual pure
virtual ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { return this->node()->shallowReduce(context, angleUnit); }
virtual ExpressionReference shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { return this->node()->shallowBeautify(context, angleUnit); };
/* Approximation */
template<typename U> static U epsilon();
/* Expression roots/extrema solver*/
constexpr static double k_solverPrecision = 1.0E-5;
constexpr static double k_sqrtEps = 1.4901161193847656E-8; // sqrt(DBL_EPSILON)
constexpr static double k_goldenRatio = 0.381966011250105151795413165634361882279690820194237137864; // (3-sqrt(5))/2
constexpr static double k_maxFloat = 1e100;
typedef double (*EvaluationAtAbscissa)(char symbol, double abscissa, Context & context, Preferences::AngleUnit angleUnit, const ExpressionReference expression0, const ExpressionReference expression1);
Coordinate2D nextMinimumOfExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const ExpressionReference expression = ExpressionReference(nullptr), bool lookForRootMinimum = false) const;
void bracketMinimum(char symbol, double start, double step, double max, double result[3], EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const ExpressionReference expression = ExpressionReference(nullptr)) const;
Coordinate2D brentMinimum(char symbol, double ax, double bx, EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const ExpressionReference expression = ExpressionReference(nullptr)) const;
double nextIntersectionWithExpression(char symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const ExpressionReference expression) const;
void bracketRoot(char symbol, double start, double step, double max, double result[2], EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const ExpressionReference expression) const;
double brentRoot(char symbol, double ax, double bx, double precision, EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const ExpressionReference expression) const;
};
/*
class UndefinedNode : public ExpressionNode {
public:
// ExpressionNode
Type type() const override { return Type::Undefined; }
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return Complex<float>::Undefined().storeEvaluation(); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return Complex<double>::Undefined().storeEvaluation(); }
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override;
// TreeNode
size_t size() const override { return sizeof(UndefinedNode); }
const char * description() const override { return "Allocation Failed"; }
int numberOfChildren() const override { return 0; }
bool isAllocationFailure() const override { return true; }
};
class SymbolNode : public ExpressionNode {
public:
bool isApproximate(Context & context) const;
bool isMatrixSymbol() const;
char name() const;
// ExpressionNode
Type type() const override { return Type::Undefined; }
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return Complex<float>::Undefined().storeEvaluation(); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return Complex<double>::Undefined().storeEvaluation(); }
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override;
// TreeNode
size_t size() const override { return sizeof(UndefinedNode); }
const char * description() const override { return "Allocation Failed"; }
int numberOfChildren() const override { return 0; }
bool isAllocationFailure() const override { return true; }
};
class RationalNode : public ExpressionNode {
public:
// ExpressionNode
Type type() const override { return Type::Rational; }
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return Complex<float>::Undefined().storeEvaluation(); }
Evaluation<double> * approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return Complex<double>::Undefined().storeEvaluation(); }
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override;
// TreeNode
size_t size() const override { return sizeof(UndefinedNode); }
const char * description() const override { return "Allocation Failed"; }
int numberOfChildren() const override { return 0; }
bool isAllocationFailure() const override { return true; }
};
class OppositeNode : public ExpressionNode {
public:
// ExpressionNode
Type type() const override { return Type::Opposite; }
Evaluation<float> * approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return Complex<float>::Undefined().storeEvaluation(); }
Evaluation<double> * approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return Complex<double>::Undefined().storeEvaluation(); }
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override;
// TreeNode
size_t size() const override { return sizeof(UndefinedNode); }
const char * description() const override { return "Allocation Failed"; }
int numberOfChildren() const override { return 0; }
bool isAllocationFailure() const override { return true; }
};
typedef ExpressionReference UndefinedRef;
typedef ExpressionReference SymbolRef;
class RationalRef : public ExpressionReference {
public:
RationalRef(int i) :
ExpressionReference()
{
}
};
class OppositeRef : public ExpressionReference {
public:
OppositeRef(ExpressionReference child) :
ExpressionReference()
{
}
};
*/
}
#endif

View File

@@ -13,7 +13,6 @@ class Factor : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -24,12 +23,12 @@ private:
}
const char * name() const { return "factor"; }
/* Simplification */
Expression * shallowBeautify(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowBeautify(Context& context, Preferences::AngleUnit angleUnit) override;
Expression * createMultiplicationOfIntegerPrimeDecomposition(Integer i, Context & context, Preferences::AngleUnit angleUnit);
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const {
return operand(0)->privateApproximate(T(), context, angleUnit);
}
};

View File

@@ -10,22 +10,21 @@ class Factorial : public StaticHierarchy<1> {
public:
Factorial(const Expression * argument, bool clone = true);
Type type() const override;
Expression * clone() const override;
private:
constexpr static int k_maxOperandValue = 100;
/* Layout */
bool needParenthesisWithParent(const Expression * e) const override;
bool needsParenthesisWithParent(SerializableNode * parentNode) const override;
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
/* Simplication */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
Expression * shallowBeautify(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowBeautify(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}

View File

@@ -0,0 +1,68 @@
#ifndef POINCARE_FLOAT_H
#define POINCARE_FLOAT_H
#include <poincare/number.h>
namespace Poincare {
/* Float reprensents an approximated number. This class is use when:
* - a rational overflows
* - to avoid turning float/double into Decimal back and forth because
* performances are dramatically affected when doing so. For instance, when
* plotting a graph, we need to set a float/double value for a symbol and
* approximate an expression containing the symbol for each dot displayed).
* We thus use the Float class that hold a float/double.
* Float can only be approximated ; Float is an INTERNAL node only. Indeed,
* they are always turned back into Decimal when beautifying. Thus, the usual
* methods of expression are not implemented to avoid code duplication with
* Decimal. */
template<typename T>
class FloatNode : public NumberNode {
public:
void setFloat(T a) { m_value = a; }
T value() const { return m_value; }
// TreeNode
size_t size() const override { return sizeof(FloatNode<T>); }
const char * description() const override { return "Float"; }
// Properties
Type type() const override { return Type::Float; }
// Layout
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
assert(false);
return 0;
}
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
assert(false);
return nullptr;
}
/* Evaluation */
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
private:
template<typename U> EvaluationReference<U> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const {
return ComplexReference<U>((U)m_value);
}
T m_value;
};
template<typename T>
class FloatReference : public NumberReference {
public:
FloatReference(T value) : NumberReference() {
TreeNode * node = TreePool::sharedPool()->createTreeNode<RationalNode>();
m_identifier = node->identifier();
if (!node->isAllocationFailure()) {
static_cast<FloatNode<T> *>(node)->setFloat(value);
}
}
};
}
#endif

View File

@@ -11,7 +11,6 @@ class Floor : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
@@ -20,13 +19,13 @@ private:
}
const char * name() const { return "floor"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit, computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -11,7 +11,6 @@ class FracPart : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,13 +21,13 @@ private:
}
const char * name() const { return "frac"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit, computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -15,24 +15,19 @@ class Integer;
class GlobalContext : public Context {
public:
GlobalContext();
~GlobalContext();
GlobalContext(const GlobalContext& other) = delete;
GlobalContext(GlobalContext&& other) = delete;
GlobalContext& operator=(const GlobalContext& other) = delete;
GlobalContext& operator=(GlobalContext&& other) = delete;
/* The expression recorded in global context is already a expression.
* Otherwise, we would need the context and the angle unit to evaluate it */
const Expression * expressionForSymbol(const Symbol * symbol) override;
LayoutRef layoutForSymbol(const Symbol * symbol, int numberOfSignificantDigits);
void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) override;
const ExpressionReference expressionForSymbol(const SymbolReference symbol) override;
LayoutRef layoutForSymbol(const SymbolReference symbol, int numberOfSignificantDigits);
void setExpressionForSymbolName(const ExpressionReference expression, const SymbolReference symbol, Context & context) override;
static constexpr uint16_t k_maxNumberOfScalarExpressions = 26;
static constexpr uint16_t k_maxNumberOfListExpressions = 10;
static constexpr uint16_t k_maxNumberOfMatrixExpressions = 10;
private:
static Decimal * defaultExpression();
int symbolIndex(const Symbol * symbol) const;
Expression * m_expressions[k_maxNumberOfScalarExpressions];
Matrix * m_matrixExpressions[k_maxNumberOfMatrixExpressions];
ExpressionReference m_expressions[k_maxNumberOfScalarExpressions];
MatrixReference m_matrixExpressions[k_maxNumberOfMatrixExpressions];
/* Matrix layout memoization */
LayoutRef m_matrixLayouts[k_maxNumberOfMatrixExpressions];
Approximation<double> m_pi;

View File

@@ -11,7 +11,6 @@ class GreatCommonDivisor : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,11 +21,11 @@ private:
}
const char * name() const { return "gcd"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -11,7 +11,6 @@ class HyperbolicArcCosine : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,13 +21,13 @@ private:
}
const char * name() const { return "acosh"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -11,7 +11,6 @@ class HyperbolicArcSine : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,13 +21,13 @@ private:
}
const char * name() const { return "asinh"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -11,7 +11,6 @@ class HyperbolicArcTangent : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,13 +21,13 @@ private:
}
const char * name() const { return "atanh"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -11,7 +11,6 @@ class HyperbolicCosine : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
private:
/* Layout */
@@ -23,12 +22,12 @@ private:
}
const char * name() const { return "cosh"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -11,7 +11,6 @@ class HyperbolicSine : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
private:
/* Layout */
@@ -23,12 +22,12 @@ private:
}
const char * name() const { return "sinh"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -11,7 +11,6 @@ class HyperbolicTangent : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
private:
/* Layout */
@@ -23,12 +22,12 @@ private:
}
const char * name() const { return "tanh"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -11,7 +11,6 @@ class ImaginaryPart : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,13 +21,13 @@ private:
}
const char * name() const { return "im"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -0,0 +1,49 @@
#ifndef POINCARE_INFINITY_H
#define POINCARE_INFINITY_H
#include <poincare/number.h>
namespace Poincare {
class InfinityNode : public NumberNode {
public:
void setNegative(bool negative) { m_negative = negative; }
// TreeNode
size_t size() const override { return sizeof(InfinityNode); }
const char * description() const override { return "Infinity"; }
// Properties
Type type() const override { return Type::Infinity; }
Sign sign() const override { return m_negative ? Sign::Negative : Sign::Positive; }
// Approximation
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return templatedApproximate<float>();
}
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return templatedApproximate<double>();
}
// Layout
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override;
private:
template<typename T> EvaluationReference<T> templatedApproximate() const;
bool m_negative;
};
class InfinityReference : public NumberReference {
public:
InfinityReference(bool negative) {
TreeNode * node = TreePool::sharedPool()->createTreeNode<InfinityNode>();
m_identifier = node->identifier();
if (!node->isAllocationFailure()) {
static_cast<InfinityNode *>(node)->setNegative(negative);
}
}
};
}
#endif

View File

@@ -3,54 +3,33 @@
#include <stdint.h>
#include <assert.h>
#include <poincare/number.h>
#include <poincare/complex.h>
namespace Poincare {
class ExpressionLayout;
class LayoutReference;
class LayoutNode;
class IntegerReference;
struct IntegerDivisionReference;
typedef uint16_t half_native_uint_t;
typedef int32_t native_int_t;
typedef int64_t double_native_int_t;
typedef uint32_t native_uint_t;
typedef uint64_t double_native_uint_t;
/* All algorithm should be improved with:
* Modern Computer Arithmetic, Richard P. Brent and Paul Zimmermann */
struct IntegerDivision;
class Integer {
class NaturalIntegerAbstract {
friend class IntegerReference;
friend class RationalReference;
public:
typedef uint16_t half_native_uint_t;
typedef int32_t native_int_t;
typedef int64_t double_native_int_t;
typedef uint32_t native_uint_t;
typedef uint64_t double_native_uint_t;
// FIXME: This constructor should be constexpr
Integer(native_int_t i = 0) :
m_digit(i>0 ? i : -i),
m_numberOfDigits(1),
m_negative(i<0)
{
}
Integer(double_native_int_t i);
Integer(const char * digits, bool negative = false); // Digits are NOT NULL-terminated
static Integer exponent(int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative);
static Integer numerator(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative, Integer * exponent);
static Integer denominator(Integer * exponent);
~Integer();
Integer(Integer&& other); // C++11 move constructor
Integer& operator=(Integer&& other); // C++11 move assignment operator
Integer(const Integer& other); // C++11 copy constructor
Integer& operator=(const Integer& other); // C++11 copy assignment operator
// Getter & Setter
bool isNegative() const { return m_negative; }
void setNegative(bool negative);
int extractedInt() const { assert(m_numberOfDigits == 1 && m_digit <= k_maxExtractableInteger); return m_negative ? -m_digit : m_digit; }
// Comparison
static int NaturalOrder(const Integer & i, const Integer & j);
bool isEqualTo(const Integer & other) const;
bool isLowerThan(const Integer & other) const;
// Getters
uint32_t digit(int i) const { assert(i < m_numberOfDigits); return digits()[i]; }
size_t numberOfDigits() const { return m_numberOfDigits; }
// Layout
int writeTextInBuffer(char * buffer, int bufferSize) const;
@@ -59,36 +38,38 @@ public:
// Approximation
template<typename T> T approximate() const;
// Arithmetic
static Integer Addition(const Integer & i, const Integer & j);
static Integer Subtraction(const Integer & i, const Integer & j);
static Integer Multiplication(const Integer & i, const Integer & j);
static Integer Factorial(const Integer & i);
static IntegerDivision Division(const Integer & numerator, const Integer & denominator);
static Integer Power(const Integer & i, const Integer & j);
static int numberOfDigitsWithoutSign(const Integer & i);
//static Integer Division(const Integer & i, const Integer & j);
//static IntegerDivision division(const Integer & i, const Integer & j);
bool isOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && !m_negative); };
bool isTwo() const { return (m_numberOfDigits == 1 && digit(0) == 2 && !m_negative); };
bool isTen() const { return (m_numberOfDigits == 1 && digit(0) == 10 && !m_negative); };
bool isMinusOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && m_negative); };
bool isZero() const { return (m_numberOfDigits == 1 && digit(0) == 0); };
constexpr static int k_maxExtractableInteger = 0x7FFFFFFF;
private:
Integer(const native_uint_t * digits, uint16_t numberOfDigits, bool negative);
static Integer IntegerWithHalfDigitAtIndex(half_native_uint_t halfDigit, int index);
// Properties
static int numberOfDigits(const NaturalIntegerAbstract * i);
virtual bool isOne() const { return (m_numberOfDigits == 1 && digit(0) == 1); };
virtual bool isTwo() const { return (m_numberOfDigits == 1 && digit(0) == 2); };
virtual bool isTen() const { return (m_numberOfDigits == 1 && digit(0) == 10); };
bool isZero() const { return (m_numberOfDigits == 0); };
bool isInfinity() const { return m_numberOfDigits > k_maxNumberOfDigits; }
bool isEven() const { return (m_numberOfDigits == 0 || ((digit(0) & 1) == 0)); }
void releaseDynamicIvars();
static int8_t ucmp(const Integer & a, const Integer & b); // -1, 0, or 1
static Integer usum(const Integer & a, const Integer & b, bool subtract, bool outputNegative);
static Integer addition(const Integer & a, const Integer & b, bool inverseBNegative);
static IntegerDivision udiv(const Integer & a, const Integer & b);
bool usesImmediateDigit() const { return m_numberOfDigits == 1; }
native_uint_t digit(int i) const {
assert(i >= 0 && i < m_numberOfDigits);
return (usesImmediateDigit() ? m_digit : m_digits[i]);
// Arithmetic
/* buffer has to be k_maxNumberOfDigits+1 to allow ...*/
static int8_t ucmp(const NaturalIntegerAbstract * a, const NaturalIntegerAbstract * b); // -1, 0, or 1
static IntegerReference usum(const NaturalIntegerAbstract * a, const NaturalIntegerAbstract * b, bool subtract);
static IntegerReference umult(const NaturalIntegerAbstract * a, const NaturalIntegerAbstract * b);
static IntegerDivisionReference udiv(const NaturalIntegerAbstract * a, const NaturalIntegerAbstract * b);
static IntegerReference upow(const NaturalIntegerAbstract * a, const NaturalIntegerAbstract * b);
static IntegerReference ufact(const NaturalIntegerAbstract * a);
constexpr static int k_maxNumberOfDigits = 11;
protected:
constexpr static int k_maxNumberOfDigitsBase10 = 105; // (2^32)^k_maxNumberOfDigits-1 ~ 10^105
NaturalIntegerAbstract(size_t numberOfDigits = 0) :
m_numberOfDigits(numberOfDigits)
{
}
virtual native_uint_t * digits() const = 0;
virtual void setDigitAtIndex(native_uint_t digit, int index) = 0;
size_t m_numberOfDigits; // In base native_uint_max
private:
static IntegerReference IntegerWithHalfDigitAtIndex(half_native_uint_t halfDigit, int index);
uint16_t numberOfHalfDigits() const {
native_uint_t d = digit(m_numberOfDigits-1);
native_uint_t halfBase = 1 << (8*sizeof(half_native_uint_t));
@@ -99,23 +80,128 @@ private:
if (i >= numberOfHalfDigits()) {
return 0;
}
return (usesImmediateDigit() ? ((half_native_uint_t *)&m_digit)[i] : ((half_native_uint_t *)m_digits)[i]);
return ((half_native_uint_t *)digits())[i];
}
// Small integer optimization. Similar to short string optimization.
union {
const native_uint_t * m_digits; // Little-endian
native_uint_t m_digit;
};
uint16_t m_numberOfDigits; // In base native_uint_max
bool m_negative; // Make sure zero cannot be negative
static_assert(sizeof(native_int_t) <= sizeof(native_uint_t), "native_uint_t should be able to contain native_int_t data");
static_assert(sizeof(double_native_int_t) <= sizeof(double_native_uint_t), "double_native_int_t type has not the right size compared to double_native_uint_t");
static_assert(sizeof(native_int_t) == sizeof(native_uint_t), "native_int_t type has not the right size compared to native_uint_t");
static_assert(sizeof(double_native_uint_t) == 2*sizeof(native_uint_t), "double_native_uint_t should be twice the size of native_uint_t");
static_assert(sizeof(double_native_int_t) == 2*sizeof(native_int_t), "double_native_int_t type has not the right size compared to native_int_t");
};
struct IntegerDivision {
Integer quotient;
Integer remainder;
class NaturalIntegerPointer : public NaturalIntegerAbstract {
public:
NaturalIntegerPointer(native_uint_t * buffer, size_t size);
private:
native_uint_t * digits() const override { return m_digits; }
void setDigitAtIndex(native_uint_t digit, int index) override { assert(index < m_numberOfDigits); m_digits[index] = digit; }
native_uint_t * m_digits;
};
class IntegerNode : public NumberNode, public NaturalIntegerAbstract {
public:
IntegerNode() :
NaturalIntegerAbstract(),
m_negative(false) {}
void setDigits(native_int_t i);
void setDigits(double_native_int_t i);
void setDigits(const native_uint_t * digits, size_t size, bool negative);
// Getters
native_uint_t * digits() const override { return (native_uint_t *)m_digits; }
// ExpressionNode
Type type() const override { return Type::Integer; }
// Simplification
ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
// Approximation
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference<float>(templatedApproximate<float>()); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference<double>(templatedApproximate<double>()); }
template<typename T> T templatedApproximate() const;
// Layout
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override;
// TreeNode
size_t size() const override;
const char * description() const override { return "Integer"; }
// ExpressionNode
Sign sign() const override { return m_negative ? Sign::Negative : Sign::Positive; }
ExpressionReference setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override;
void setNegative(bool negative);
// Comparison
static int NaturalOrder(const IntegerNode * i, const IntegerNode * j);
int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override { return NaturalOrder(this, static_cast<const IntegerNode *>(e)); }
// Properties
bool isOne() const override { return (NaturalIntegerAbstract::isOne() && !m_negative); };
bool isTwo() const override { return (NaturalIntegerAbstract::isTwo() && !m_negative); };
bool isTen() const override{ return (NaturalIntegerAbstract::isTen() && !m_negative); };
bool isMinusOne() const { return (NaturalIntegerAbstract::isOne() && m_negative); };
private:
void setDigitAtIndex(native_uint_t digit, int index) override { m_digits[index] = digit; }
bool m_negative; // Make sure zero cannot be negative
native_uint_t m_digits[0];
};
class IntegerReference : public NumberReference {
friend class NaturalIntegerAbstract;
friend class NaturalIntegerPointer;
friend class IntegerNode;
friend class RationalReference;
public:
IntegerReference(TreeNode * n) : NumberReference(n) {}
IntegerReference(const char * digits, size_t length, bool negative);
IntegerReference(const NaturalIntegerAbstract * naturalInteger);
IntegerReference(native_int_t i);
IntegerReference(double_native_int_t i);
static IntegerReference Overflow() { return IntegerReference((native_uint_t *)nullptr, IntegerNode::k_maxNumberOfDigits+1, false); }
// TreeNode
IntegerNode * typedNode() const { assert(node()->type() == ExpressionNode::Type::Integer); return static_cast<IntegerNode *>(node()); }
constexpr static int k_maxExtractableInteger = 0x7FFFFFFF;
int extractedInt() const;
// Comparison
static int NaturalOrder(const IntegerReference i, const IntegerReference j);
// Properties
bool isZero() const;
bool isOne() const;
bool isInfinity() const;
bool isEven() const;
bool isNegative() const { return node()->sign() == ExpressionNode::Sign::Negative; }
void setNegative(bool negative);
// Arithmetic
static IntegerReference Addition(const IntegerReference i, const IntegerReference j);
static IntegerReference Subtraction(const IntegerReference i, const IntegerReference j);
static IntegerReference Multiplication(const IntegerReference i, const IntegerReference j);
static IntegerDivisionReference Division(const IntegerReference numerator, const IntegerReference denominator);
static IntegerReference Power(const IntegerReference i, const IntegerReference j);
static IntegerReference Factorial(const IntegerReference i);
private:
IntegerReference(const native_uint_t * digits, size_t numberOfDigits, bool negative);
IntegerReference(size_t size) : NumberReference() {
TreeNode * node = TreePool::sharedPool()->createTreeNode<IntegerNode>(size);
m_identifier = node->identifier();
}
static IntegerReference addition(const IntegerReference a, const IntegerReference b, bool inverseBNegative);
size_t numberOfDigits() const { return typedNode()->numberOfDigits(); }
uint32_t digit(int i) const { return typedNode()->digit(i); }
};
struct IntegerDivisionReference {
IntegerReference quotient;
IntegerReference remainder;
};
}

View File

@@ -11,7 +11,6 @@ class Integral : public StaticHierarchy<3> {
using StaticHierarchy<3>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
int polynomialDegree(char symbolName) const override;
private:
/* Layout */
@@ -20,11 +19,11 @@ private:
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "int");
}
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
template<typename T>
struct DetailedResult
{

View File

@@ -1,7 +1,7 @@
#ifndef POINCARE_LAYOUT_ENGINE_H
#define POINCARE_LAYOUT_ENGINE_H
#include <poincare/expression.h>
#include <poincare/expression_reference.h>
#include <poincare/layout_reference.h>
namespace Poincare {
@@ -10,30 +10,14 @@ class LayoutEngine {
public:
/* Expression to Layout */
static LayoutRef createInfixLayout(const Expression * expression, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, const char * operatorName);
static LayoutRef createPrefixLayout(const Expression * expression, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, const char * operatorName);
static LayoutRef createInfixLayout(const ExpressionReference expression, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, const char * operatorName);
static LayoutRef createPrefixLayout(const ExpressionReference expression, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, const char * operatorName);
/* Create special layouts */
static LayoutRef createParenthesedLayout(LayoutRef layout, bool cloneLayout);
static LayoutRef createStringLayout(const char * buffer, int bufferSize, KDText::FontSize fontSize = KDText::FontSize::Large);
static LayoutRef createLogLayout(LayoutRef argument, LayoutRef index);
/* Expression to Text */
static int writeInfixExpressionTextInBuffer(
const Expression * expression,
char * buffer,
int bufferSize,
Preferences::PrintFloatMode floatDisplayMode,
int numberOfDigits,
const char * operatorName);
static int writePrefixExpressionTextInBuffer(
const Expression * expression,
char * buffer,
int bufferSize,
Preferences::PrintFloatMode floatDisplayMode,
int numberOfDigits,
const char * operatorName);
/* SerializableReference to Text */
static int writeInfixSerializableRefTextInBuffer(
const SerializableRef serializableRef,
@@ -58,11 +42,6 @@ public:
static int writeOneCharInBuffer(char * buffer, int bufferSize, char charToWrite);
private:
static constexpr char divideChar = '/';
// These two functions return the index of the null-terminating char.
static int writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, void * expressionLayout, char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfDigits, const char * operatorName, int firstChildIndex, int lastChildIndex);
static int writePrefixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, void * expressionLayout, char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfDigits, const char * operatorName, bool writeFirstChild = true);
static void writeChildTreeInBuffer(SerializableRef childRef, SerializableRef parentRef, char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfDigits, int * numberOfChar);
};

View File

@@ -11,7 +11,6 @@ class LeastCommonMultiple : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,11 +21,11 @@ private:
}
const char * name() const { return "lcm"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -12,7 +12,6 @@ class Logarithm : public BoundedStaticHierarchy<2> {
friend class NaperianLogarithm;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
@@ -20,16 +19,16 @@ private:
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "log");
}
/* Simplification */
Expression * shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
Expression * simpleShallowReduce(Context & context, Preferences::AngleUnit angleUnit);
Expression * shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override;
bool parentIsAPowerOfSameBase() const;
Expression * splitInteger(Integer i, bool isDenominator, Context & context, Preferences::AngleUnit angleUnit);
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -1,53 +1,72 @@
#ifndef POINCARE_MATRIX_H
#define POINCARE_MATRIX_H
#include <poincare/dynamic_hierarchy.h>
#include <poincare/expression_reference.h>
#include <poincare/matrix_data.h>
namespace Poincare {
class Multiplication;
class Matrix : public DynamicHierarchy {
template<typename T> friend class MatrixComplex;
class MatrixNode : public ExpressionNode {
public:
void setDimensions(int numberOfRows, int numberOfColumns) {
m_numberOfRows = numberOfRows;
m_numberOfColumns = m_numberOfColumns;
}
int numberOfRows() const { return m_numberOfRows; }
int numberOfColumns() const { return m_numberOfColumns; }
// TreeNode
size_t size() const override { return sizeof(MatrixNode); }
const char * description() const override { return "Matrix"; }
int numberOfChildren() const { return m_numberOfRows*m_numberOfColumns; }
// Properties
Type type() const override { return Type::Matrix; }
int polynomialDegree(char symbolName) const override;
// Approximation
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return templatedApproximate<float>();
}
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return templatedApproximate<double>();
}
// Layout
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override;
private:
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
class MatrixReference : public ExpressionReference {
template<typename T> friend class MatrixComplexNode;
friend class GlobalContext;
public:
Matrix(MatrixData * matrixData); // pilfer the operands of matrixData
Matrix(const Expression * const * operands, int numberOfRows, int numberOfColumns, bool cloneOperands = true);
Expression * matrixOperand(int i, int j) { return editableOperand(i*numberOfColumns()+j); }
MatrixNode * typedNode() const { assert(!isAllocationFailure()); return static_cast<MatrixNode *>(node()); }
int numberOfRows() const;
int numberOfColumns() const;
/* Expression */
Type type() const override;
Expression * clone() const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int polynomialDegree(char symbolName) const override;
ExpressionReference matrixChild(int i, int j) { assert(!isAllocationFailure()); return childAtIndex(i*numberOfColumns()+j); }
/* Operation on matrix */
int rank(Context & context, Preferences::AngleUnit angleUnit, bool inPlace);
// Inverse the array in-place. Array has to be given in the form array[row_index][column_index]
template<typename T> static int ArrayInverse(T * array, int numberOfRows, int numberOfColumns);
#if MATRIX_EXACT_REDUCING
//template<typename T> Expression * createTrace() const;
//template<typename T> Expression * createDeterminant() const;
Matrix * createTranspose() const;
static Matrix * createIdentity(int dim);
ExpressionReference trace() const;
ExpressionReference determinant() const;
MatrixReference transpose() const;
static MatrixReference createIdentity(int dim);
/* createInverse can be called on any matrix reduce or not, approximate or not. */
Expression * createInverse(Context & context, Preferences::AngleUnit angleUnit) const;
ExpressionReference inverse(Context & context, Preferences::AngleUnit angleUnit) const;
#endif
private:
/* rowCanonize turns a matrix in its reduced row echelon form. */
void rowCanonize(Context & context, Preferences::AngleUnit angleUnit, Multiplication * m = nullptr);
// Row canonize the array in place
template<typename T> static void ArrayRowCanonize(T * array, int numberOfRows, int numberOfColumns, T * c = nullptr);
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
int m_numberOfRows;
};
}

View File

@@ -0,0 +1,59 @@
#ifndef POINCARE_MATRIX_COMPLEX_H
#define POINCARE_MATRIX_COMPLEX_H
#include <poincare/evaluation.h>
#include <poincare/complex.h>
namespace Poincare {
template<typename T>
class MatrixComplexReference;
template<typename T>
class MatrixComplexNode : public EvaluationNode<T> {
public:
// TreeNode
size_t size() const override { return sizeof(MatrixComplexNode<T>); }
const char * description() const override { return "Evaluation matrix complex"; }
int numberOfChildren() const override { return m_numberOfRows*m_numberOfColumns; }
void setMatrixComplexDimension(int numberOfRows, int numberOfColumns);
typename Poincare::EvaluationNode<T>::Type type() const override { return Poincare::EvaluationNode<T>::Type::MatrixComplex; }
int numberOfComplexOperands() const { return m_numberOfRows*m_numberOfColumns; }
// WARNING: complexOperand may return a nullptr
ComplexNode<T> * childAtIndex(int index) const override;
int numberOfRows() const { return m_numberOfRows; }
int numberOfColumns() const { return m_numberOfColumns; }
bool isUndefined() const override;
ExpressionReference complexToExpression(Preferences::Preferences::ComplexFormat complexFormat) const override;
std::complex<T> trace() const override;
std::complex<T> determinant() const override;
EvaluationReference<T> inverse() const override;
EvaluationReference<T> transpose() const override;
private:
// TODO: find another solution for inverse and determinant (avoid capping the matrix)
static constexpr int k_maxNumberOfCoefficients = 100;
int m_numberOfRows;
int m_numberOfColumns;
};
template<typename T>
class MatrixComplexReference : public EvaluationReference<T> {
public:
MatrixComplexReference(TreeNode * t) : EvaluationReference<T>(t) {}
MatrixComplexReference(int numberOfRows, int numberOfColumns);
static MatrixComplexReference<T> Undefined() {
std::complex<T> undef = std::complex<T>(NAN, NAN);
return MatrixComplexReference<T>((std::complex<T> *)&undef, 1, 1);
}
static MatrixComplexReference<T> createIdentity(int dim);
int numberOfRows() const;
int numberOfColumns() const;
private:
MatrixComplexReference(std::complex<T> * operands, int numberOfRows, int numberOfColumns);
MatrixComplexNode<T> * node() const override{ return static_cast<MatrixComplexNode<T> *>(TreeReference::node()); }
};
}
#endif

View File

@@ -10,7 +10,6 @@ class MatrixDimension : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -21,11 +20,11 @@ private:
}
const char * name() const { return "dim"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -10,7 +10,6 @@ class MatrixInverse : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Evaluation */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -21,11 +20,11 @@ private:
}
const char * name() const { return "inverse"; }
/* Simplification */
Expression * shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -11,7 +11,6 @@ class MatrixTrace : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,11 +21,11 @@ private:
}
const char * name() const { return "trace"; }
/* Simplification */
Expression * shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -10,7 +10,6 @@ class MatrixTranspose : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -21,11 +20,11 @@ private:
}
const char * name() const { return "transpose"; }
/* Simplification */
Expression * shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -20,7 +20,6 @@ class Multiplication : public DynamicHierarchy {
friend class Complex<double>;
public:
Type type() const override;
Expression * clone() const override;
Sign sign() const override;
int polynomialDegree(char symbolName) const override;
int privateGetPolynomialCoefficients(char symbolName, Expression * coefficients[]) const override;
@@ -33,13 +32,13 @@ public:
template<typename T> static MatrixComplex<T> computeOnMatrices(const MatrixComplex<T> m, const MatrixComplex<T> n);
private:
/* Property */
Expression * setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override;
/* Layout */
bool needParenthesisWithParent(const Expression * e) const override;
bool needsParenthesisWithParent(SerializableNode * parentNode) const override;
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
Expression * privateShallowReduce(Context& context, Preferences::AngleUnit angleUnit, bool expand, bool canBeInterrupted);
void mergeMultiplicationOperands();
void factorizeBase(Expression * e1, Expression * e2, Context & context, Preferences::AngleUnit angleUnit);
@@ -62,10 +61,10 @@ private:
template<typename T> static MatrixComplex<T> computeOnMatrixAndComplex(const MatrixComplex<T> m, const std::complex<T> c) {
return ApproximationEngine::elementWiseOnMatrixComplexAndComplex(m, c, compute<T>);
}
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::mapReduce<float>(this, context, angleUnit, compute<float>, computeOnComplexAndMatrix<float>, computeOnMatrixAndComplex<float>, computeOnMatrices<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::mapReduce<double>(this, context, angleUnit, compute<double>, computeOnComplexAndMatrix<double>, computeOnMatrixAndComplex<double>, computeOnMatrices<double>);
}
};

View File

@@ -0,0 +1,28 @@
#ifndef POINCARE_NARY_EXPRESSION_NODE_H
#define POINCARE_NARY_EXPRESSION_NODE_H
#include <poincare/expression_reference.h>
namespace Poincare {
class NAryExpressionNode : public ExpressionNode { // TODO: VariableArityExpressionNode?
public:
int numberOfChildren() const override { return m_numberOfChildren; }
// Comparison
typedef int (*ExpressionOrder)(const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted);
// Commutative properties
void sortOperands(ExpressionOrder order, bool canBeInterrupted);
ExpressionReference squashUnaryHierarchy();
protected:
int m_numberOfChildren;
private:
int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override;
int simplificationOrderGreaterType(const ExpressionNode * e, bool canBeInterrupted) const override;
};
}
#endif

View File

@@ -11,7 +11,6 @@ class NaperianLogarithm : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,13 +21,13 @@ private:
}
const char * name() const { return "ln"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -10,7 +10,6 @@ class NthRoot : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
@@ -18,11 +17,11 @@ private:
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "root");
}
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};

View File

@@ -0,0 +1,50 @@
#ifndef POINCARE_NUMBER_H
#define POINCARE_NUMBER_H
#include <poincare/expression_reference.h>
namespace Poincare {
/* Number class has 3 subclasses:
* - Undefined
* - Integer
* - Rational
* - Float
* - Decimal
* - Infinite
*/
class IntegerReference;
class RationalReference;
class NumberNode : public ExpressionNode {
public:
bool isNumber() const override { return true; }
int numberOfChildren() const override { return 0; }
double doubleApproximation() const;
};
class NumberReference : public ExpressionReference {
public:
using ExpressionReference::ExpressionReference;
NumberNode * numberNode() const { assert(!isAllocationFailure()); return static_cast<NumberNode *>(node()); }
/* Return either a IntegerReference, a DecimalReference or an InfiniteReference. */
static NumberReference Integer(const char * digits, size_t length, bool negative);
/* This set of Functions return either a RationalReference or a FloatReference
* or InfiniteReference in case of overflow. DecimalReference are not taken into
* account as it is not an internal node - it will always be truned into a
* Rational/Float beforehand. */
static NumberReference Addition(const NumberReference i, const NumberReference j);
static NumberReference Multiplication(const NumberReference i, const NumberReference j);
static NumberReference Power(const NumberReference i, const NumberReference j);
private:
typedef IntegerReference (*IntegerBinaryOperation)(const IntegerReference, const IntegerReference);
typedef RationalReference (*RationalBinaryOperation)(const RationalReference, const RationalReference);
typedef double (*DoubleBinaryOperation)(double, double);
static NumberReference BinaryOperation(const NumberReference i, const NumberReference j, IntegerBinaryOperation integerOp, RationalBinaryOperation rationalOp, DoubleBinaryOperation doubleOp);
};
}
#endif

View File

@@ -1,34 +1,49 @@
#ifndef POINCARE_OPPOSITE_H
#define POINCARE_OPPOSITE_H
#include <poincare/static_hierarchy.h>
#include <poincare/layout_engine.h>
#include <poincare/expression_reference.h>
#include <poincare/approximation_engine.h>
namespace Poincare {
class Opposite : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
class OppositeNode : public ExpressionNode {
public:
Expression * clone() const override;
Type type() const override;
// TreeNode
size_t size() const override { return sizeof(OppositeNode); }
const char * description() const override { return "Opposite"; }
int numberOfChildren() const override { return 0; }
// Properties
Type type() const override { return Type::Opposite; }
int polynomialDegree(char symbolName) const override;
Sign sign() const override;
template<typename T> static std::complex<T> compute(const std::complex<T> c, Preferences::AngleUnit angleUnit);
private:
/* Layout */
bool needParenthesisWithParent(const Expression * e) const override;
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
// Approximation
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit, compute<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, compute<double>);
}
// Layout
bool needsParenthesisWithParent(SerializableNode * parentNode) const override;
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override;
// Simplification
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
private:
template<typename T> static ComplexReference<T> compute(const std::complex<T> c, Preferences::AngleUnit angleUnit) { return ComplexReference<T>(-c); }
};
class OppositeReference : public ExpressionReference {
public:
OppositeReference(ExpressionReference operand) {
TreeNode * node = TreePool::sharedPool()->createTreeNode<OppositeNode>();
m_identifier = node->identifier();
}
};
}

View File

@@ -1,31 +1,44 @@
#ifndef POINCARE_PARENTHESIS_H
#define POINCARE_PARENTHESIS_H
#include <poincare/static_hierarchy.h>
#include <poincare/expression_reference.h>
#include <poincare/layout_engine.h>
namespace Poincare {
class Parenthesis : public StaticHierarchy<1> {
class ParenthesisNode : public ExpressionNode {
public:
using StaticHierarchy<1>::StaticHierarchy;
public:
Expression * clone() const override;
Type type() const override;
// TreeNode
size_t size() const override { return sizeof(ParenthesisNode); }
const char * description() const override { return "Parenthesis"; }
int numberOfChildren() const override { return 1; }
// Properties
Type type() const override { return Type::Parenthesis; }
int polynomialDegree(char symbolName) const override;
private:
/* Layout */
// Layout
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "");
return LayoutEngine::writePrefixSerializableRefTextInBuffer(ExpressionReference(this), buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "");
}
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
// Simplification
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
// Approximation
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
private:
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
class ParenthesisReference : public ExpressionReference {
public:
ParenthesisReference(ExpressionReference exp) {
TreeNode * node = TreePool::sharedPool()->createTreeNode<ParenthesisNode>();
m_identifier = node->identifier();
addChildTreeAtIndex(exp, 0, 0);
}
};
}

View File

@@ -11,7 +11,6 @@ class PermuteCoefficient : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
constexpr static int k_maxNValue = 100;
/* Layout */
@@ -23,11 +22,11 @@ private:
}
const char * name() const { return "permute"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -20,7 +20,6 @@ class Power : public StaticHierarchy<2> {
friend class Symbol;
public:
Type type() const override;
Expression * clone() const override;
Sign sign() const override;
int polynomialDegree(char symbolName) const override;
int privateGetPolynomialCoefficients(char symbolName, Expression * coefficients[]) const override;
@@ -29,19 +28,19 @@ private:
constexpr static int k_maxNumberOfTermsInExpandedMultinome = 25;
constexpr static int k_maxExactPowerMatrix = 100;
/* Property */
Expression * setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override;
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
bool needParenthesisWithParent(const Expression * e) const override;
bool needsParenthesisWithParent(SerializableNode * parentNode) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, name());
}
static const char * name() { return "^"; }
/* Simplify */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
Expression * shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override;
int simplificationOrderGreaterType(const Expression * e, bool canBeInterrupted) const override;
int simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const override;
int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override;
Expression * simplifyPowerPower(Power * p, Expression * r, Context & context, Preferences::AngleUnit angleUnit);
Expression * cloneDenominator(Context & context, Preferences::AngleUnit angleUnit) const override;
Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, Preferences::AngleUnit angleUnit);
@@ -60,10 +59,10 @@ private:
template<typename T> static MatrixComplex<T> computeOnComplexAndMatrix(const std::complex<T> c, const MatrixComplex<T> n);
template<typename T> static MatrixComplex<T> computeOnMatrixAndComplex(const MatrixComplex<T> m, const std::complex<T> d);
template<typename T> static MatrixComplex<T> computeOnMatrices(const MatrixComplex<T> m, const MatrixComplex<T> n);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::mapReduce<float>(this, context, angleUnit, compute<float>, computeOnComplexAndMatrix<float>, computeOnMatrixAndComplex<float>, computeOnMatrices<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::mapReduce<double>(this, context, angleUnit, compute<double>, computeOnComplexAndMatrix<double>, computeOnMatrixAndComplex<double>, computeOnMatrices<double>);
}
};

View File

@@ -10,7 +10,6 @@ class PredictionInterval : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
int polynomialDegree(char symbolName) const override;
private:
/* Layout */
@@ -22,11 +21,11 @@ private:
}
const char * name() const { return "prediction95"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(Expression::SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<float> approximate(Expression::SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(Expression::DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -9,18 +9,17 @@ class Product : public Sequence {
using Sequence::Sequence;
public:
Type type() const override;
Expression * clone() const override;
private:
const char * name() const override;
int emptySequenceValue() const override;
LayoutRef createSequenceLayout(LayoutRef argumentLayout, LayoutRef subscriptLayout, LayoutRef superscriptLayout) const override;
Evaluation<double> * evaluateWithNextTerm(DoublePrecision p, Evaluation<double> * a, Evaluation<double> * b) const override {
EvaluationReference<double> evaluateWithNextTerm(DoublePrecision p, Evaluation<double> * a, Evaluation<double> * b) const override {
return templatedApproximateWithNextTerm<double>(a, b);
}
Evaluation<float> * evaluateWithNextTerm(SinglePrecision p, Evaluation<float> * a, Evaluation<float> * b) const override {
EvaluationReference<float> evaluateWithNextTerm(SinglePrecision p, Evaluation<float> * a, Evaluation<float> * b) const override {
return templatedApproximateWithNextTerm<float>(a, b);
}
template<typename T> Evaluation<T> * templatedApproximateWithNextTerm(Evaluation<T> * a, Evaluation<T> * b) const;
template<typename T> EvaluationReference<T> templatedApproximateWithNextTerm(Evaluation<T> * a, Evaluation<T> * b) const;
};
}

View File

@@ -10,7 +10,6 @@ class Randint : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -21,13 +20,13 @@ private:
}
const char * name() const { return "randint"; }
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return templateApproximate<float>(context, angleUnit);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return templateApproximate<double>(context, angleUnit);
}
template <typename T> Evaluation<T> * templateApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
template <typename T> EvaluationReference<T> templateApproximate()Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -11,11 +11,10 @@ class Random : public StaticHierarchy<0> {
using StaticHierarchy<0>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
Sign sign() const override { return Sign::Positive; }
template<typename T> static T random();
private:
Expression * setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override;
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, numberOfSignificantDigits, name());
@@ -25,13 +24,13 @@ private:
}
const char * name() const { return "random"; }
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return templateApproximate<float>();
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return templateApproximate<double>();
}
template <typename T> Evaluation<T> * templateApproximate() const {
template <typename T> EvaluationReference<T> templateApproximate()) const {
return new Complex<T>(random<T>());
}
};

View File

@@ -2,63 +2,90 @@
#define POINCARE_RATIONAL_H
#include <poincare/integer.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation.h>
namespace Poincare {
class Rational : public StaticHierarchy<0> {
friend class Power;
friend class Multiplication;
class RationalNode : public NumberNode {
public:
/* The constructor build a irreductible fraction whose sign is on numerator */
Rational(const Integer numerator, const Integer denominator);
Rational(const Integer numerator);
Rational(Integer::native_int_t i) : Rational(Integer(i)) {}
Rational(Integer::native_int_t i, Integer::native_int_t j) : Rational(Integer(i), Integer(j)) {}
void setDigits(native_uint_t * i, size_t numeratorSize, native_uint_t * j, size_t denominatorSize, bool negative);
NaturalIntegerPointer numerator() const;
NaturalIntegerPointer denominator() const;
// TreeNode
size_t size() const override;
const char * description() const override { return "Rational"; }
// Serialization Node
bool needsParenthesisWithParent(SerializableNode * e) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
Rational(const Rational & other);
Rational & operator=(const Rational & other);
// Getter
const Integer numerator() const;
const Integer denominator() const;
// Expression subclassing
Type type() const override;
Expression * clone() const override;
Type type() const override { return Type::Rational; }
Sign sign() const override;
Expression * cloneDenominator(Context & context, Preferences::AngleUnit angleUnit) const override;
void setSign(Sign s);
// Layout
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
// Approximation
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference<float>(templatedApproximate<float>()); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference<double>(templatedApproximate<double>()); }
template<typename T> T templatedApproximate() const;
// Basic test
bool isZero() const { return m_numerator.isZero(); }
bool isOne() const { return m_numerator.isOne() && m_denominator.isOne(); }
bool isMinusOne() const { return m_numerator.isMinusOne() && m_denominator.isOne(); }
bool isHalf() const { return m_numerator.isOne() && m_denominator.isTwo(); }
bool isMinusHalf() const { return m_numerator.isMinusOne() && m_denominator.isTwo(); }
bool isTen() const { return m_numerator.isTen() && m_denominator.isOne(); }
bool isZero() const { return numerator().isZero(); }
bool isOne() const { return numerator().isOne() && denominator().isOne() && !m_negative; }
bool isMinusOne() const { return numerator().isOne() && denominator().isOne() && m_negative; }
bool isHalf() const { return numerator().isOne() && denominator().isTwo() && !m_negative; }
bool isMinusHalf() const { return numerator().isOne() && denominator().isTwo() && m_negative; }
bool isTen() const { return numerator().isTen() && denominator().isOne() && !m_negative; }
static int NaturalOrder(const RationalNode i, const RationalNode j);
private:
int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override;
ExpressionReference shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override;
ExpressionReference setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override {
setSign(s);
return ExpressionReference(this);
}
ExpressionReference cloneDenominator(Context & context, Preferences::AngleUnit angleUnit) const override;
bool m_negative;
size_t m_numberOfDigitsNumerator;
size_t m_numberOfDigitsDenominator;
native_uint_t m_digits[0];
};
class RationalReference : public NumberReference {
public:
/* The constructor build a irreductible fraction */
RationalReference(IntegerReference numerator, IntegerReference denominator);
RationalReference(const IntegerReference numerator);
RationalReference(const NaturalIntegerAbstract * numerator, bool negative);
RationalReference(native_int_t i);
RationalReference(native_int_t i, native_int_t j);
// TreeNode
RationalNode * typedNode() const { assert(node()->type() == ExpressionNode::Type::Rational); return static_cast<RationalNode *>(node()); }
// Properties
bool isOne() const;
bool numeratorOrDenominatorIsInfinity() const;
// Arithmetic
static Rational Addition(const Rational & i, const Rational & j);
static Rational Multiplication(const Rational & i, const Rational & j);
static Rational Power(const Rational & i, const Integer & j);
static int NaturalOrder(const Rational & i, const Rational & j);
/* Warning: when using this function, always assert that the result does not
* involve infinity numerator or denominator or handle these cases. */
static RationalReference Addition(const RationalReference i, const RationalReference j);
static RationalReference Multiplication(const RationalReference i, const RationalReference j);
// IntegerPower of (p1/q1)^(p2/q2) --> (p1^p2)/(q1^p2)
static RationalReference IntegerPower(const RationalReference i, const RationalReference j);
static int NaturalOrder(const RationalReference i, const RationalReference j);
private:
bool needParenthesisWithParent(const Expression * e) const override;
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename U> Complex<U> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
Expression * shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override;
Expression * setSign(Sign s);
Expression * setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override {
return setSign(s);
RationalReference(size_t size) : NumberReference() {
TreeNode * node = TreePool::sharedPool()->createTreeNode<RationalNode>(size);
m_identifier = node->identifier();
}
/* Sorting */
int simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const override;
Integer m_numerator;
Integer m_denominator;
};
}

View File

@@ -11,7 +11,6 @@ class RealPart : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,13 +21,13 @@ private:
}
const char * name() const { return "re"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -11,7 +11,6 @@ class Round : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
@@ -22,11 +21,11 @@ private:
}
const char * name() const { return "round"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Complex */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
};
}

View File

@@ -17,12 +17,12 @@ private:
virtual LayoutRef createSequenceLayout(LayoutRef subscriptLayout, LayoutRef superscriptLayout, LayoutRef argumentLayout) const = 0;
virtual const char * name() const = 0;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
virtual int emptySequenceValue() const = 0;
virtual Evaluation<float> * evaluateWithNextTerm(SinglePrecision p, Evaluation<float> * a, Evaluation<float> * b) const = 0;
virtual Evaluation<double> * evaluateWithNextTerm(DoublePrecision p, Evaluation<double> * a, Evaluation<double> * b) const = 0;
virtual EvaluationReference<float> evaluateWithNextTerm(SinglePrecision p, Evaluation<float> * a, Evaluation<float> * b) const = 0;
virtual EvaluationReference<double> evaluateWithNextTerm(DoublePrecision p, Evaluation<double> * a, Evaluation<double> * b) const = 0;
};
}

View File

@@ -9,7 +9,7 @@ namespace Poincare {
class SerializableNode : public TreeNode {
public:
using TreeNode::TreeNode;
virtual bool needsParenthesisWithParent(SerializableNode * parentNode) { return false; } //TODO
virtual bool needsParenthesisWithParent(SerializableNode * parentNode) const { return false; } //TODO
virtual int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const = 0;
};

View File

@@ -17,23 +17,22 @@ public:
/* We don't want to clone the expression provided at construction.
* So we don't want it to be deleted when we're destroyed (parent destructor). */
}
Expression * clone() const override { return nullptr; }
int polynomialDegree(char symbolName) const override { return -1; }
Type type() const override { return Expression::Type::SimplificationRoot; }
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
return nullptr;
}
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { return 0; }
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
assert(false);
return nullptr;
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
assert(false);
return nullptr;
}
private:
Expression * shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override { return this; }
ExpressionReference shallowReduce(Context & context, Preferences::AngleUnit angleUnit) override { return this; }
};
}

View File

@@ -14,7 +14,6 @@ class Sine : public StaticHierarchy<1> {
float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override;
public:
Type type() const override;
Expression * clone() const override;
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian);
private:
/* Layout */
@@ -26,12 +25,12 @@ private:
}
const char * name() const { return "sin"; }
/* Simplication */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -11,19 +11,18 @@ class SquareRoot : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
private:
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}

View File

@@ -25,7 +25,7 @@ public:
virtual bool hasValidNumberOfOperands(int numberOfOperands) const;
protected:
void build(const Expression * const * operands, int numberOfOperands, bool cloneOperands);
int simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const override;
int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override;
const Expression * m_operands[T];
};

View File

@@ -13,18 +13,17 @@ class Store : public StaticHierarchy<2> {
public:
using StaticHierarchy<2>::StaticHierarchy;
Type type() const override;
Expression * clone() const override;
int polynomialDegree(char symbolName) const override;
private:
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
/* Evalutation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
const Symbol * symbol() const { return static_cast<const Symbol *>(operand(1)); }
const Expression * value() const { return operand(0); }

View File

@@ -11,12 +11,11 @@ class Subtraction : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
template<typename T> static std::complex<T> compute(const std::complex<T> c, const std::complex<T> d);
int polynomialDegree(char symbolName) const override;
private:
/* Layout */
bool needParenthesisWithParent(const Expression * e) const override;
bool needsParenthesisWithParent(SerializableNode * parentNode) const override;
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
return LayoutEngine::createInfixLayout(this, floatDisplayMode, numberOfSignificantDigits, name());
}
@@ -25,7 +24,7 @@ private:
}
static const char * name() { return "-"; }
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static MatrixComplex<T> computeOnMatrixAndComplex(const MatrixComplex<T> m, const std::complex<T> c) {
return ApproximationEngine::elementWiseOnMatrixComplexAndComplex(m, c, compute<T>);
@@ -35,10 +34,10 @@ private:
return ApproximationEngine::elementWiseOnComplexMatrices(m, n, compute<T>);
}
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::mapReduce<float>(this, context, angleUnit, compute<float>, computeOnComplexAndMatrix<float>, computeOnMatrixAndComplex<float>, computeOnMatrices<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::mapReduce<double>(this, context, angleUnit, compute<double>, computeOnComplexAndMatrix<double>, computeOnMatrixAndComplex<double>, computeOnMatrices<double>);
}
};

View File

@@ -9,18 +9,17 @@ class Sum : public Sequence {
using Sequence::Sequence;
public:
Type type() const override;
Expression * clone() const override;
private:
const char * name() const override;
int emptySequenceValue() const override;
LayoutRef createSequenceLayout(LayoutRef argumentLayout, LayoutRef subscriptLayout, LayoutRef superscriptLayout) const override;
Evaluation<double> * evaluateWithNextTerm(DoublePrecision p, Evaluation<double> * a, Evaluation<double> * b) const override {
EvaluationReference<double> evaluateWithNextTerm(DoublePrecision p, Evaluation<double> * a, Evaluation<double> * b) const override {
return templatedApproximateWithNextTerm<double>(a, b);
}
Evaluation<float> * evaluateWithNextTerm(SinglePrecision p, Evaluation<float> * a, Evaluation<float> * b) const override {
EvaluationReference<float> evaluateWithNextTerm(SinglePrecision p, Evaluation<float> * a, Evaluation<float> * b) const override {
return templatedApproximateWithNextTerm<float>(a, b);
}
template<typename T> Evaluation<T> * templatedApproximateWithNextTerm(Evaluation<T> * a, Evaluation<T> * b) const;
template<typename T> EvaluationReference<T> templatedApproximateWithNextTerm(Evaluation<T> * a, Evaluation<T> * b) const;
};
}

View File

@@ -1,12 +1,52 @@
#ifndef POINCARE_SYMBOL_H
#define POINCARE_SYMBOL_H
#include <poincare/static_hierarchy.h>
#include <poincare/expression_reference.h>
namespace Poincare {
class Symbol : public StaticHierarchy<0> {
class SymbolNode : public ExpressionNode {
friend class Store;
public:
void setName(const char name) { m_name = name; }
char name() const { return m_name; }
// TreeNode
size_t size() const override { return sizeof(SymbolNode); }
const char * description() const override { return "Symbol"; }
int numberOfChildren() const override { return 0; }
// Expression Properties
Type type() const override { return Type::Symbol; }
Sign sign() const override;
ExpressionReference replaceSymbolWithExpression(char symbol, ExpressionReference expression) override;
int polynomialDegree(char symbolName) const override;
int getPolynomialCoefficients(char symbolName, ExpressionReference coefficients[]) const override;
int getVariables(isVariableTest isVariable, char * variables) const override;
float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override;
/* Comparison */
int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override;
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
/* Simplification */
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Approximation */
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
private:
bool hasAnExactRepresentation(Context & context) const;
template<typename T> EvaluationReference<T> templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
char m_name;
};
class SymbolReference : public ExpressionReference {
public:
enum SpecialSymbols : char {
/* We can use characters from 1 to 31 as they do not correspond to usual
@@ -41,40 +81,22 @@ public:
X3,
Y3 = 29
};
SymbolReference(const char name) {
TreeNode * node = TreePool::sharedPool()->createTreeNode<SymbolNode>();
m_identifier = node->identifier();
if (!node->isAllocationFailure()) {
static_cast<SymbolNode *>(node)->setName(name);
}
}
// Symbol properties
static const char * textForSpecialSymbols(char name);
static SpecialSymbols matrixSymbol(char index);
Symbol(char name);
Symbol(Symbol&& other); // C++11 move constructor
Symbol(const Symbol& other); // C++11 copy constructor
char name() const;
Type type() const override;
Expression * clone() const override;
int polynomialDegree(char symbolName) const override;
int privateGetPolynomialCoefficients(char symbolName, Expression * coefficients[]) const override;
Sign sign() const override;
bool isMatrixSymbol() const;
bool isScalarSymbol() const;
static bool isMatrixSymbol(char c);
static bool isScalarSymbol(char c);
static bool isVariableSymbol(char c);
static bool isSeriesSymbol(char c);
static bool isRegressionSymbol(char c);
bool isApproximate(Context & context) const;
float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override;
bool hasAnExactRepresentation(Context & context) const;
static const char * textForSpecialSymbols(char name);
int getVariables(isVariableTest isVariable, char * variables) const override;
private:
Expression * replaceSymbolWithExpression(char symbol, Expression * expression) override;
/* Simplification */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Comparison */
int simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const override;
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
const char m_name;
static bool isApproximate(char c, Context & context);
};
}

View File

@@ -12,7 +12,6 @@ class Tangent : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Type type() const override;
Expression * clone() const override;
float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override;
private:
/* Layout */
@@ -24,13 +23,13 @@ private:
}
const char * name() const { return "tan"; }
/* Simplication */
Expression * shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
ExpressionReference shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian);
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return ApproximationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -104,6 +104,8 @@ public:
}
}
void swapChildren(int i, int j);
protected:
TreeReference() : m_identifier(-1) {}
void setIdentifierAndRetain(int newId) {

View File

@@ -1,24 +1,41 @@
#ifndef POINCARE_UNDEFINED_H
#define POINCARE_UNDEFINED_H
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation.h>
#include <poincare/number.h>
namespace Poincare {
class Undefined : public StaticHierarchy<0> {
class UndefinedNode : public NumberNode {
public:
Type type() const override;
Expression * clone() const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
// TreeNode
size_t size() const override { return sizeof(UndefinedNode); }
const char * description() const override { return "Undefined"; }
// Properties
Type type() const override { return Type::Undefined; }
int polynomialDegree(char symbolName) const override;
private:
/* Layout */
// Approximation
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return templatedApproximate<float>();
}
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override {
return templatedApproximate<double>();
}
// Layout
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
/* Evaluation */
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, angleUnit); }
Evaluation<double> * privateApproximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override;
private:
template<typename T> EvaluationReference<T> templatedApproximate() const;
};
class UndefinedReference : public NumberReference {
public:
UndefinedReference() {
TreeNode * node = TreePool::sharedPool()->createTreeNode<UndefinedNode>();
m_identifier = node->identifier();
}
};
}

View File

@@ -27,7 +27,7 @@ LayoutRef AbsoluteValue::createLayout(Preferences::PrintFloatMode floatDisplayMo
return AbsoluteValueLayoutRef(operand(0)->createLayout(floatDisplayMode, numberOfSignificantDigits));
}
Expression * AbsoluteValue::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
ExpressionReference AbsoluteValue::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;

View File

@@ -35,7 +35,7 @@ int Addition::polynomialDegree(char symbolName) const {
return degree;
}
int Addition::privateGetPolynomialCoefficients(char symbolName, Expression * coefficients[]) const {
int Addition::getPolynomialCoefficients(char symbolName, ExpressionReference coefficients[]) const {
int deg = polynomialDegree(symbolName);
if (deg < 0 || deg > k_maxPolynomialDegree) {
return -1;
@@ -63,7 +63,7 @@ bool Addition::needParenthesisWithParent(const Expression * e) const {
/* Simplication */
Expression * Addition::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
ExpressionReference Addition::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;

View File

@@ -0,0 +1,12 @@
#include <poincare/allocation_failed_evaluation.h>
#include <poincare/expression_reference.h>
#include <poincare/undefined.h>
namespace Poincare {
template<typename T>
ExpressionReference AllocationFailedEvaluationNode<T>::complexToExpression(Preferences::Preferences::ComplexFormat complexFormat) const {
return UndefinedReference();
}
}

View File

@@ -25,101 +25,113 @@ template <typename T> std::complex<T> ApproximationEngine::truncateRealOrImagina
return c;
}
template<typename T> Evaluation<T> * ApproximationEngine::map(const Expression * expression, Context& context, Preferences::AngleUnit angleUnit, ComplexCompute<T> compute) {
assert(expression->numberOfOperands() == 1);
Evaluation<T> * input = expression->operand(0)->privateApproximate(T(), context, angleUnit);
Evaluation<T> * result = nullptr;
if (input->type() == Evaluation<T>::Type::Complex) {
Complex<T> * c = static_cast<Complex<T> *>(input);
result = new Complex<T>(compute(*c, angleUnit));
template<typename T> EvaluationReference<T> ApproximationEngine::map(const ExpressionNode * expression, Context& context, Preferences::AngleUnit angleUnit, ComplexCompute<T> compute) {
assert(expression->numberOfChildren() == 1);
EvaluationReference<T> input = expression->childAtIndex(0)->approximate(T(), context, angleUnit);
if (input.node()->type() == EvaluationNode<T>::Type::AllocationFailure) {
return EvaluationReference<T>(EvaluationNode<T>::FailedAllocationStaticNode());
} else if (input.node()->type() == EvaluationNode<T>::Type::Complex) {
const ComplexNode<T> * c = static_cast<ComplexNode<T> *>(input.node());
return compute(*c, angleUnit);
} else {
assert(input->type() == Evaluation<T>::Type::MatrixComplex);
MatrixComplex<T> * m = static_cast<MatrixComplex<T> *>(input);
std::complex<T> * operands = new std::complex<T> [m->numberOfComplexOperands()];
for (int i = 0; i < m->numberOfComplexOperands(); i++) {
const std::complex<T> c = m->complexOperand(i);
operands[i] = compute(c, angleUnit);
assert(input.node()->type() == EvaluationNode<T>::Type::MatrixComplex);
MatrixComplexReference<T> m = MatrixComplexReference<T>(input.node());
MatrixComplexReference<T> result(m.numberOfRows(), m.numberOfColumns());
for (int i = 0; i < result.numberOfRows()*result.numberOfColumns(); i++) {
ComplexNode<T> * child = static_cast<MatrixComplexNode<T> *>(m.node())->childAtIndex(i);
if (child) {
result.addChildTreeAtIndex(compute(*child, angleUnit), i, i);
} else {
result.addChildTreeAtIndex(ComplexReference<T>::Undefined(), i, i);
}
}
result = new MatrixComplex<T>(operands, m->numberOfRows(), m->numberOfColumns());
delete[] operands;
return result;
}
delete input;
return result;
}
template<typename T> Evaluation<T> * ApproximationEngine::mapReduce(const Expression * expression, Context& context, Preferences::AngleUnit angleUnit, ComplexAndComplexReduction<T> computeOnComplexes, ComplexAndMatrixReduction<T> computeOnComplexAndMatrix, MatrixAndComplexReduction<T> computeOnMatrixAndComplex, MatrixAndMatrixReduction<T> computeOnMatrices) {
Evaluation<T> * result = expression->operand(0)->privateApproximate(T(), context, angleUnit);
for (int i = 1; i < expression->numberOfOperands(); i++) {
Evaluation<T> * intermediateResult = nullptr;
Evaluation<T> * nextOperandEvaluation = expression->operand(i)->privateApproximate(T(), context, angleUnit);
if (result->type() == Evaluation<T>::Type::Complex && nextOperandEvaluation->type() == Evaluation<T>::Type::Complex) {
const Complex<T> * c = static_cast<const Complex<T> *>(result);
const Complex<T> * d = static_cast<const Complex<T> *>(nextOperandEvaluation);
intermediateResult = new Complex<T>(computeOnComplexes(*c, *d));
} else if (result->type() == Evaluation<T>::Type::Complex) {
const Complex<T> * c = static_cast<const Complex<T> *>(result);
assert(nextOperandEvaluation->type() == Evaluation<T>::Type::MatrixComplex);
const MatrixComplex<T> * n = static_cast<const MatrixComplex<T> *>(nextOperandEvaluation);
intermediateResult = new MatrixComplex<T>(computeOnComplexAndMatrix(*c, *n));
} else if (nextOperandEvaluation->type() == Evaluation<T>::Type::Complex) {
assert(result->type() == Evaluation<T>::Type::MatrixComplex);
const MatrixComplex<T> * m = static_cast<const MatrixComplex<T> *>(result);
const Complex<T> * d = static_cast<const Complex<T> *>(nextOperandEvaluation);
intermediateResult = new MatrixComplex<T>(computeOnMatrixAndComplex(*m, *d));
template<typename T> EvaluationReference<T> ApproximationEngine::mapReduce(const ExpressionNode * expression, Context& context, Preferences::AngleUnit angleUnit, ComplexAndComplexReduction<T> computeOnComplexes, ComplexAndMatrixReduction<T> computeOnComplexAndMatrix, MatrixAndComplexReduction<T> computeOnMatrixAndComplex, MatrixAndMatrixReduction<T> computeOnMatrices) {
EvaluationReference<T> result = expression->childAtIndex(0)->approximate(T(), context, angleUnit);
for (int i = 1; i < expression->numberOfChildren(); i++) {
EvaluationReference<T> intermediateResult(nullptr);
EvaluationReference<T> nextOperandEvaluation = expression->childAtIndex(i)->approximate(T(), context, angleUnit);
if (result.node()->type() == EvaluationNode<T>::Type::AllocationFailure || nextOperandEvaluation.node()->type() == EvaluationNode<T>::Type::AllocationFailure) {
return EvaluationReference<T>(EvaluationNode<T>::FailedAllocationStaticNode());
}
if (result.node()->type() == EvaluationNode<T>::Type::Complex && nextOperandEvaluation.node()->type() == EvaluationNode<T>::Type::Complex) {
const ComplexNode<T> * c = static_cast<const ComplexNode<T> *>(result.node());
const ComplexNode<T> * d = static_cast<const ComplexNode<T> *>(nextOperandEvaluation.node());
intermediateResult = computeOnComplexes(*c, *d);
} else if (result.node()->type() == EvaluationNode<T>::Type::Complex) {
assert(nextOperandEvaluation.node()->type() == EvaluationNode<T>::Type::MatrixComplex);
const ComplexNode<T> * c = static_cast<const ComplexNode<T> *>(result.node());
MatrixComplexReference<T> n = MatrixComplexReference<T>(nextOperandEvaluation.node());
intermediateResult = computeOnComplexAndMatrix(*c, n);
} else if (nextOperandEvaluation.node()->type() == EvaluationNode<T>::Type::Complex) {
assert(result.node()->type() == EvaluationNode<T>::Type::MatrixComplex);
MatrixComplexReference<T> m = MatrixComplexReference<T>(result.node());
const ComplexNode<T> * d = static_cast<const ComplexNode<T> *>(nextOperandEvaluation.node());
intermediateResult = computeOnMatrixAndComplex(m, *d);
} else {
assert(result->type() == Evaluation<T>::Type::MatrixComplex);
const MatrixComplex<T> * m = static_cast<const MatrixComplex<T> *>(result);
assert(nextOperandEvaluation->type() == Evaluation<T>::Type::MatrixComplex);
const MatrixComplex<T> * n = static_cast<const MatrixComplex<T> *>(nextOperandEvaluation);
intermediateResult = new MatrixComplex<T>(computeOnMatrices(*m, *n));
assert(result.node()->type() == EvaluationNode<T>::Type::MatrixComplex);
assert(nextOperandEvaluation.node()->type() == EvaluationNode<T>::Type::MatrixComplex);
MatrixComplexReference<T> m = MatrixComplexReference<T>(result.node());
MatrixComplexReference<T> n = MatrixComplexReference<T>(nextOperandEvaluation.node());
intermediateResult = computeOnMatrices(m, n);
}
delete result;
delete nextOperandEvaluation;
result = intermediateResult;
assert(result != nullptr);
if (result->isUndefined()) {
return new Complex<T>(Complex<T>::Undefined());
if (result.isUndefined()) {
return ComplexReference<T>::Undefined();
}
}
return result;
}
template<typename T> MatrixComplex<T> ApproximationEngine::elementWiseOnMatrixComplexAndComplex(const MatrixComplex<T> m, const std::complex<T> c, ComplexAndComplexReduction<T> computeOnComplexes) {
std::complex<T> * operands = new std::complex<T> [m.numberOfRows()*m.numberOfColumns()];
for (int i = 0; i < m.numberOfComplexOperands(); i++) {
const std::complex<T> d = m.complexOperand(i);
operands[i] = computeOnComplexes(d, c);
template<typename T> MatrixComplexReference<T> ApproximationEngine::elementWiseOnMatrixComplexAndComplex(const MatrixComplexReference<T> m, const std::complex<T> c, ComplexAndComplexReduction<T> computeOnComplexes) {
if (m.isAllocationFailure()) {
return MatrixComplexReference<T>(EvaluationNode<T>::FailedAllocationStaticNode());
}
MatrixComplex<T> result = MatrixComplex<T>(operands, m.numberOfRows(), m.numberOfColumns());
delete[] operands;
return result;
MatrixComplexReference<T> matrix(m.numberOfRows(), m.numberOfColumns());
for (int i = 0; i < m.numberOfChildren(); i++) {
ComplexNode<T> * child = static_cast<MatrixComplexNode<T> *>(m.node())->childAtIndex(i);
if (child) {
matrix.addChildTreeAtIndex(computeOnComplexes(*child, c), i, i);
} else {
matrix.addChildTreeAtIndex(ComplexReference<T>::Undefined(), i, i);
}
}
return matrix;
}
template<typename T> MatrixComplex<T> ApproximationEngine::elementWiseOnComplexMatrices(const MatrixComplex<T> m, const MatrixComplex<T> n, ComplexAndComplexReduction<T> computeOnComplexes) {
template<typename T> MatrixComplexReference<T> ApproximationEngine::elementWiseOnComplexMatrices(const MatrixComplexReference<T> m, const MatrixComplexReference<T> n, ComplexAndComplexReduction<T> computeOnComplexes) {
if (m.isAllocationFailure() || n.isAllocationFailure()) {
return MatrixComplexReference<T>(EvaluationNode<T>::FailedAllocationStaticNode());
}
if (m.numberOfRows() != n.numberOfRows() || m.numberOfColumns() != n.numberOfColumns()) {
return MatrixComplex<T>::Undefined();
return MatrixComplexReference<T>::Undefined();
}
std::complex<T> * operands = new std::complex<T> [m.numberOfRows()*m.numberOfColumns()];
for (int i = 0; i < m.numberOfComplexOperands(); i++) {
const Complex<T> c = m.complexOperand(i);
const Complex<T> d = n.complexOperand(i);
operands[i] = computeOnComplexes(c, d);
MatrixComplexReference<T> matrix(m.numberOfRows(), m.numberOfColumns());
for (int i = 0; i < m.numberOfChildren(); i++) {
ComplexNode<T> * childM = static_cast<MatrixComplexNode<T> *>(m.node())->childAtIndex(i);
ComplexNode<T> * childN = static_cast<MatrixComplexNode<T> *>(n.node())->childAtIndex(i);
if (childM && childN) {
matrix.addChildTreeAtIndex(computeOnComplexes(*childM, *childN), i, i);
} else {
matrix.addChildTreeAtIndex(ComplexReference<T>::Undefined(), i, i);
}
}
MatrixComplex<T> result = MatrixComplex<T>(operands, m.numberOfRows(), m.numberOfColumns());
delete[] operands;
return result;
return matrix;
}
template std::complex<float> Poincare::ApproximationEngine::truncateRealOrImaginaryPartAccordingToArgument<float>(std::complex<float>);
template std::complex<double> Poincare::ApproximationEngine::truncateRealOrImaginaryPartAccordingToArgument<double>(std::complex<double>);
template Poincare::Evaluation<float> * Poincare::ApproximationEngine::map(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexCompute<float> compute);
template Poincare::Evaluation<double> * Poincare::ApproximationEngine::map(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexCompute<double> compute);
template Poincare::Evaluation<float> * Poincare::ApproximationEngine::mapReduce(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexAndComplexReduction<float> computeOnComplexes, Poincare::ApproximationEngine::ComplexAndMatrixReduction<float> computeOnComplexAndMatrix, Poincare::ApproximationEngine::MatrixAndComplexReduction<float> computeOnMatrixAndComplex, Poincare::ApproximationEngine::MatrixAndMatrixReduction<float> computeOnMatrices);
template Poincare::Evaluation<double> * Poincare::ApproximationEngine::mapReduce(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexAndComplexReduction<double> computeOnComplexes, Poincare::ApproximationEngine::ComplexAndMatrixReduction<double> computeOnComplexAndMatrix, Poincare::ApproximationEngine::MatrixAndComplexReduction<double> computeOnMatrixAndComplex, Poincare::ApproximationEngine::MatrixAndMatrixReduction<double> computeOnMatrices);
template Poincare::MatrixComplex<float> Poincare::ApproximationEngine::elementWiseOnMatrixComplexAndComplex<float>(const Poincare::MatrixComplex<float>, const std::complex<float>, std::complex<float> (*)(std::complex<float>, std::complex<float>));
template Poincare::MatrixComplex<double> Poincare::ApproximationEngine::elementWiseOnMatrixComplexAndComplex<double>(const Poincare::MatrixComplex<double>, std::complex<double> const, std::complex<double> (*)(std::complex<double>, std::complex<double>));
template Poincare::MatrixComplex<float> Poincare::ApproximationEngine::elementWiseOnComplexMatrices<float>(const Poincare::MatrixComplex<float>, const Poincare::MatrixComplex<float>, std::complex<float> (*)(std::complex<float>, std::complex<float>));
template Poincare::MatrixComplex<double> Poincare::ApproximationEngine::elementWiseOnComplexMatrices<double>(const Poincare::MatrixComplex<double>, const Poincare::MatrixComplex<double>, std::complex<double> (*)(std::complex<double>, std::complex<double>));
template Poincare::EvaluationReference<float> Poincare::ApproximationEngine::map(const Poincare::ExpressionNode * expression, Poincare::Context& context, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexCompute<float> compute);
template Poincare::EvaluationReference<double> Poincare::ApproximationEngine::map(const Poincare::ExpressionNode * expression, Poincare::Context& context, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexCompute<double> compute);
template Poincare::EvaluationReference<float> Poincare::ApproximationEngine::mapReduce(const Poincare::ExpressionNode * expression, Poincare::Context& context, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexAndComplexReduction<float> computeOnComplexes, Poincare::ApproximationEngine::ComplexAndMatrixReduction<float> computeOnComplexAndMatrix, Poincare::ApproximationEngine::MatrixAndComplexReduction<float> computeOnMatrixAndComplex, Poincare::ApproximationEngine::MatrixAndMatrixReduction<float> computeOnMatrices);
template Poincare::EvaluationReference<double> Poincare::ApproximationEngine::mapReduce(const Poincare::ExpressionNode * expression, Poincare::Context& context, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationEngine::ComplexAndComplexReduction<double> computeOnComplexes, Poincare::ApproximationEngine::ComplexAndMatrixReduction<double> computeOnComplexAndMatrix, Poincare::ApproximationEngine::MatrixAndComplexReduction<double> computeOnMatrixAndComplex, Poincare::ApproximationEngine::MatrixAndMatrixReduction<double> computeOnMatrices);
template Poincare::MatrixComplexReference<float> Poincare::ApproximationEngine::elementWiseOnMatrixComplexAndComplex<float>(const Poincare::MatrixComplexReference<float>, const std::complex<float>, Poincare::ComplexReference<float> (*)(std::complex<float>, std::complex<float>));
template Poincare::MatrixComplexReference<double> Poincare::ApproximationEngine::elementWiseOnMatrixComplexAndComplex<double>(const Poincare::MatrixComplexReference<double>, std::complex<double> const, Poincare::ComplexReference<double> (*)(std::complex<double>, std::complex<double>));
template Poincare::MatrixComplexReference<float> Poincare::ApproximationEngine::elementWiseOnComplexMatrices<float>(const Poincare::MatrixComplexReference<float>, const Poincare::MatrixComplexReference<float>, Poincare::ComplexReference<float> (*)(std::complex<float>, std::complex<float>));
template Poincare::MatrixComplexReference<double> Poincare::ApproximationEngine::elementWiseOnComplexMatrices<double>(const Poincare::MatrixComplexReference<double>, const Poincare::MatrixComplexReference<double>, Poincare::ComplexReference<double> (*)(std::complex<double>, std::complex<double>));
}

View File

@@ -17,7 +17,7 @@ Expression * ArcCosine::clone() const {
return a;
}
Expression * ArcCosine::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
ExpressionReference ArcCosine::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;

View File

@@ -17,7 +17,7 @@ Expression * ArcSine::clone() const {
return a;
}
Expression * ArcSine::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
ExpressionReference ArcSine::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;

View File

@@ -17,7 +17,7 @@ Expression * ArcTangent::clone() const {
return a;
}
Expression * ArcTangent::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
ExpressionReference ArcTangent::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;

View File

@@ -3,18 +3,24 @@
namespace Poincare {
Integer Arithmetic::LCM(const Integer * a, const Integer * b) {
if (a->isZero() || b->isZero()) {
return Integer(0);
IntegerReference Arithmetic::LCM(const IntegerReference a, const IntegerReference b) {
if (a.isAllocationFailure() || b.isAllocationFailure()) {
return IntegerReference(ExpressionNode::FailedAllocationStaticNode());
}
Integer signResult = Integer::Division(Integer::Multiplication(*a, *b), GCD(a,b)).quotient;
if (a.isZero() || b.isZero()) {
return IntegerReference(0);
}
IntegerReference signResult = IntegerReference::Division(IntegerReference::Multiplication(a, b), GCD(a,b)).quotient;
signResult.setNegative(false);
return signResult;
}
Integer Arithmetic::GCD(const Integer * a, const Integer * b) {
Integer i = *a;
Integer j = *b;
IntegerReference Arithmetic::GCD(const IntegerReference a, const IntegerReference b) {
if (a.isAllocationFailure() || b.isAllocationFailure()) {
return IntegerReference(ExpressionNode::FailedAllocationStaticNode());
}
IntegerReference i = IntegerReference(a.clone().node());
IntegerReference j = IntegerReference(b.clone().node());
i.setNegative(false);
j.setNegative(false);
do {
@@ -24,10 +30,10 @@ Integer Arithmetic::GCD(const Integer * a, const Integer * b) {
if (j.isZero()) {
return i;
}
if (j.isLowerThan(i)) {
i = Integer::Division(i, j).remainder;
if (IntegerReference::NaturalOrder(i, j) > 0) {
i = IntegerReference::Division(i, j).remainder;
} else {
j = Integer::Division(j, i).remainder;
j = IntegerReference::Division(j, i).remainder;
}
} while(true);
}
@@ -36,62 +42,74 @@ int primeFactors[Arithmetic::k_numberOfPrimeFactors] = {2, 3, 5, 7, 11, 13, 17,
3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919};
// we can go to 7907*7907 = 62 520 649
void Arithmetic::PrimeFactorization(const Integer * n, Integer * outputFactors, Integer * outputCoefficients, int outputLength) {
void Arithmetic::PrimeFactorization(const IntegerReference n, IntegerReference outputFactors[], IntegerReference outputCoefficients[], int outputLength) {
if (n.isAllocationFailure()) {
/* Special case 0: Allocation failure. */
outputCoefficients[0] = -1;
return;
}
// To avoid cloning n to get its absolute value m, we change n sign and reset it before returning
bool nIsNegative = n.isNegative();
IntegerReference m = *(const_cast<IntegerReference *>(&n));
m.setNegative(false);
/* First we look for prime divisors in the table primeFactors (to speed up
* the prime factorization for low numbers). When k_numberOfPrimeFactors is
* overflow, try every number as divisor. */
Integer m = *n;
m.setNegative(false);
if (m.isEqualTo(Integer(1))) {
if (IntegerReference::NaturalOrder(m, IntegerReference(1))) {
m.setNegative(nIsNegative);
return;
}
const Integer primorial32("525896479052627740771371797072411912900610967452630");
if (primorial32.isLowerThan(m)) {
const IntegerReference primorial32("525896479052627740771371797072411912900610967452630", false);
if (IntegerReference::NaturalOrder(primorial32, m) < 0) {
/* Special case 1: We do not want to break i in prime factor because it
* might take too many factors... More than k_maxNumberOfPrimeFactors.
* outputCoefficients[0] is set to -1 to indicate a special case. */
outputCoefficients[0] = Integer(-1);
outputCoefficients[0] = -1;
m.setNegative(nIsNegative);
return;
}
for (int index = 0; index < outputLength; index++) {
outputCoefficients[index] = Integer(0);
outputCoefficients[index] = IntegerReference(0);
}
int t = 0; // n prime factor index
int k = 0; // prime factor index
Integer testedPrimeFactor = Integer(primeFactors[k]); // prime factor
IntegerReference testedPrimeFactor(primeFactors[k]); // prime factor
outputFactors[t] = testedPrimeFactor;
IntegerDivision d = {.quotient = 0, .remainder = 0};
IntegerDivisionReference d = {.quotient = 0, .remainder = 0};
bool stopCondition;
do {
stopCondition = Integer::Power(outputFactors[t], Integer(2)).isLowerThan(m);
d = Integer::Division(m, testedPrimeFactor);
if (d.remainder.isEqualTo(Integer(0))) {
outputCoefficients[t] = Integer::Addition(outputCoefficients[t], Integer(1));
m = std::move(d.quotient);
if (m.isEqualTo(Integer(1))) {
stopCondition = IntegerReference::NaturalOrder(IntegerReference::Power(outputFactors[t], IntegerReference(2)), m) < 0;
d = IntegerReference::Division(m, testedPrimeFactor);
if (d.remainder.isZero()) {
outputCoefficients[t] = IntegerReference::Addition(outputCoefficients[t], IntegerReference(1));
m = d.quotient;
if (m.isOne()) {
m.setNegative(nIsNegative);
return;
}
continue;
}
if (!outputCoefficients[t].isEqualTo(Integer(0))) {
if (!outputCoefficients[t].isZero()) {
t++;
}
k++;
testedPrimeFactor = k < k_numberOfPrimeFactors ? Integer(primeFactors[k]) : Integer::Addition(testedPrimeFactor, Integer(1));
testedPrimeFactor = k < k_numberOfPrimeFactors ? IntegerReference(primeFactors[k]) : IntegerReference::Addition(testedPrimeFactor, IntegerReference(1));
outputFactors[t] = testedPrimeFactor;
} while (stopCondition && testedPrimeFactor.isLowerThan(Integer(k_biggestPrimeFactor)));
if (Integer::Power(Integer(k_biggestPrimeFactor), Integer(2)).isLowerThan(m)) {
} while (stopCondition && IntegerReference::NaturalOrder(testedPrimeFactor,IntegerReference(k_biggestPrimeFactor)) < 0);
if (IntegerReference::NaturalOrder(IntegerReference::Power(IntegerReference(k_biggestPrimeFactor), IntegerReference(2)), m) < 0) {
/* Special case 2: We do not want to break i in prime factor because it
* take too much time: the prime factor that should be tested is above
* k_biggestPrimeFactor.
* outputCoefficients[0] is set to -1 to indicate a special case. */
outputCoefficients[0] = -1;
m.setNegative(nIsNegative);
return;
}
outputFactors[t] = std::move(m);
outputCoefficients[t] = Integer::Addition(outputCoefficients[t], Integer(1));
}
outputFactors[t] = m;
outputCoefficients[t] = IntegerReference::Addition(outputCoefficients[t], IntegerReference(1));
m.setNegative(nIsNegative);
}
}

View File

@@ -20,7 +20,7 @@ Expression * BinomialCoefficient::clone() const {
return b;
}
Expression * BinomialCoefficient::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
ExpressionReference BinomialCoefficient::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;

View File

@@ -20,7 +20,7 @@ Expression * Ceiling::clone() const {
return c;
}
Expression * Ceiling::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
ExpressionReference Ceiling::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;

146
poincare/src/complex.cpp Normal file
View File

@@ -0,0 +1,146 @@
extern "C" {
#include <assert.h>
#include <float.h>
#include <stdlib.h>
}
#include <poincare/complex.h>
//#include <poincare/division.h>
//#include <poincare/matrix.h>
#include <poincare/expression_reference.h>
#include <poincare/undefined.h>
#include <poincare/infinity.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 {
template<typename T>
void ComplexNode<T>::setComplex(std::complex<T> c) {
this->real(c.real());
this->imag(c.imag());
if (this->real() == -0) {
this->real(0);
}
if (this->imag() == -0) {
this->imag(0);
}
}
template<typename T>
T ComplexNode<T>::toScalar() const {
if (this->imag() == 0.0) {
return this->real();
}
return NAN;
}
template <typename T>
static ExpressionReference CreateDecimal(T f) {
if (std::isnan(f)) {
return UndefinedReference();
}
if (std::isinf(f)) {
return InfiniteReference(f < 0.0);
}
return DecimalReference(f);
}
template<typename T>
ExpressionReference ComplexNode<T>::complexToExpression(Preferences::ComplexFormat complexFormat) const {
if (std::isnan(this->real()) || std::isnan(this->imag())) {
return UndefinedReference();
}
switch (complexFormat) {
case Preferences::ComplexFormat::Cartesian:
{
ExpressionReference real(nullptr);
ExpressionReference imag(nullptr);
if (this->real() != 0 || this->imag() == 0) {
real = CreateDecimal<T>(this->real());
}
if (this->imag() != 0) {
if (this->imag() == 1.0 || this->imag() == -1) {
imag = SymbolReference(Ion::Charset::IComplex);
} else if (this->imag() > 0) {
imag = MultiplicationReference(CreateDecimal(this->imag()), SymbolReference(Ion::Charset::IComplex));
} else {
imag = MultiplicationReference(CreateDecimal(-this->imag()), SymbolReference(Ion::Charset::IComplex));
}
}
if (!imag.isDefined()) {
return real;
} else if (!real.isDefined()) {
if (this->imag() > 0) {
return imag;
} else {
return OppositeReference(imag);
}
return imag;
} else if (this->imag() > 0) {
return AdditionReference(real, imag);
} else {
return SubtractionReference(real, imag);
}
}
default:
{
assert(complexFormat == Preferences::ComplexFormat::Polar);
ExpressionReference norm(nullptr);
ExpressionReference 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) {
ExpressionReference arg(nullptr);
if (th == 1.0) {
arg = SymbolReference(Ion::Charset::IComplex);
} else if (th == -1.0) {
arg = OppositeReference(SymbolReference(Ion::Charset::IComplex));
} else if (th > 0) {
arg = MultiplicationReference(CreateDecimal(th), SymbolReference(Ion::Charset::IComplex));
} else {
arg = OppositeRefrence(MultiplicationReference(CreateDecimal(-th), SymbolReference(Ion::Charset::IComplex)));
}
exp = PowerReference(SymbolReference(Ion::Charset::Exponential), arg);
}
if (!exp.isDefined()) {
return norm;
} else if (!norm.isDefined()) {
return exp;
} else {
return MultiplicationReference(norm, exp);
}
}
}
}
template<typename T>
EvaluationReference<T> ComplexNode<T>::inverse() const {
return ComplexReference<T>(Division::compute(std::complex<T>(1.0), *this));
}
template<typename T>
ComplexReference<T>::ComplexReference(std::complex<T> c) :
EvaluationReference<T>()
{
TreeNode * node = TreePool::sharedPool()->createTreeNode<ComplexNode<T>>();
this->m_identifier = node->identifier();
if (!(node->isAllocationFailure())) {
static_cast<ComplexNode<T> *>(node)->setComplex(c);
}
}
template class ComplexReference<float>;
template class ComplexReference<double>;
}

View File

@@ -16,7 +16,7 @@ Expression * ComplexArgument::clone() const {
return a;
}
Expression * ComplexArgument::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
ExpressionReference ComplexArgument::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;

View File

@@ -24,7 +24,7 @@ int ConfidenceInterval::polynomialDegree(char symbolName) const {
return -1;
}
Expression * ConfidenceInterval::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
ExpressionReference ConfidenceInterval::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
@@ -62,7 +62,7 @@ Expression * ConfidenceInterval::shallowReduce(Context& context, Preferences::An
}
template<typename T>
Evaluation<T> * ConfidenceInterval::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const {
EvaluationReference<T> ConfidenceInterval::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const {
Evaluation<T> * fInput = operand(0)->privateApproximate(T(), context, angleUnit);
Evaluation<T> * nInput = operand(1)->privateApproximate(T(), context, angleUnit);
T f = static_cast<Complex<T> *>(fInput)->toScalar();

Some files were not shown because too many files have changed in this diff Show More