[poincare] Improve Logarithm::shallowReduce

Change-Id: Ie0f4c0cb25f7c62c65786f7b3a47583ed7323770
This commit is contained in:
Émilie Feral
2017-11-17 17:11:36 +01:00
parent 3f48f49fbe
commit 39ca735f21
3 changed files with 43 additions and 34 deletions

View File

@@ -22,6 +22,7 @@ private:
/* Simplification */
Expression * shallowReduce(Context & context, AngleUnit angleUnit) override;
Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override;
bool parentIsAPowerOfSameBase() const;
Expression * splitInteger(Integer i, bool isDenominator, Context & context, AngleUnit angleUnit);
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);

View File

@@ -60,37 +60,22 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) {
if (numberOfOperands() == 2 && op->isIdenticalTo(operand(1))) {
return replaceWith(new Rational(1), true);
}
/* log(x^y, b)->y*log(x, b) if x>0
* We do not apply this rule if the parent node is a power of b. In this case
* there could be a simplication of form e^ln(3^(1/2))->3^(1/2) */
if (op->type() == Type::Power && op->operand(0)->sign() == Sign::Positive) {
bool shouldApplyRule = true;
if (parent()->type() == Type::Power && parent()->operand(1) == this) {
const Expression * powerOperand0 = parent()->operand(0);
if (numberOfOperands() == 1) {
if (powerOperand0->type() == Type::Rational && static_cast<const Rational *>(powerOperand0)->isTen()) {
shouldApplyRule = false;
}
}
if (numberOfOperands() == 2) {
if (powerOperand0->isIdenticalTo(operand(1))){
shouldApplyRule = false;
}
}
}
if (shouldApplyRule) {
Power * p = static_cast<Power *>(op);
Expression * x = p->editableOperand(0);
Expression * y = p->editableOperand(1);
p->detachOperands();
replaceOperand(p, x, true);
Expression * newLog = shallowReduce(context, angleUnit);
newLog = newLog->replaceWith(new Multiplication(y, newLog->clone(), false), true);
return newLog->shallowReduce(context, angleUnit);
}
/* We do not apply some rules if the parent node is a power of b. In this
* case there is a simplication of form e^ln(3^(1/2))->3^(1/2) */
bool letLogAtRoot = parentIsAPowerOfSameBase();
// log(x^y, b)->y*log(x, b) if x>0
if (!letLogAtRoot && op->type() == Type::Power && op->operand(0)->sign() == Sign::Positive) {
Power * p = static_cast<Power *>(op);
Expression * x = p->editableOperand(0);
Expression * y = p->editableOperand(1);
p->detachOperands();
replaceOperand(p, x, true);
Expression * newLog = shallowReduce(context, angleUnit);
newLog = newLog->replaceWith(new Multiplication(y, newLog->clone(), false), true);
return newLog->shallowReduce(context, angleUnit);
}
// log(x*y, b)->log(x,b)+log(y, b) if x,y>0
if (op->type() == Type::Multiplication) {
if (!letLogAtRoot && op->type() == Type::Multiplication) {
Addition * a = new Addition();
for (int i = 0; i<op->numberOfOperands()-1; i++) {
Expression * factor = op->editableOperand(i);
@@ -128,15 +113,34 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) {
return replaceWith(new Rational(1), true);
}
// log(r) = a0log(p0)+a1log(p1)+... with r = p0^a0*p1^a1*... (Prime decomposition)
Expression * n = splitInteger(r->numerator(), false, context, angleUnit);
Expression * d = splitInteger(r->denominator(), true, context, angleUnit);
Addition * a = new Addition(n, d, false);
replaceWith(a, true);
return a->shallowReduce(context, angleUnit);
if (!letLogAtRoot) {
Expression * n = splitInteger(r->numerator(), false, context, angleUnit);
Expression * d = splitInteger(r->denominator(), true, context, angleUnit);
Addition * a = new Addition(n, d, false);
replaceWith(a, true);
return a->shallowReduce(context, angleUnit);
}
}
return this;
}
bool Logarithm::parentIsAPowerOfSameBase() const {
if (parent()->type() == Type::Power && parent()->operand(1) == this) {
const Expression * powerOperand0 = parent()->operand(0);
if (numberOfOperands() == 1) {
if (powerOperand0->type() == Type::Rational && static_cast<const Rational *>(powerOperand0)->isTen()) {
return true;
}
}
if (numberOfOperands() == 2) {
if (powerOperand0->isIdenticalTo(operand(1))){
return true;
}
}
}
return false;
}
Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & context, AngleUnit angleUnit) {
assert(!i.isZero());
assert(!i.isNegative());

View File

@@ -479,6 +479,10 @@ QUIZ_CASE(poincare_simplify_easy) {
assert_parsed_expression_simplify_to("log(1/R(2))", "-log(2)/2");
assert_parsed_expression_simplify_to("log(-I)", "log(-I)");
assert_parsed_expression_simplify_to("R(-I)", "R(-I)");
assert_parsed_expression_simplify_to("X^ln(65)", "65");
assert_parsed_expression_simplify_to("X^ln(PX)", "PX");
assert_parsed_expression_simplify_to("X^log(PX)", "X^(log(P)+log(X))");
assert_parsed_expression_simplify_to("R(X^2)", "X");
/* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */
//assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789");