[poincare] Rather check for undefined operand in shallowReduce instead

of in deepReduce

Change-Id: I6db09297c75867178d83f27909f915b53ec161c9
This commit is contained in:
Émilie Feral
2017-11-10 15:13:44 +01:00
parent b53716cd2b
commit 8aa4444337
22 changed files with 148 additions and 10 deletions

View File

@@ -14,17 +14,68 @@ class Evaluation;
class Rational;
class Expression {
friend class Division;
friend class Logarithm;
friend class Opposite;
friend class NaperianLogarithm;
friend class Subtraction;
friend class Addition;
friend class Undefined;
friend class Rational;
friend class Decimal;
friend class Multiplication;
friend class Power;
friend class Trigonometry;
friend class Addition;
friend class Factorial;
friend class Division;
friend class Store;
friend class Sine;
friend class Cosine;
friend class Tangent;
friend class AbsoluteValue;
friend class ArcCosine;
friend class ArcSine;
friend class ArcTangent;
friend class BinomialCoefficient;
friend class Ceiling;
friend class ComplexArgument;
friend class ConfidenceInterval;
friend class Conjugate;
friend class Derivative;
friend class Determinant;
friend class DivisionQuotient;
friend class DivisionRemainder;
friend class Floor;
friend class FracPart;
friend class GreatCommonDivisor;
friend class HyperbolicArcCosine;
friend class HyperbolicArcSine;
friend class HyperbolicArcTangent;
friend class HyperbolicCosine;
friend class HyperbolicSine;
friend class HyperbolicTangent;
friend class ImaginaryPart;
friend class Integral;
friend class LeastCommonMultiple;
friend class Logarithm;
friend class MatrixDimension;
friend class MatrixInverse;
friend class MatrixTrace;
friend class MatrixTranspose;
friend class NaperianLogarithm;
friend class NthRoot;
friend class Opposite;
friend class Parenthesis;
friend class PermuteCoefficient;
friend class PredictionInterval;
friend class Product;
friend class RealPart;
friend class Round;
friend class SquareRoot;
friend class Subtraction;
friend class Sum;
friend class Symbol;
friend class Matrix;
friend class SimplificationRoot;
friend class Sequence;
friend class Trigonometry;
friend class EvaluationEngine;
friend class SimplificationEngine;
public:
enum class Type : uint8_t {
Undefined = 0,
@@ -200,7 +251,7 @@ private:
Expression * deepBeautify(Context & context, AngleUnit angleUnit);
Expression * deepReduce(Context & context, AngleUnit angleUnit);
// TODO: should be virtual pure
virtual Expression * shallowReduce(Context & context, AngleUnit angleUnit) { return this; };
virtual Expression * shallowReduce(Context & context, AngleUnit angleUnit);
virtual Expression * shallowBeautify(Context & context, AngleUnit angleUnit) { return this; };
// Private methods used in simplification process

View File

@@ -30,6 +30,10 @@ ExpressionLayout * AbsoluteValue::privateCreateLayout(FloatDisplayMode floatDisp
}
Expression * AbsoluteValue::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
if (operand(0)->sign() == Sign::Positive) {
return replaceWith(editableOperand(0), true);
}

View File

@@ -23,6 +23,10 @@ Expression * Addition::clone() const {
/* Simplication */
Expression * Addition::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
/* Step 1: Addition is associative, so let's start by merging children which
* also are additions themselves. */
int i = 0;

View File

@@ -17,6 +17,10 @@ Expression * ArcCosine::clone() const {
}
Expression * ArcCosine::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit);
}

View File

@@ -17,6 +17,10 @@ Expression * ArcSine::clone() const {
}
Expression * ArcSine::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit);
}

View File

@@ -17,6 +17,10 @@ Expression * ArcTangent::clone() const {
}
Expression * ArcTangent::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit);
}

View File

@@ -22,6 +22,10 @@ Expression * Cosine::clone() const {
}
Expression * Cosine::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
return Trigonometry::shallowReduceDirectFunction(this, context, angleUnit);
}

View File

@@ -154,6 +154,10 @@ ExpressionLayout * Decimal::privateCreateLayout(FloatDisplayMode floatDisplayMod
}
Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
int numberOfDigits = numberOfDigitsInMantissa();
Integer numerator = m_mantissa;
Integer denominator = Integer(1);

View File

