[poincare] Rule i^r -> e^(iPir') with r rational

Change-Id: I6453406e6888776844c0fe1ff0c7fe2a450d1f6e
This commit is contained in:
Émilie Feral
2017-11-16 16:22:34 +01:00
parent e651a62ddb
commit 6cb9ccbe63
3 changed files with 44 additions and 13 deletions

View File

@@ -40,7 +40,8 @@ private:
Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, AngleUnit angleUnit);
Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context & context, AngleUnit angleUnit);
Expression * removeSquareRootsFromDenominator(Context & context, AngleUnit angleUnit);
static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator);
static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator, Context & context, AngleUnit angleUnit);
static Expression * CreateNthRootOfUnity(const Rational r);
/* Evaluation */
constexpr static int k_maxApproximatePowerMatrix = 1000;
constexpr static int k_maxExactPowerMatrix = 100;

View File

@@ -190,6 +190,11 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) {
if (b->isOne()) {
return replaceWith(editableOperand(0), true);
}
// i^(p/q)
if (operand(0)->type() == Type::Symbol && static_cast<const Symbol *>(operand(0))->name() == Ion::Charset::IComplex) {
Rational r = Rational::Multiplication(*b, Rational(1, 2));
return replaceWith(CreateNthRootOfUnity(r))->shallowReduce(context, angleUnit);
}
}
if (operand(0)->type() == Type::Rational) {
Rational * a = static_cast<Rational *>(editableOperand(0));
@@ -310,18 +315,18 @@ Expression * Power::simplifyRationalRationalPower(Expression * result, Rational
Expression * d = nullptr;
if (b->sign() == Sign::Negative) {
b->setSign(Sign::Positive);
n = CreateSimplifiedIntegerRationalPower(a->denominator(), b, false);
d = CreateSimplifiedIntegerRationalPower(a->numerator(), b, true);
n = CreateSimplifiedIntegerRationalPower(a->denominator(), b, false, context, angleUnit);
d = CreateSimplifiedIntegerRationalPower(a->numerator(), b, true, context, angleUnit);
} else {
n = CreateSimplifiedIntegerRationalPower(a->numerator(), b, false);
d = CreateSimplifiedIntegerRationalPower(a->denominator(), b, true);
n = CreateSimplifiedIntegerRationalPower(a->numerator(), b, false, context, angleUnit);
d = CreateSimplifiedIntegerRationalPower(a->denominator(), b, true, context, angleUnit);
}
Multiplication * m = new Multiplication(n, d, false);
result->replaceWith(m, true);
return m->shallowReduce(context, angleUnit);
}
Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator) {
Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator, Context & context, AngleUnit angleUnit) {
assert(!i.isZero());
assert(r->sign() == Sign::Positive);
if (i.isOne()) {
@@ -359,18 +364,38 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r
m->removeOperand(p);
}
if (i.isNegative()) {
const Symbol * exp = new Symbol(Ion::Charset::Exponential);
const Symbol * iComplex = new Symbol(Ion::Charset::IComplex);
const Symbol * pi = new Symbol(Ion::Charset::SmallPi);
const Expression * multExpOperands[3] = {iComplex, pi, r->clone()};
Multiplication * mExp = new Multiplication(multExpOperands, 3, false);
Power * pExp = new Power(exp, mExp, false);
m->addOperand(pExp);
Expression * nthRootOfUnity = CreateNthRootOfUnity(*r);
m->addOperand(nthRootOfUnity);
nthRootOfUnity->shallowReduce(context, angleUnit);
}
m->sortOperands(SimplificationOrder);
return m;
}
Expression * Power::CreateNthRootOfUnity(const Rational r) {
const Symbol * exp = new Symbol(Ion::Charset::Exponential);
const Symbol * iComplex = new Symbol(Ion::Charset::IComplex);
const Symbol * pi = new Symbol(Ion::Charset::SmallPi);
const Expression * multExpOperands[3] = {iComplex, pi, new Rational(r)};
Multiplication * mExp = new Multiplication(multExpOperands, 3, false);
mExp->sortOperands(SimplificationOrder);
return new Power(exp, mExp, false);
#if 0
const Symbol * iComplex = new Symbol(Ion::Charset::IComplex);
const Symbol * pi = new Symbol(Ion::Charset::SmallPi);
Expression * op = new Multiplication(pi, r->clone(), false);
Cosine * cos = new Cosine(op, false);
op = op->shallowReduce(context, angleUnit);
Sine * sin = new Sine(op, true);
Expression * m = new Multiplication(iComplex, sin, false);
sin->shallowReduce(context, angleUnit);
Expression * a = new Addition(cos, m, false);
cos->shallowReduce(context, angleUnit);
const Expression * multExpOperands[3] = {pi, r->clone()};
#endif
}
Expression * Power::shallowBeautify(Context& context, AngleUnit angleUnit) {
// X^-y -> 1/(X->shallowBeautify)^y
if (operand(1)->sign() == Sign::Negative) {

View File

@@ -128,6 +128,11 @@ QUIZ_CASE(poincare_simplify_easy) {
assert_parsed_expression_simplify_to("R([[4,2][P/7,1]])", "[[2,R(2)][R(P/7),1]]");
assert_parsed_expression_simplify_to("tan([[P/3,0][P/7,P/6]])", "[[R(3),0][tan(P/7),R(3)/3]]");
/* Complex */
assert_parsed_expression_simplify_to("I", "I");
assert_parsed_expression_simplify_to("R(-33)", "R(33)*X^(IP/2)");
assert_parsed_expression_simplify_to("I^(3/5)", "X^(IP3/10)");
assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)");
assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25");
assert_parsed_expression_simplify_to("-1/3", "-1/3");