Numworks Epsilon  1.4.1
Graphing Calculator Operating System
power.cpp
Go to the documentation of this file.
1 extern "C" {
2 #include <assert.h>
3 #include <stdlib.h>
4 }
5 #include <cmath>
6 #include <math.h>
7 #include <ion.h>
10 #include <poincare/matrix.h>
11 #include <poincare/power.h>
12 #include <poincare/opposite.h>
13 #include <poincare/parenthesis.h>
14 #include <poincare/addition.h>
15 #include <poincare/undefined.h>
16 #include <poincare/square_root.h>
17 #include <poincare/nth_root.h>
18 #include <poincare/division.h>
20 #include <poincare/arithmetic.h>
21 #include <poincare/symbol.h>
22 #include <poincare/subtraction.h>
23 #include <poincare/cosine.h>
24 #include <poincare/sine.h>
27 
28 namespace Poincare {
29 
31  return Type::Power;
32 }
33 
35  return new Power(m_operands, true);
36 }
37 
39  if (shouldStopProcessing()) {
40  return Sign::Unknown;
41  }
42  if (operand(0)->sign() == Sign::Positive && operand(1)->sign() != Sign::Unknown) {
43  return Sign::Positive;
44  }
45  if (operand(0)->sign() == Sign::Negative && operand(1)->type() == Type::Rational) {
46  const Rational * r = static_cast<const Rational *>(operand(1));
47  if (r->denominator().isOne()) {
48  if (Integer::Division(r->numerator(), Integer(2)).remainder.isZero()) {
49  return Sign::Positive;
50  } else {
51  return Sign::Negative;
52  }
53  }
54  }
55  return Sign::Unknown;
56 }
57 
58 int Power::polynomialDegree(char symbolName) const {
59  Rational op0Deg = Rational(operand(0)->polynomialDegree(symbolName));
60  if (op0Deg.sign() == Sign::Negative) {
61  return -1;
62  }
63  if (operand(1)->type() == Type::Rational) {
64  op0Deg = Rational::Multiplication(op0Deg, *(static_cast<const Rational *>(operand(1))));
65  if (!op0Deg.denominator().isOne()) {
66  return -1;
67  }
69  return -1;
70  }
71  return op0Deg.numerator().extractedInt();
72  }
73  return -1;
74 }
75 
76 Expression * Power::setSign(Sign s, Context & context, AngleUnit angleUnit) {
77  assert(s == Sign::Positive);
79  editableOperand(0)->setSign(Sign::Positive, context, angleUnit);
80  return this;
81 }
82 
83 template<typename T>
85  // c == c.r * e^(c.th*i)
86  // d == d.a + d.b*i
87  // c^d == e^(ln(c^d))
88  // == e^(ln(c) * d)
89  // == e^(ln(c.r * e^(c.th*i)) * (d.a + d.b*i))
90  // == e^((ln(c.r) + ln(e^(c.th*i))) * (d.a + d.b*i))
91  // == e^((ln(c.r) + c.th*i) * (d.a + d.b*i))
92  // == e^(ln(c.r)*d.a + ln(c.r)*d.b*i + c.th*i*d.a + c.th*i*d.b*i)
93  // == e^((ln(c.r^d.a) + ln(e^(c.th*d.b*i^2))) + (ln(c.r)*d.b + c.th*d.a)*i)
94  // == e^(ln(c.r^d.a * e^(-c.th*d.b))) * e^((ln(c.r)*d.b + c.th*d.a)*i)
95  // == c.r^d.a*e^(-c.th*d.b) * e^((ln(c.r)*d.b + c.th*d.a)*i)
96  if (c.a() == 0 && c.b() == 0) { // ln(c.r) and c.th are undefined
97  return Complex<T>::Float(d.a() > 0 ? 0 : NAN);
98  }
99  T radius = std::pow(c.r(), d.a()) * std::exp(-c.th() * d.b());
100  T theta = std::log(c.r())*d.b() + c.th()*d.a();
101  return Complex<T>::Polar(radius, theta);
102 }
103 
104 template<typename T> Matrix * Power::computeOnMatrixAndComplex(const Matrix * m, const Complex<T> * d) {
105  if (m->numberOfRows() != m->numberOfColumns()) {
106  return nullptr;
107  }
108  T power = d->toScalar();
109  if (std::isnan(power) || std::isinf(power) || power != (int)power || std::fabs(power) > k_maxApproximatePowerMatrix) {
110  return nullptr;
111  }
112  if (power < 0) {
113  Matrix * inverse = m->createInverse<T>();
114  if (inverse == nullptr) {
115  return nullptr;
116  }
117  Complex<T> minusC = Opposite::compute(*d, AngleUnit::Default);
118  Matrix * result = Power::computeOnMatrixAndComplex(inverse, &minusC);
119  delete inverse;
120  return result;
121  }
122  Matrix * result = Matrix::createApproximateIdentity<T>(m->numberOfRows());
123  // TODO: implement a quick exponentiation
124  for (int k = 0; k < (int)power; k++) {
125  if (shouldStopProcessing()) {
126  delete result;
127  return nullptr;
128  }
129  Matrix * mult = Multiplication::computeOnMatrices<T>(result, m);
130  delete result;
131  result = mult;
132  }
133  return result;
134 }
135 
136 bool Power::needParenthesisWithParent(const Expression * e) const {
137  Type types[] = {Type::Power, Type::Factorial};
138  return e->isOfType(types, 2);
139 }
140 
141 ExpressionLayout * Power::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const {
142  assert(floatDisplayMode != PrintFloat::Mode::Default);
143  assert(complexFormat != ComplexFormat::Default);
144  const Expression * indiceOperand = m_operands[1];
145  // Delete eventual parentheses of the indice in the pretty print
146  if (m_operands[1]->type() == Type::Parenthesis) {
147  indiceOperand = m_operands[1]->operand(0);
148  }
149  return new BaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript);
150 }
151 
152 int Power::simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const {
153  int baseComparison = SimplificationOrder(operand(0), e->operand(0), canBeInterrupted);
154  if (baseComparison != 0) {
155  return baseComparison;
156  }
157  return SimplificationOrder(operand(1), e->operand(1), canBeInterrupted);
158 }
159 
160 int Power::simplificationOrderGreaterType(const Expression * e, bool canBeInterrupted) const {
161  int baseComparison = SimplificationOrder(operand(0), e, canBeInterrupted);
162  if (baseComparison != 0) {
163  return baseComparison;
164  }
165  Rational one(1);
166  return SimplificationOrder(operand(1), &one, canBeInterrupted);
167 }
168 
169 Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) {
170  Expression * e = Expression::shallowReduce(context, angleUnit);
171  if (e != this) {
172  return e;
173  }
174 #if MATRIX_EXACT_REDUCING
175  /* Step 0: get rid of matrix */
176  if (operand(1)->type() == Type::Matrix) {
177  return replaceWith(new Undefined(), true);
178  }
179  if (operand(0)->type() == Type::Matrix) {
180  Matrix * mat = static_cast<Matrix *>(editableOperand(0));
181  if (operand(1)->type() != Type::Rational || !static_cast<const Rational *>(operand(1))->denominator().isOne()) {
182  return replaceWith(new Undefined(), true);
183  }
184  Integer exponent = static_cast<const Rational *>(operand(1))->numerator();
185  if (mat->numberOfRows() != mat->numberOfColumns()) {
186  return replaceWith(new Undefined(), true);
187  }
188  if (exponent.isNegative()) {
189  editableOperand(1)->setSign(Sign::Positive, context, angleUnit);
190  Expression * newMatrix = shallowReduce(context, angleUnit);
191  Expression * parent = newMatrix->parent();
192  MatrixInverse * inv = new MatrixInverse(newMatrix, false);
193  parent->replaceOperand(newMatrix, inv, false);
194  return inv;
195  }
196  if (Integer::NaturalOrder(exponent, Integer(k_maxExactPowerMatrix)) > 0) {
197  return this;
198  }
199  int exp = exponent.extractedInt(); // Ok, because 0 < exponent < k_maxExactPowerMatrix
200  Matrix * id = Matrix::createIdentity(mat->numberOfRows());
201  if (exp == 0) {
202  return replaceWith(id, true);
203  }
204  Multiplication * result = new Multiplication(id, mat->clone());
205  // TODO: implement a quick exponentiation
206  for (int k = 1; k < exp; k++) {
207  result->addOperand(mat->clone());
208  }
209  replaceWith(result, true);
210  return result->shallowReduce(context, angleUnit);
211  }
212 #endif
213 
214  /* Step 0: if both operands are true complexes, the result is undefined.
215  * We can assert that evaluations is a complex as matrix are not simplified */
216  Complex<float> * op0 = static_cast<Complex<float> *>(operand(0)->approximate<float>(context, angleUnit));
217  Complex<float> * op1 = static_cast<Complex<float> *>(operand(1)->approximate<float>(context, angleUnit));
218  bool bothOperandsComplexes = op0->b() != 0 && op1->b() != 0;
219  delete op0;
220  delete op1;
221  if (bothOperandsComplexes) {
222  return replaceWith(new Undefined(), true);
223  }
224 
225  /* Step 1: We handle simple cases as x^0, x^1, 0^x and 1^x first for 2 reasons:
226  * - we can assert this step that there is no division by 0:
227  * for instance, 0^(-2)->undefined
228  * - we save computational time by early escaping for these cases. */
229  if (operand(1)->type() == Type::Rational) {
230  const Rational * b = static_cast<const Rational *>(operand(1));
231  // x^0
232  if (b->isZero()) {
233  // 0^0 = undef
234  if (operand(0)->type() == Type::Rational && static_cast<const Rational *>(operand(0))->isZero()) {
235  return replaceWith(new Undefined(), true);
236  }
237  /* Warning: in all other case but 0^0, we replace x^0 by one. This is
238  * almost always true except when x = 0. However, not substituting x^0 by
239  * one would prevent from simplifying many expressions like x/x->1. */
240  return replaceWith(new Rational(1), true);
241  }
242  // x^1
243  if (b->isOne()) {
244  return replaceWith(editableOperand(0), true);
245  }
246  }
247  if (operand(0)->type() == Type::Rational) {
248  Rational * a = static_cast<Rational *>(editableOperand(0));
249  // 0^x
250  if (a->isZero()) {
251  if (operand(1)->sign() == Sign::Positive) {
252  return replaceWith(new Rational(0), true);
253  }
254  if (operand(1)->sign() == Sign::Negative) {
255  return replaceWith(new Undefined(), true);
256  }
257  }
258  // 1^x
259  if (a->isOne()) {
260  return replaceWith(new Rational(1), true);
261  }
262  }
263 
264  /* Step 2: We look for square root and sum of square roots (two terms maximum
265  * so far) at the denominator and move them to the numerator. */
266  Expression * r = removeSquareRootsFromDenominator(context, angleUnit);
267  if (r) {
268  return r;
269  }
270 
271  if (operand(1)->type() == Type::Rational) {
272  const Rational * b = static_cast<const Rational *>(operand(1));
273  // i^(p/q)
274  if (operand(0)->type() == Type::Symbol && static_cast<const Symbol *>(operand(0))->name() == Ion::Charset::IComplex) {
276  return replaceWith(CreateNthRootOfUnity(r))->shallowReduce(context, angleUnit);
277  }
278  }
279  bool letPowerAtRoot = parentIsALogarithmOfSameBase();
280  if (operand(0)->type() == Type::Rational) {
281  Rational * a = static_cast<Rational *>(editableOperand(0));
282  // p^q with p, q rationals
283  if (!letPowerAtRoot && operand(1)->type() == Type::Rational) {
284  Rational * exp = static_cast<Rational *>(editableOperand(1));
285  /* First, we check that the simplification does not involve too complex power
286  * of integers (ie 3^999) that would take too much time to compute. */
287  if (RationalExponentShouldNotBeReduced(exp)) {
288  return this;
289  }
290  return simplifyRationalRationalPower(this, a, exp, context, angleUnit);
291  }
292  }
293  // e^(i*Pi*r) with r rational
294  if (!letPowerAtRoot && isNthRootOfUnity()) {
295  Expression * m = editableOperand(1);
296  detachOperand(m);
297  Expression * i = m->editableOperand(m->numberOfOperands()-1);
298  static_cast<Multiplication *>(m)->removeOperand(i, false);
299  if (angleUnit == AngleUnit::Degree) {
300  const Expression * pi = m->operand(m->numberOfOperands()-1);
301  m->replaceOperand(pi, new Rational(180), true);
302  }
303  Expression * cos = new Cosine(m, false);
304  m = m->shallowReduce(context, angleUnit);
305  Expression * sin = new Sine(m, true);
306  Expression * complexPart = new Multiplication(sin, i, false);
307  sin->shallowReduce(context, angleUnit);
308  Expression * a = new Addition(cos, complexPart, false);
309  cos->shallowReduce(context, angleUnit);
310  complexPart->shallowReduce(context, angleUnit);
311  return replaceWith(a, true)->shallowReduce(context, angleUnit);
312  }
313  // x^log(y,x)->y if y > 0
314  if (operand(1)->type() == Type::Logarithm) {
315  if (operand(1)->numberOfOperands() == 2 && operand(0)->isIdenticalTo(operand(1)->operand(1))) {
316  // y > 0
317  if (operand(1)->operand(0)->sign() == Sign::Positive) {
318  return replaceWith(editableOperand(1)->editableOperand(0), true);
319  }
320  }
321  // 10^log(y)
322  if (operand(1)->numberOfOperands() == 1 && operand(0)->type() == Type::Rational && static_cast<const Rational *>(operand(0))->isTen()) {
323  return replaceWith(editableOperand(1)->editableOperand(0), true);
324  }
325  }
326  // (a^b)^c -> a^(b*c) if a > 0 or c is integer
327  if (operand(0)->type() == Type::Power) {
328  Power * p = static_cast<Power *>(editableOperand(0));
329  // Check is a > 0 or c is Integer
330  if (p->operand(0)->sign() == Sign::Positive ||
331  (operand(1)->type() == Type::Rational && static_cast<Rational *>(editableOperand(1))->denominator().isOne())) {
332  return simplifyPowerPower(p, editableOperand(1), context, angleUnit);
333  }
334  }
335  // (a*b*c*...)^r ?
336  if (!letPowerAtRoot && operand(0)->type() == Type::Multiplication) {
337  Multiplication * m = static_cast<Multiplication *>(editableOperand(0));
338  // (a*b*c*...)^n = a^n*b^n*c^n*... if n integer
339  if (operand(1)->type() == Type::Rational && static_cast<Rational *>(editableOperand(1))->denominator().isOne()) {
340  return simplifyPowerMultiplication(m, editableOperand(1), context, angleUnit);
341  }
342  // (a*b*...)^r -> |a|^r*(sign(a)*b*...)^r if a rational
343  for (int i = 0; i < m->numberOfOperands(); i++) {
344  // a is signed and a != -1
345  if (m->operand(i)->sign() != Sign::Unknown && (m->operand(i)->type() != Type::Rational || !static_cast<const Rational *>(m->operand(i))->isMinusOne())) {
346  //if (m->operand(i)->sign() == Sign::Positive || m->operand(i)->type() == Type::Rational) {
347  Expression * r = editableOperand(1);
348  Expression * rCopy = r->clone();
349  Expression * factor = m->editableOperand(i);
350  if (factor->sign() == Sign::Negative) {
351  m->replaceOperand(factor, new Rational(-1), false);
352  factor->setSign(Sign::Positive, context, angleUnit);
353  } else {
354  m->removeOperand(factor, false);
355  }
356  m->shallowReduce(context, angleUnit);
357  Power * p = new Power(factor, rCopy, false);
358  Multiplication * root = new Multiplication(p, clone(), false);
359  p->shallowReduce(context, angleUnit);
360  root->editableOperand(1)->shallowReduce(context, angleUnit);
361  replaceWith(root, true);
362  return root->shallowReduce(context, angleUnit);
363  }
364  }
365  }
366  // a^(b+c) -> Rational(a^b)*a^c with a and b rational and a != 0
367  if (!letPowerAtRoot && operand(0)->type() == Type::Rational && !static_cast<const Rational *>(operand(0))->isZero() && operand(1)->type() == Type::Addition) {
368  Addition * a = static_cast<Addition *>(editableOperand(1));
369  // Check is b is rational
370  if (a->operand(0)->type() == Type::Rational) {
371  /* First, we check that the simplification does not involve too complex power
372  * of integers (ie 3^999) that would take too much time to compute. */
373  if (RationalExponentShouldNotBeReduced(static_cast<const Rational *>(a->operand(0)))) {
374  return this;
375  }
376  Power * p1 = static_cast<Power *>(clone());
377  replaceOperand(a, a->editableOperand(1), true);
378  Power * p2 = static_cast<Power *>(clone());
379  Multiplication * m = new Multiplication(p1, p2, false);
380  simplifyRationalRationalPower(p1, static_cast<Rational *>(p1->editableOperand(0)), static_cast<Rational *>(p1->editableOperand(1)->editableOperand(0)), context, angleUnit);
381  replaceWith(m, true);
382  return m->shallowReduce(context, angleUnit);
383  }
384  }
385 
386  // (a0+a1+...am)^n with n integer -> a^n+?a^(n-1)*b+?a^(n-2)*b^2+...+b^n (Multinome)
387  if (!letPowerAtRoot && operand(1)->type() == Type::Rational && static_cast<const Rational *>(operand(1))->denominator().isOne() && operand(0)->type() == Type::Addition) {
388  // Exponent n
389  Rational * nr = static_cast<Rational *>(editableOperand(1));
390  Integer n = nr->numerator();
391  n.setNegative(false);
392  /* if n is above 25, the resulting sum would have more than
393  * k_maxNumberOfTermsInExpandedMultinome terms so we do not expand it. */
394  if (Integer(k_maxNumberOfTermsInExpandedMultinome).isLowerThan(n) || n.isOne()) {
395  return this;
396  }
397  int clippedN = n.extractedInt(); // Authorized because n < k_maxNumberOfTermsInExpandedMultinome
398  // Number of terms in addition m
399  int m = operand(0)->numberOfOperands();
400  /* The multinome (a0+a2+...+a(m-1))^n has BinomialCoefficient(n+m-1,n) terms;
401  * we expand the multinome only when the number of terms in the resulting
402  * sum has less than k_maxNumberOfTermsInExpandedMultinome terms. */
403  if (k_maxNumberOfTermsInExpandedMultinome < BinomialCoefficient::compute(static_cast<double>(clippedN), static_cast<double>(clippedN+m-1))) {
404  return this;
405  }
406  Expression * result = editableOperand(0);
407  Expression * a = result->clone();
408  for (int i = 2; i <= clippedN; i++) {
409  if (result->type() == Type::Addition) {
410  Expression * a0 = new Addition();
411  for (int j = 0; j < a->numberOfOperands(); j++) {
412  Multiplication * m = new Multiplication(result, a->editableOperand(j), true);
413  SimplificationRoot rootM(m); // m need to have a parent when applying distributeOnOperandAtIndex
414  Expression * expandM = m->distributeOnOperandAtIndex(0, context, angleUnit);
415  rootM.detachOperands();
416  if (a0->type() == Type::Addition) {
417  static_cast<Addition *>(a0)->addOperand(expandM);
418  } else {
419  a0 = new Addition(a0, expandM, false);
420  }
421  SimplificationRoot rootA0(a0); // a0 need a parent to be reduced.
422  a0 = a0->shallowReduce(context, angleUnit);
423  rootA0.detachOperands();
424  }
425  result = result->replaceWith(a0, true);
426  } else {
427  Multiplication * m = new Multiplication(a, result, true);
428  SimplificationRoot root(m);
429  result = result->replaceWith(m->distributeOnOperandAtIndex(0, context, angleUnit), true);
430  result = result->shallowReduce(context, angleUnit);
431  root.detachOperands();
432  }
433  }
434  delete a;
435  if (nr->sign() == Sign::Negative) {
436  nr->replaceWith(new Rational(-1), true);
437  return shallowReduce(context, angleUnit);
438  } else {
439  return replaceWith(result, true);
440  }
441  }
442 #if 0
443  /* We could use the Newton formula instead which is quicker but not immediate
444  * to implement in the general case (Newton multinome). */
445  // (a+b)^n with n integer -> a^n+?a^(n-1)*b+?a^(n-2)*b^2+...+b^n (Newton)
446  if (!letPowerAtRoot && operand(1)->type() == Type::Rational && static_cast<const Rational *>(operand(1))->denominator().isOne() && operand(0)->type() == Type::Addition && operand(0)->numberOfOperands() == 2) {
447  Rational * nr = static_cast<Rational *>(editableOperand(1));
448  Integer n = nr->numerator();
449  n.setNegative(false);
450  if (Integer(k_maxExpandedBinome).isLowerThan(n) || n.isOne()) {
451  return this;
452  }
453  int clippedN = n.extractedInt(); // Authorized because n < k_maxExpandedBinome < k_maxNValue
456  Addition * a = new Addition();
457  for (int i = 0; i <= clippedN; i++) {
458  Rational * r = new Rational(static_cast<int>(BinomialCoefficient::compute(static_cast<double>(i), static_cast<double>(clippedN))));
459  Power * p0 = new Power(x0->clone(), new Rational(i), false);
460  Power * p1 = new Power(x1->clone(), new Rational(clippedN-i), false);
461  const Expression * operands[3] = {r, p0, p1};
462  Multiplication * m = new Multiplication(operands, 3, false);
463  p0->shallowReduce(context, angleUnit);
464  p1->shallowReduce(context, angleUnit);
465  a->addOperand(m);
466  m->shallowReduce(context, angleUnit);
467  }
468  if (nr->sign() == Sign::Negative) {
469  nr->replaceWith(new Rational(-1), true);
470  editableOperand(0)->replaceWith(a, true)->shallowReduce(context, angleUnit);
471  return shallowReduce(context, angleUnit);
472  } else {
473  return replaceWith(a, true)->shallowReduce(context, angleUnit);
474  }
475  }
476 #endif
477  return this;
478 }
479 
480 bool Power::parentIsALogarithmOfSameBase() const {
481  if (parent()->type() == Type::Logarithm && parent()->operand(0) == this) {
482  // parent = log(10^x)
483  if (parent()->numberOfOperands() == 1) {
484  if (operand(0)->type() == Type::Rational && static_cast<const Rational *>(operand(0))->isTen()) {
485  return true;
486  }
487  return false;
488  }
489  // parent = log(x^y,x)
490  if (operand(0)->isIdenticalTo(parent()->operand(1))) {
491  return true;
492  }
493  }
494  // parent = ln(e^x)
495  if (parent()->type() == Type::NaperianLogarithm && parent()->operand(0) == this && operand(0)->type() == Type::Symbol && static_cast<const Symbol *>(operand(0))->name() == Ion::Charset::Exponential) {
496  return true;
497  }
498  return false;
499 }
500 
501 Expression * Power::simplifyPowerPower(Power * p, Expression * e, Context& context, AngleUnit angleUnit) {
502  Expression * p0 = p->editableOperand(0);
503  Expression * p1 = p->editableOperand(1);
504  p->detachOperands();
505  Multiplication * m = new Multiplication(p1, e, false);
506  replaceOperand(e, m, false);
507  replaceOperand(p, p0, true);
508  m->shallowReduce(context, angleUnit);
509  return shallowReduce(context, angleUnit);
510 }
511 
512 Expression * Power::simplifyPowerMultiplication(Multiplication * m, Expression * r, Context& context, AngleUnit angleUnit) {
513  for (int index = 0; index < m->numberOfOperands(); index++) {
514  Expression * factor = m->editableOperand(index);
515  Power * p = new Power(factor, r, true); // We copy r and factor to avoid inheritance issues
516  m->replaceOperand(factor, p, true);
517  p->shallowReduce(context, angleUnit);
518  }
519  detachOperand(m);
520  return replaceWith(m, true)->shallowReduce(context, angleUnit); // delete r
521 }
522 
523 Expression * Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context& context, AngleUnit angleUnit) {
524  if (b->denominator().isOne()) {
525  Rational r = Rational::Power(*a, b->numerator());
526  return result->replaceWith(new Rational(r),true);
527  }
528  Expression * n = nullptr;
529  Expression * d = nullptr;
530  if (b->sign() == Sign::Negative) {
531  b->setSign(Sign::Positive);
532  n = CreateSimplifiedIntegerRationalPower(a->denominator(), b, false, context, angleUnit);
533  d = CreateSimplifiedIntegerRationalPower(a->numerator(), b, true, context, angleUnit);
534  } else {
535  n = CreateSimplifiedIntegerRationalPower(a->numerator(), b, false, context, angleUnit);
536  d = CreateSimplifiedIntegerRationalPower(a->denominator(), b, true, context, angleUnit);
537  }
538  Multiplication * m = new Multiplication(n, d, false);
539  result->replaceWith(m, true);
540  return m->shallowReduce(context, angleUnit);
541 }
542 
543 Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator, Context & context, AngleUnit angleUnit) {
544  assert(!i.isZero());
545  assert(r->sign() == Sign::Positive);
546  if (i.isOne()) {
547  return new Rational(1);
548  }
549  Integer absI = i;
550  absI.setNegative(false);
551  Integer factors[Arithmetic::k_maxNumberOfPrimeFactors];
552  Integer coefficients[Arithmetic::k_maxNumberOfPrimeFactors];
554 
555  if (coefficients[0].isMinusOne()) {
556  /* We could not break i in prime factor (either it might take too many
557  * factors or too much time). */
558  r->setSign(isDenominator ? Sign::Negative : Sign::Positive);
559  return new Power(new Rational(i), r->clone(), false);
560  }
561 
562  Integer r1(1);
563  Integer r2(1);
564  int index = 0;
565  while (!coefficients[index].isZero() && index < Arithmetic::k_maxNumberOfPrimeFactors) {
566  Integer n = Integer::Multiplication(coefficients[index], r->numerator());
567  IntegerDivision div = Integer::Division(n, r->denominator());
568  r1 = Integer::Multiplication(r1, Integer::Power(factors[index], div.quotient));
569  r2 = Integer::Multiplication(r2, Integer::Power(factors[index], div.remainder));
570  index++;
571  }
572  Rational * p1 = new Rational(r2);
573  Integer one = isDenominator ? Integer(-1) : Integer(1);
574  Rational * p2 = new Rational(one, r->denominator());
575  Power * p = new Power(p1, p2, false);
576  if (r1.isEqualTo(Integer(1)) && !i.isNegative()) {
577  return p;
578  }
579  Rational * r3 = isDenominator ? new Rational(Integer(1), r1) : new Rational(r1);
580  Multiplication * m = new Multiplication(r3, p, false);
581  if (r2.isOne()) {
582  m->removeOperand(p);
583  }
584  if (i.isNegative()) {
585  Expression * nthRootOfUnity = CreateNthRootOfUnity(*r);
586  m->addOperand(nthRootOfUnity);
587  nthRootOfUnity->shallowReduce(context, angleUnit);
588 
589  }
590  m->sortOperands(SimplificationOrder, false);
591  return m;
592 }
593 
594 Expression * Power::CreateNthRootOfUnity(const Rational r) {
596  const Symbol * iComplex = new Symbol(Ion::Charset::IComplex);
597  const Symbol * pi = new Symbol(Ion::Charset::SmallPi);
598  const Expression * multExpOperands[3] = {iComplex, pi, new Rational(r)};
599  Multiplication * mExp = new Multiplication(multExpOperands, 3, false);
600  mExp->sortOperands(SimplificationOrder, false);
601  return new Power(exp, mExp, false);
602 #if 0
603  const Symbol * iComplex = new Symbol(Ion::Charset::IComplex);
604  const Symbol * pi = new Symbol(Ion::Charset::SmallPi);
605  Expression * op = new Multiplication(pi, r->clone(), false);
606  Cosine * cos = new Cosine(op, false);
607  op = op->shallowReduce(context, angleUnit);
608  Sine * sin = new Sine(op, true);
609  Expression * m = new Multiplication(iComplex, sin, false);
610  sin->shallowReduce(context, angleUnit);
611  Expression * a = new Addition(cos, m, false);
612  cos->shallowReduce(context, angleUnit);
613  const Expression * multExpOperands[3] = {pi, r->clone()};
614 #endif
615 }
616 
617 Expression * Power::shallowBeautify(Context& context, AngleUnit angleUnit) {
618  // X^-y -> 1/(X->shallowBeautify)^y
619  if (operand(1)->sign() == Sign::Negative) {
620  Expression * p = cloneDenominator(context, angleUnit);
621  Division * d = new Division(new Rational(1), p, false);
622  p->shallowReduce(context, angleUnit);
623  replaceWith(d, true);
624  return d->shallowBeautify(context, angleUnit);
625  }
626  if (operand(1)->type() == Type::Rational && static_cast<const Rational *>(operand(1))->numerator().isOne()) {
627  Integer index = static_cast<const Rational *>(operand(1))->denominator();
628  if (index.isEqualTo(Integer(2))) {
629  const Expression * sqrtOperand[1] = {operand(0)};
630  SquareRoot * sqr = new SquareRoot(sqrtOperand, true);
631  return replaceWith(sqr, true);
632  }
633  const Expression * rootOperand[2] = {operand(0)->clone(), new Rational(index)};
634  NthRoot * nr = new NthRoot(rootOperand, false);
635  return replaceWith(nr, true);
636  }
637  // +(a,b)^c ->(+(a,b))^c
638  if (operand(0)->type() == Type::Addition || operand(0)->type() == Type::Multiplication) {
639  const Expression * o[1] = {operand(0)};
640  Parenthesis * p = new Parenthesis(o, true);
641  replaceOperand(operand(0), p, true);
642  }
643  return this;
644 }
645 
646 Expression * Power::cloneDenominator(Context & context, AngleUnit angleUnit) const {
647  if (operand(1)->sign() == Sign::Negative) {
648  Expression * denominator = clone();
649  Expression * newExponent = denominator->editableOperand(1)->setSign(Sign::Positive, context, angleUnit);
650  if (newExponent->type() == Type::Rational && static_cast<Rational *>(newExponent)->isOne()) {
651  delete denominator;
652  return operand(0)->clone();
653  }
654  return denominator;
655  }
656  return nullptr;
657 }
658 
659 bool Power::TermIsARationalSquareRootOrRational(const Expression * e) {
660  if (e->type() == Type::Rational) {
661  return true;
662  }
663  if (e->type() == Type::Power && e->operand(0)->type() == Type::Rational && e->operand(1)->type() == Type::Rational && static_cast<const Rational *>(e->operand(1))->isHalf()) {
664  return true;
665  }
666  if (e->type() == Type::Multiplication && e->numberOfOperands() == 2 && e->operand(0)->type() == Type::Rational && e->operand(1)->type() == Type::Power && e->operand(1)->operand(0)->type() == Type::Rational && e->operand(1)->operand(1)->type() == Type::Rational && static_cast<const Rational *>(e->operand(1)->operand(1))->isHalf()) {
667  return true;
668  }
669  return false;
670 }
671 
672 const Rational * Power::RadicandInExpression(const Expression * e) {
673  if (e->type() == Type::Rational) {
674  return nullptr;
675  } else if (e->type() == Type::Power) {
676  assert(e->type() == Type::Power);
677  assert(e->operand(0)->type() == Type::Rational);
678  return static_cast<const Rational *>(e->operand(0));
679  } else {
680  assert(e->type() == Type::Multiplication);
681  assert(e->operand(1)->type() == Type::Power);
682  assert(e->operand(1)->operand(0)->type() == Type::Rational);
683  return static_cast<const Rational *>(e->operand(1)->operand(0));
684  }
685 }
686 
687 const Rational * Power::RationalFactorInExpression(const Expression * e) {
688  if (e->type() == Type::Rational) {
689  return static_cast<const Rational *>(e);
690  } else if (e->type() == Type::Power) {
691  return nullptr;
692  } else {
693  assert(e->type() == Type::Multiplication);
694  assert(e->operand(0)->type() == Type::Rational);
695  return static_cast<const Rational *>(e->operand(0));
696  }
697 }
698 
699 Expression * Power::removeSquareRootsFromDenominator(Context & context, AngleUnit angleUnit) {
700  Expression * result = nullptr;
701 
702  if (operand(0)->type() == Type::Rational && operand(1)->type() == Type::Rational && (static_cast<const Rational *>(operand(1))->isHalf() || static_cast<const Rational *>(operand(1))->isMinusHalf())) {
703  /* We're considering a term of the form sqrt(p/q) (or 1/sqrt(p/q)), with
704  * p and q integers.
705  * We'll turn those into sqrt(p*q)/q (or sqrt(p*q)/p) . */
706  Integer p = static_cast<const Rational *>(operand(0))->numerator();
707  assert(!p.isZero()); // We eliminated case of form 0^(-1/2) at first step of shallowReduce
708  Integer q = static_cast<const Rational *>(operand(0))->denominator();
709  // We do nothing for terms of the form sqrt(p)
710  if (!q.isOne() || static_cast<const Rational *>(operand(1))->isMinusHalf()) {
711  Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(1, 2), false);
712  if (static_cast<const Rational *>(operand(1))->isHalf()) {
713  result = new Multiplication(new Rational(Integer(1), q), sqrt, false);
714  } else {
715  result = new Multiplication(new Rational(Integer(1), p), sqrt, false); // We use here the assertion that p != 0
716  }
717  sqrt->shallowReduce(context, angleUnit);
718  }
719  } else if (operand(1)->type() == Type::Rational && static_cast<const Rational *>(operand(1))->isMinusOne() && operand(0)->type() == Type::Addition && operand(0)->numberOfOperands() == 2 && TermIsARationalSquareRootOrRational(operand(0)->operand(0)) && TermIsARationalSquareRootOrRational(operand(0)->operand(1))) {
720  /* We're considering a term of the form
721  *
722  * 1/(n1/d1*sqrt(p1/q1) + n2/d2*sqrt(p2/q2))
723  *
724  * and we want to turn it into
725  *
726  * n1*q2*d1*d2^2*sqrt(p1*q1) - n2*q1*d2*d1^2*sqrt(p2*q2)
727  * -------------------------------------------------------
728  * n1^2*d2^2*p1*q2 - n2^2*d1^2*p2*q1
729  */
730  const Rational * f1 = RationalFactorInExpression(operand(0)->operand(0));
731  const Rational * f2 = RationalFactorInExpression(operand(0)->operand(1));
732  const Rational * r1 = RadicandInExpression(operand(0)->operand(0));
733  const Rational * r2 = RadicandInExpression(operand(0)->operand(1));
734  Integer n1 = (f1 ? f1->numerator() : Integer(1));
735  Integer d1 = (f1 ? f1->denominator() : Integer(1));
736  Integer p1 = (r1 ? r1->numerator() : Integer(1));
737  Integer q1 = (r1 ? r1->denominator() : Integer(1));
738  Integer n2 = (f2 ? f2->numerator() : Integer(1));
739  Integer d2 = (f2 ? f2->denominator() : Integer(1));
740  Integer p2 = (r2 ? r2->numerator() : Integer(1));
741  Integer q2 = (r2 ? r2->denominator() : Integer(1));
742 
743  // Compute the denominator = n1^2*d2^2*p1*q2 - n2^2*d1^2*p2*q1
744  Integer denominator = Integer::Subtraction(
747  Integer::Power(n1, Integer(2)),
748  Integer::Power(d2, Integer(2))),
749  Integer::Multiplication(p1, q2)),
752  Integer::Power(n2, Integer(2)),
753  Integer::Power(d1, Integer(2))),
754  Integer::Multiplication(p2, q1)));
755 
756  // Compute the numerator
757  Power * sqrt1 = new Power(new Rational(Integer::Multiplication(p1, q1)), new Rational(1, 2), false);
758  Power * sqrt2 = new Power(new Rational(Integer::Multiplication(p2, q2)), new Rational(1, 2), false);
759  Integer factor1 = Integer::Multiplication(
760  Integer::Multiplication(n1, d1),
761  Integer::Multiplication(Integer::Power(d2, Integer(2)), q2));
762  Multiplication * m1 = new Multiplication(new Rational(factor1), sqrt1, false);
763  Integer factor2 = Integer::Multiplication(
764  Integer::Multiplication(n2, d2),
765  Integer::Multiplication(Integer::Power(d1, Integer(2)), q1));
766  Multiplication * m2 = new Multiplication(new Rational(factor2), sqrt2, false);
767  Subtraction * numerator = nullptr;
768  if (denominator.isNegative()) {
769  numerator = new Subtraction(m2, m1, false);
770  denominator.setNegative(false);
771  } else {
772  numerator = new Subtraction(m1, m2, false);
773  }
774 
775  result = new Multiplication(numerator, new Rational(Integer(1), denominator), false);
776  numerator->deepReduce(context, angleUnit);
777  }
778 
779  if (result) {
780  replaceWith(result, true);
781  result = result->shallowReduce(context, angleUnit);
782  }
783  return result;
784 }
785 
786 bool Power::isNthRootOfUnity() const {
787  if (operand(0)->type() != Type::Symbol || static_cast<const Symbol *>(operand(0))->name() != Ion::Charset::Exponential) {
788  return false;
789  }
790  if (operand(1)->type() != Type::Multiplication) {
791  return false;
792  }
793  if (operand(1)->numberOfOperands() < 2 || operand(1)->numberOfOperands() > 3) {
794  return false;
795  }
796  const Expression * i = operand(1)->operand(operand(1)->numberOfOperands()-1);
797  if (i->type() != Type::Symbol || static_cast<const Symbol *>(i)->name() != Ion::Charset::IComplex) {
798  return false;
799  }
800  const Expression * pi = operand(1)->operand(operand(1)->numberOfOperands()-2);
801  if (pi->type() != Type::Symbol || static_cast<const Symbol *>(pi)->name() != Ion::Charset::SmallPi) {
802  return false;
803  }
804  if (numberOfOperands() == 2) {
805  return true;
806  }
807  if (operand(1)->operand(0)->type() == Type::Rational) {
808  return true;
809  }
810  return false;
811 }
812 
813 bool Power::RationalExponentShouldNotBeReduced(const Rational * r) {
814  Integer maxIntegerExponent = r->numerator();
815  maxIntegerExponent.setNegative(false);
816  if (Integer::NaturalOrder(maxIntegerExponent, Integer(k_maxIntegerPower)) > 0) {
817  return true;
818  }
819  return false;
820 }
821 
822 template Complex<float> Power::compute<float>(Complex<float>, Complex<float>);
823 template Complex<double> Power::compute<double>(Complex<double>, Complex<double>);
824 }
int numberOfColumns() const
Definition: matrix.cpp:40
static bool shouldStopProcessing()
Definition: expression.cpp:65
#define exp(x)
Definition: math.h:176
Expression * parent() const
Definition: expression.h:185
friend class Addition
Definition: power.h:16
static Integer Power(const Integer &i, const Integer &j)
Definition: integer.cpp:313
Matrix * createInverse() const
Definition: matrix.cpp:195
#define NAN
Definition: math.h:30
T toScalar() const
Definition: complex.cpp:173
constexpr Event Power
Definition: events.h:83
#define assert(e)
Definition: assert.h:9
#define isinf(x)
Definition: math.h:44
friend class Multiplication
Definition: rational.h:12
friend class Symbol
Definition: power.h:19
Expression * replaceWith(Expression *newOperand, bool deleteAfterReplace=true)
Definition: expression.cpp:85
Expression * approximate(Context &context, AngleUnit angleUnit=AngleUnit::Default) const
Definition: expression.cpp:338
friend class Sine
Definition: expression.h:27
static Matrix * createIdentity(int dim)
Definition: matrix.cpp:285
friend class SimplificationRoot
Definition: expression.h:74
#define x0
Definition: b_tgamma.c:86
#define T(x)
Definition: events.cpp:26
T a() const
Definition: complex.cpp:99
static Complex< T > Polar(T r, T theta)
Definition: complex.cpp:33
#define one
Definition: k_tan.c:68
const Expression *const * operands() const override
Sign sign() const override
Definition: power.cpp:38
friend class Multiplication
Definition: power.h:13
static Complex< T > compute(const Complex< T > c, AngleUnit angleUnit)
Definition: opposite.cpp:48
#define fabs(x)
Definition: math.h:178
friend class SquareRoot
Definition: power.h:15
virtual Expression * clone() const =0
const Integer denominator() const
Definition: rational.cpp:59
Sign sign() const override
Definition: rational.cpp:72
int polynomialDegree(char symbolName) const override
Definition: power.cpp:58
friend class NthRoot
Definition: power.h:14
c(generic_all_nodes)
Expression * editableOperand(int i)
Definition: expression.h:176
friend class Rational
Definition: expression.h:18
#define sin(x)
Definition: math.h:194
static int SimplificationOrder(const Expression *e1, const Expression *e2, bool canBeInterrupted=false)
Definition: expression.cpp:226
friend class Complex< float >
Definition: expression.h:80
#define log(x)
Definition: math.h:184
friend class Power
Definition: expression.h:21
virtual int numberOfOperands() const =0
friend class Subtraction
Definition: expression.h:70
bool isIdenticalTo(const Expression *e) const
Definition: expression.h:219
static constexpr int k_maxExtractableInteger
Definition: integer.h:73
#define pow(x, y)
Definition: math.h:190
static void PrimeFactorization(const Integer *i, Integer *outputFactors, Integer *outputCoefficients, int outputLength)
Definition: arithmetic.cpp:39
#define cos(x)
Definition: math.h:172
const Expression * m_operands[T]
Expression * clone() const override
Definition: power.cpp:34
const Integer numerator() const
Definition: rational.cpp:55
static constexpr int k_maxNumberOfPrimeFactors
Definition: arithmetic.h:15
ExpressionLayout * createLayout(PrintFloat::Mode floatDisplayMode=PrintFloat::Mode::Default, ComplexFormat complexFormat=ComplexFormat::Default) const
Definition: expression.cpp:244
static int NaturalOrder(const Integer &i, const Integer &j)
Definition: integer.cpp:212
#define isnan(x)
Definition: math.h:43
friend class Division
Definition: power.h:17
bool isOne() const
Definition: integer.h:68
int numberOfRows() const
Definition: matrix.cpp:36
static Complex< T > Float(T x)
Definition: complex.cpp:23
static Integer Subtraction(const Integer &i, const Integer &j)
Definition: integer.cpp:236
int numberOfOperands() const override
friend class Matrix
Definition: expression.h:73
virtual Sign sign() const
Definition: expression.h:195
static Complex< T > compute(const Complex< T > c, const Complex< T > d)
Definition: power.cpp:84
constexpr Event Multiplication
Definition: events.h:101
void detachOperand(const Expression *e)
Definition: expression.cpp:115
friend class Power
Definition: rational.h:11
friend class Parenthesis
Definition: expression.h:63
friend class MatrixInverse
Definition: expression.h:57
friend class Cosine
Definition: expression.h:28
static Integer Multiplication(const Integer &i, const Integer &j)
Definition: integer.cpp:240
const Expression * operand(int i) const
Definition: expression.cpp:78
static IntegerDivision Division(const Integer &numerator, const Integer &denominator)
Definition: integer.cpp:281
#define sqrt(x)
Definition: math.h:196
Type type() const override
Definition: power.cpp:30
virtual Type type() const =0
friend class Undefined
Definition: expression.h:17
void replaceOperand(const Expression *oldOperand, Expression *newOperand, bool deleteOldOperand=true)
Definition: expression.cpp:91
int extractedInt() const
Definition: integer.h:45