[poincare] Merger Trigonometry and trigonometric function

Change-Id: Idff99ad2db109f7085a56daf288831eb2a69aa8b
This commit is contained in:
Émilie Feral
2017-10-16 10:21:12 +02:00
parent 591ab0550d
commit a9dacd18f3
7 changed files with 71 additions and 91 deletions

View File

@@ -77,7 +77,6 @@ objs += $(addprefix poincare/src/,\
sum.o\
symbol.o\
tangent.o\
trigonometric_function.o\
trigonometry.o\
undefined.o\
variable_context.o\

View File

@@ -1,12 +1,12 @@
#ifndef POINCARE_COSINE_H
#define POINCARE_COSINE_H
#include <poincare/trigonometric_function.h>
#include <poincare/trigonometry.h>
namespace Poincare {
class Cosine : public TrigonometricFunction {
using TrigonometricFunction::TrigonometricFunction;
class Cosine : public Trigonometry {
using Trigonometry::Trigonometry;
public:
Type type() const override;
Expression * clone() const override;

View File

@@ -1,12 +1,12 @@
#ifndef POINCARE_SINE_H
#define POINCARE_SINE_H
#include <poincare/trigonometric_function.h>
#include <poincare/trigonometry.h>
namespace Poincare {
class Sine : public TrigonometricFunction {
using TrigonometricFunction::TrigonometricFunction;
class Sine : public Trigonometry {
using Trigonometry::Trigonometry;
public:
Type type() const override;
Expression * clone() const override;

View File

@@ -1,21 +0,0 @@
#ifndef POINCARE_TRIGONOMETRIC_FUNCTION_H
#define POINCARE_TRIGONOMETRIC_FUNCTION_H
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
#include <poincare/trigonometry.h>
namespace Poincare {
class TrigonometricFunction : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Expression * immediateSimplify() override;
private:
virtual Trigonometry::Function trigonometricFunctionType() const = 0;
};
}
#endif

View File

@@ -2,17 +2,25 @@
#define POINCARE_TRIGONOMETRY_H
#include <poincare/expression.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
#include <poincare/trigonometry.h>
namespace Poincare {
class Trigonometry {
class Trigonometry : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Expression * immediateSimplify() override;
constexpr static int k_numberOfEntries = 18;
protected:
enum class Function {
Cosine = 0,
Sine = 1,
};
virtual Function trigonometricFunctionType() const = 0;
static Expression * table(const Expression * e, Function f, bool inverse); // , Function f, bool inverse
constexpr static int k_numberOfEntries = 18;
};
}

View File

@@ -1,61 +0,0 @@
#include <poincare/trigonometric_function.h>
#include <poincare/hyperbolic_cosine.h>
#include <poincare/complex.h>
#include <poincare/symbol.h>
#include <poincare/rational.h>
#include <poincare/multiplication.h>
#include <ion.h>
extern "C" {
#include <assert.h>
}
#include <cmath>
namespace Poincare {
Expression * TrigonometricFunction::immediateSimplify() {
Expression * lookup = Trigonometry::table(operand(0), trigonometricFunctionType(), false);
if (lookup != nullptr) {
return replaceWith(lookup, true);
}
if (operand(0)->sign() < 0) {
((Expression *)operand(0))->turnIntoPositive();
((Expression *)operand(0))->immediateSimplify();
if (trigonometricFunctionType() == Trigonometry::Function::Cosine) {
return immediateSimplify();
} else if (trigonometricFunctionType() == Trigonometry::Function::Sine) {
const Expression * multOperands[2] = {new Rational(Integer(-1)), clone()};
Multiplication * m = new Multiplication(multOperands, 2, false);
((Expression *)m->operand(1))->immediateSimplify();
return replaceWith(m, true)->immediateSimplify();
}
assert(false);
}
if (operand(0)->type() == Type::Multiplication && operand(0)->operand(1)->type() == Type::Symbol && static_cast<const Symbol *>(operand(0)->operand(1))->name() == Ion::Charset::SmallPi && operand(0)->operand(0)->type() == Type::Rational) {
Rational * r = static_cast<Rational *>((Expression *)operand(0)->operand(0));
// Replace argument in [0, Pi[
if (r->denominator().isLowerThan(r->numerator())) {
IntegerDivision div = Integer::Division(r->numerator(), r->denominator());
// For Sine, replace argument in [0, Pi/2[
if (trigonometricFunctionType() == Trigonometry::Function::Sine && r->denominator().isLowerThan(Integer::Addition(div.remainder, div.remainder))) {
div.remainder = Integer::Subtraction(r->denominator(), div.remainder);
}
Rational * newR = new Rational(div.remainder, r->denominator());
const_cast<Expression *>(operand(0))->replaceOperand(r, newR, true);
const_cast<Expression *>(operand(0))->immediateSimplify();
if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) {
Expression * simplifiedCosine = immediateSimplify(); // recursive
const Expression * multOperands[2] = {new Rational(Integer(-1)), simplifiedCosine->clone()};
Multiplication * m = new Multiplication(multOperands, 2, false);
return simplifiedCosine->replaceWith(m, true)->immediateSimplify();
} else {
return immediateSimplify(); // recursive
}
}
assert(r->sign() > 0);
assert(r->numerator().isLowerThan(r->denominator()));
}
return this;
}
}

View File

@@ -1,9 +1,64 @@
#include <poincare/trigonometry.h>
#include <poincare/simplification_root.h>
#include <poincare/hyperbolic_cosine.h>
#include <poincare/complex.h>
#include <poincare/symbol.h>
#include <poincare/rational.h>
#include <poincare/multiplication.h>
#include <ion.h>
extern "C" {
#include <assert.h>
}
#include <cmath>
namespace Poincare {
Expression * Trigonometry::immediateSimplify() {
Expression * lookup = Trigonometry::table(operand(0), trigonometricFunctionType(), false);
if (lookup != nullptr) {
return replaceWith(lookup, true);
}
if (operand(0)->sign() < 0) {
((Expression *)operand(0))->turnIntoPositive();
((Expression *)operand(0))->immediateSimplify();
if (trigonometricFunctionType() == Trigonometry::Function::Cosine) {
return immediateSimplify();
} else if (trigonometricFunctionType() == Trigonometry::Function::Sine) {
const Expression * multOperands[2] = {new Rational(Integer(-1)), clone()};
Multiplication * m = new Multiplication(multOperands, 2, false);
((Expression *)m->operand(1))->immediateSimplify();
return replaceWith(m, true)->immediateSimplify();
}
assert(false);
}
if (operand(0)->type() == Type::Multiplication && operand(0)->operand(1)->type() == Type::Symbol && static_cast<const Symbol *>(operand(0)->operand(1))->name() == Ion::Charset::SmallPi && operand(0)->operand(0)->type() == Type::Rational) {
Rational * r = static_cast<Rational *>((Expression *)operand(0)->operand(0));
// Replace argument in [0, Pi[
if (r->denominator().isLowerThan(r->numerator())) {
IntegerDivision div = Integer::Division(r->numerator(), r->denominator());
// For Sine, replace argument in [0, Pi/2[
if (trigonometricFunctionType() == Trigonometry::Function::Sine && r->denominator().isLowerThan(Integer::Addition(div.remainder, div.remainder))) {
div.remainder = Integer::Subtraction(r->denominator(), div.remainder);
}
Rational * newR = new Rational(div.remainder, r->denominator());
const_cast<Expression *>(operand(0))->replaceOperand(r, newR, true);
const_cast<Expression *>(operand(0))->immediateSimplify();
if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) {
Expression * simplifiedCosine = immediateSimplify(); // recursive
const Expression * multOperands[2] = {new Rational(Integer(-1)), simplifiedCosine->clone()};
Multiplication * m = new Multiplication(multOperands, 2, false);
return simplifiedCosine->replaceWith(m, true)->immediateSimplify();
} else {
return immediateSimplify(); // recursive
}
}
assert(r->sign() > 0);
assert(r->numerator().isLowerThan(r->denominator()));
}
return this;
}
static_assert('\x89' == Ion::Charset::SmallPi, "Incorrect");
constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] =
{{"\x89", "\x89*(-2)^(-1)", "-1"},