extern "C" { #include #include } #include #include #include #include #include "layout/baseline_relative_layout.h" namespace Poincare { Expression::Type Power::type() const { return Type::Power; } Expression * Power::cloneWithDifferentOperands(Expression** newOperands, int numberOfOperands, bool cloneOperands) const { assert(numberOfOperands == 2); return new Power(newOperands, cloneOperands); } ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); Expression * indiceOperand = m_operands[1]; // Delete eventual parentheses of the indice in the pretty print if (m_operands[1]->type() == Type::Parenthesis) { indiceOperand = (Expression *)m_operands[1]->operand(0); } return new BaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); } template Complex Power::compute(const Complex c, const Complex d) { // c == c.r * e^(c.th*i) // d == d.a + d.b*i // c^d == e^(ln(c^d)) // == e^(ln(c) * d) // == e^(ln(c.r * e^(c.th*i)) * (d.a + d.b*i)) // == e^((ln(c.r) + ln(e^(c.th*i))) * (d.a + d.b*i)) // == e^((ln(c.r) + c.th*i) * (d.a + d.b*i)) // == e^(ln(c.r)*d.a + ln(c.r)*d.b*i + c.th*i*d.a + c.th*i*d.b*i) // == e^((ln(c.r^d.a) + ln(e^(c.th*d.b*i^2))) + (ln(c.r)*d.b + c.th*d.a)*i) // == e^(ln(c.r^d.a * e^(-c.th*d.b))) * e^((ln(c.r)*d.b + c.th*d.a)*i) // == c.r^d.a*e^(-c.th*d.b) * e^((ln(c.r)*d.b + c.th*d.a)*i) if (c.a() == 0 && c.b() == 0) { // ln(c.r) and c.th are undefined return Complex::Float(d.a() > 0 ? 0 : NAN); } T radius = std::pow(c.r(), d.a()) * std::exp(-c.th() * d.b()); T theta = std::log(c.r())*d.b() + c.th()*d.a(); return Complex::Polar(radius, theta); } template Evaluation * Power::templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { if (m->numberOfRows() != m->numberOfColumns()) { return new Complex(Complex::Float(NAN)); } T power = d->toScalar(); if (std::isnan(power) || std::isinf(power) || power != (int)power || std::fabs(power) > k_maxNumberOfSteps) { return new Complex(Complex::Float(NAN)); } if (power < 0) { Evaluation * inverse = m->createInverse(); Complex minusC = Opposite::compute(*d); Evaluation * result = Power::computeOnComplexMatrixAndComplex(inverse, &minusC); delete inverse; return result; } Evaluation * result = ComplexMatrix::createIdentity(m->numberOfRows()); // TODO: implement a quick exponentiation for (int k = 0; k < (int)power; k++) { if (shouldStopProcessing()) { delete result; return new Complex(Complex::Float(NAN)); } result = Multiplication::computeOnMatrices(result, m); } return result; } template Evaluation * Power::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { return new Complex(Complex::Float(NAN)); } template Evaluation * Power::templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const { return new Complex(Complex::Float(NAN)); } template Complex Power::compute(Complex, Complex); template Complex Power::compute(Complex, Complex); }