@@ -23,6 +23,10 @@ Expression * Division::clone() const {
}
Expression * Division::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
Power * p = new Power(operand(1), new Rational(-1), false);
Multiplication * m = new Multiplication(operand(0), p, false);
detachOperands();

View File

@@ -141,11 +141,18 @@ void Expression::Reduce(Expression ** expressionAddress, Context & context, Angl
Expression * Expression::deepReduce(Context & context, AngleUnit angleUnit) {
assert(parent() != nullptr);
for (int i = 0; i < numberOfOperands(); i++) {
if ((editableOperand(i))->deepReduce(context, angleUnit)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) {
editableOperand(i)->deepReduce(context, angleUnit);
}
return shallowReduce(context, angleUnit);
}
Expression * Expression::shallowReduce(Context & context, AngleUnit angleUnit) {
for (int i = 0; i < numberOfOperands(); i++) {
if (editableOperand(i)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) {
return replaceWith(new Undefined(), true);
}
}
return shallowReduce(context, angleUnit);
return this;
}
Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) {

View File

@@ -27,6 +27,10 @@ Expression * Factorial::clone() const {
}
Expression * Factorial::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
if (operand(0)->type() == Type::Rational) {
Rational * r = static_cast<Rational *>(editableOperand(0));
if (!r->denominator().isOne()) {

View File

@@ -38,6 +38,10 @@ Complex<T> Logarithm::computeOnComplex(const Complex<T> c, AngleUnit angleUnit)
}
Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
if (operand(0)->sign() == Sign::Negative || (numberOfOperands() == 2 && operand(1)->sign() == Sign::Negative)) {
return replaceWith(new Undefined(), true);
}

View File

@@ -113,6 +113,10 @@ static inline const Expression * Base(const Expression * e) {
}
Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
/* Step 1: Multiplication is associative, so let's start by merging children
* which also are multiplications themselves. */
int i = 0;

View File

@@ -23,6 +23,10 @@ Expression * NaperianLogarithm::clone() const {
}
Expression * NaperianLogarithm::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
const Expression * logOperands[2] = {operand(0)->clone(), new Symbol(Ion::Charset::Exponential)};
Logarithm * l = new Logarithm(logOperands, 2, false);
replaceWith(l, true);

View File

@@ -20,6 +20,10 @@ Expression * NthRoot::clone() const {
}
Expression * NthRoot::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
Power * invIndex = new Power(operand(1), new Rational(-1), false);
Power * p = new Power(operand(0), invIndex, false);
detachOperands();

View File

@@ -29,6 +29,10 @@ Complex<T> Opposite::compute(const Complex<T> c, AngleUnit angleUnit) {
}
Expression * Opposite::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
const Expression * op = operand(0);
detachOperand(op);
Multiplication * m = new Multiplication(new Rational(-1), op, false);

View File

@@ -24,6 +24,10 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla
}
Expression * Parenthesis::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
return replaceWith(editableOperand(0), true);
}

View File

@@ -136,6 +136,10 @@ int Power::simplificationOrderGreaterType(const Expression * e) const {
}
Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
/* Step 0: We look for square root and sum of square roots (two terms maximum
* so far) at the denominator and move them to the numerator. */

View File

@@ -22,6 +22,10 @@ Expression * Sine::clone() const {
}
Expression * Sine::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
return Trigonometry::shallowReduceDirectFunction(this, context, angleUnit);
}

View File

@@ -33,6 +33,10 @@ Complex<T> SquareRoot::computeOnComplex(const Complex<T> c, AngleUnit angleUnit)
}
Expression * SquareRoot::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
Power * p = new Power(operand(0), new Rational(1, 2), false);
detachOperands();
replaceWith(p, true);

View File

@@ -29,6 +29,10 @@ Complex<T> Subtraction::compute(const Complex<T> c, const Complex<T> d) {
}
Expression * Subtraction::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
Multiplication * m = new Multiplication(new Rational(-1), operand(1), false);
Addition * a = new Addition(operand(0), m, false);
detachOperands();

View File

@@ -23,6 +23,10 @@ Expression * Tangent::clone() const {
}
Expression * Tangent::shallowReduce(Context& context, AngleUnit angleUnit) {
Expression * e = Expression::shallowReduce(context, angleUnit);
if (e != this) {
return e;
}
Expression * newExpression = Trigonometry::shallowReduceDirectFunction(this, context, angleUnit);
if (newExpression->type() == Type::Tangent) {
const Expression * op[1] = {newExpression->operand(0)};