diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 37dd96caf..78cffbd22 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -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; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 5fa7cf33b..5c4de12a9 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -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(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(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) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index c0ca35b56..2723e776c 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -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");