mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-21 23:00:45 +01:00
[poincare] Imporve tangent to resolve tan/sin = 1/cos
Change-Id: I7e23c7f680b6702c373bcc78f553bcb0c22bd574
This commit is contained in:
@@ -40,6 +40,7 @@ private:
|
||||
int writeTextInBuffer(char * buffer, int bufferSize) const override;
|
||||
/* Simplification */
|
||||
void factorize(Context & context, AngleUnit angleUnit);
|
||||
bool resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit);
|
||||
void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit);
|
||||
void factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit);
|
||||
Expression * distributeOnChildAtIndex(int index, Context & context, AngleUnit angleUnit);
|
||||
@@ -47,6 +48,9 @@ private:
|
||||
static bool TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2);
|
||||
static bool TermHasRationalBase(const Expression * e);
|
||||
static bool TermHasIntegerExponent(const Expression * e);
|
||||
static bool TermIsARationalSquareRootOrRational(const Expression * e);
|
||||
static const Rational * RadicandInExpression(const Expression * e);
|
||||
static const Rational * RationalFactorInExpression(const Expression * e);
|
||||
static const Expression * CreateExponent(Expression * e);
|
||||
bool isUselessOperand(const Rational * r) override;
|
||||
// Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1
|
||||
|
||||
@@ -31,6 +31,7 @@ public:
|
||||
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(); }
|
||||
|
||||
// Arithmetic
|
||||
|
||||
@@ -13,6 +13,7 @@ public:
|
||||
};
|
||||
static Expression * immediateSimplifyDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit);
|
||||
static Expression * immediateSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit);
|
||||
static bool ExpressionIsEquivalentToTangent(const Expression * e);
|
||||
constexpr static int k_numberOfEntries = 31;
|
||||
static Expression * table(const Expression * e, Expression::Type type, Context & context, Expression::AngleUnit angleUnit); // , Function f, bool inverse
|
||||
};
|
||||
|
||||
@@ -23,7 +23,19 @@ Expression * Tangent::clone() const {
|
||||
}
|
||||
|
||||
Expression * Tangent::immediateSimplify(Context& context, AngleUnit angleUnit) {
|
||||
return Trigonometry::immediateSimplifyDirectFunction(this, context, angleUnit);
|
||||
Expression * newExpression = Trigonometry::immediateSimplifyDirectFunction(this, context, angleUnit);
|
||||
if (newExpression->type() == Type::Tangent) {
|
||||
const Expression * op[1] = {newExpression->operand(0)};
|
||||
Sine * s = new Sine(op, true);
|
||||
Cosine * c = new Cosine(op, true);
|
||||
const Expression * divisionOperands[2] = {s, c};
|
||||
Division * d = new Division(divisionOperands, false);
|
||||
c->immediateSimplify(context, angleUnit);
|
||||
s->immediateSimplify(context, angleUnit);
|
||||
newExpression = newExpression->replaceWith(d, true);
|
||||
return newExpression->simplify(context, angleUnit);
|
||||
}
|
||||
return newExpression;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -75,6 +75,14 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte
|
||||
return e;
|
||||
}
|
||||
|
||||
bool Trigonometry::ExpressionIsEquivalentToTangent(const Expression * e) {
|
||||
assert(Expression::Type::Power < Expression::Type::Sine);
|
||||
if (e->type() == Expression::Type::Multiplication && e->operand(1)->type() == Expression::Type::Sine && e->operand(0)->type() == Expression::Type::Power && e->operand(0)->operand(0)->type() == Expression::Type::Cosine && e->operand(0)->operand(1)->type() == Expression::Type::Rational && static_cast<const Rational *>(e->operand(0)->operand(1))->isMinusOne()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) {
|
||||
assert(e->type() == Expression::Type::ArcCosine || e->type() == Expression::Type::ArcSine || e->type() == Expression::Type::ArcTangent);
|
||||
if (e->type() != Expression::Type::ArcTangent) {
|
||||
@@ -84,15 +92,22 @@ Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Cont
|
||||
}
|
||||
}
|
||||
Expression::Type correspondingType = e->type() == Expression::Type::ArcCosine ? Expression::Type::Cosine : (e->type() == Expression::Type::ArcSine ? Expression::Type::Sine : Expression::Type::Tangent);
|
||||
float pi = angleUnit == Expression::AngleUnit::Radian ? M_PI : 180;
|
||||
if (e->operand(0)->type() == correspondingType) {
|
||||
float trigoOp = e->operand(0)->operand(0)->approximate<float>(context, angleUnit);
|
||||
float pi = angleUnit == Expression::AngleUnit::Radian ? M_PI : 180;
|
||||
if ((e->type() == Expression::Type::ArcCosine && trigoOp >= 0.0f && trigoOp <= pi) ||
|
||||
(e->type() == Expression::Type::ArcSine && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f) ||
|
||||
(e->type() == Expression::Type::ArcTangent && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f)) {
|
||||
return e->replaceWith(const_cast<Expression *>(e->operand(0)->operand(0)), true);
|
||||
}
|
||||
}
|
||||
// Special case for arctan(sin(x)/cos(x))
|
||||
if (e->type() == Expression::Type::ArcTangent && ExpressionIsEquivalentToTangent(e->operand(0))) {
|
||||
float trigoOp = e->operand(0)->operand(1)->operand(0)->approximate<float>(context, angleUnit);
|
||||
if (trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f) {
|
||||
return e->replaceWith(const_cast<Expression *>(e->operand(0)->operand(1)->operand(0)), true);
|
||||
}
|
||||
}
|
||||
Expression * lookup = Trigonometry::table(e->operand(0), e->type(), context, angleUnit);
|
||||
if (lookup != nullptr) {
|
||||
return e->replaceWith(lookup, true);
|
||||
|
||||
Reference in New Issue
Block a user