Numworks Epsilon  1.4.1
Graphing Calculator Operating System
multiplication.cpp
Go to the documentation of this file.
1 extern "C" {
2 #include <assert.h>
3 #include <stdlib.h>
4 }
5 #include <cmath>
6 
8 #include <poincare/rational.h>
9 #include <poincare/addition.h>
10 #include <poincare/power.h>
11 #include <poincare/opposite.h>
12 #include <poincare/undefined.h>
13 #include <poincare/parenthesis.h>
14 #include <poincare/subtraction.h>
15 #include <poincare/tangent.h>
16 #include <poincare/division.h>
17 #include <poincare/arithmetic.h>
19 #include <poincare/matrix.h>
20 #include <ion.h>
21 #include "layout/string_layout.h"
24 
25 namespace Poincare {
26 
29 }
30 
32  if (numberOfOperands() == 0) {
33  return new Multiplication();
34  }
35  return new Multiplication(operands(), numberOfOperands(), true);
36 }
37 
38 int Multiplication::polynomialDegree(char symbolName) const {
39  int degree = 0;
40  for (int i = 0; i < numberOfOperands(); i++) {
41  int d = operand(i)->polynomialDegree(symbolName);
42  if (d < 0) {
43  return -1;
44  }
45  degree += d;
46  }
47  return degree;
48 }
49 
50 bool Multiplication::needParenthesisWithParent(const Expression * e) const {
52  return e->isOfType(types, 3);
53 }
54 
55 ExpressionLayout * Multiplication::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const {
56  const char middleDotString[] = {Ion::Charset::MiddleDot, 0};
57  return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, middleDotString);
58 }
59 
60 int Multiplication::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const {
61  const char multiplicationString[] = {Ion::Charset::MultiplicationSign, 0};
62  return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, multiplicationString);
63 }
64 
66  int sign = 1;
67  for (int i = 0; i < numberOfOperands(); i++) {
68  sign *= (int)operand(i)->sign();
69  }
70  return (Sign)sign;
71 }
72 
73 Expression * Multiplication::setSign(Sign s, Context & context, AngleUnit angleUnit) {
74  assert(s == Sign::Positive);
75  for (int i = 0; i < numberOfOperands(); i++) {
76  if (operand(i)->sign() == Sign::Negative) {
77  editableOperand(i)->setSign(s, context, angleUnit);
78  }
79  }
80  return shallowReduce(context, angleUnit);
81 }
82 
83 template<typename T>
85  return Complex<T>::Cartesian(c.a()*d.a()-c.b()*d.b(), c.b()*d.a() + c.a()*d.b());
86 }
87 
88 template<typename T>
90  if (m->numberOfColumns() != n->numberOfRows()) {
91  return nullptr;
92  }
94  for (int i = 0; i < m->numberOfRows(); i++) {
95  for (int j = 0; j < n->numberOfColumns(); j++) {
96  T a = 0.0f;
97  T b = 0.0f;
98  for (int k = 0; k < m->numberOfColumns(); k++) {
99  const Complex<T> * mEntry = static_cast<const Complex<T> *>(m->operand(i*m->numberOfColumns()+k));
100  const Complex<T> * nEntry = static_cast<const Complex<T> *>(n->operand(k*n->numberOfColumns()+j));
101  a += mEntry->a()*nEntry->a() - mEntry->b()*nEntry->b();
102  b += mEntry->b()*nEntry->a() + mEntry->a()*nEntry->b();
103  }
105  }
106  }
107  Matrix * result = new Matrix(operands, m->numberOfRows(), n->numberOfColumns(), false);
108  delete[] operands;
109  return result;
110 }
111 
112 bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Expression * e2) {
113  int numberOfNonRationalFactors1 = e1->operand(0)->type() == Type::Rational ? e1->numberOfOperands()-1 : e1->numberOfOperands();
114  int numberOfNonRationalFactors2 = e2->operand(0)->type() == Type::Rational ? e2->numberOfOperands()-1 : e2->numberOfOperands();
115  if (numberOfNonRationalFactors1 != numberOfNonRationalFactors2) {
116  return false;
117  }
118  int firstNonRationalOperand1 = e1->operand(0)->type() == Type::Rational ? 1 : 0;
119  int firstNonRationalOperand2 = e2->operand(0)->type() == Type::Rational ? 1 : 0;
120  for (int i = 0; i < numberOfNonRationalFactors1; i++) {
121  if (!(e1->operand(firstNonRationalOperand1+i)->isIdenticalTo(e2->operand(firstNonRationalOperand2+i)))) {
122  return false;
123  }
124  }
125  return true;
126 }
127 
128 static inline const Expression * Base(const Expression * e) {
129  if (e->type() == Expression::Type::Power) {
130  return e->operand(0);
131  }
132  return e;
133 }
134 
135 Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit) {
136  return privateShallowReduce(context, angleUnit, true, true);
137 }
138 
139 Expression * Multiplication::privateShallowReduce(Context & context, AngleUnit angleUnit, bool shouldExpand, bool canBeInterrupted) {
140  Expression * e = Expression::shallowReduce(context, angleUnit);
141  if (e != this) {
142  return e;
143  }
144  /* Step 1: Multiplication is associative, so let's start by merging children
145  * which also are multiplications themselves. */
146  mergeMultiplicationOperands();
147 
148  /* Step 2: If any of the operand is zero, the multiplication result is zero */
149  for (int i = 0; i < numberOfOperands(); i++) {
150  const Expression * o = operand(i);
151  if (o->type() == Type::Rational && static_cast<const Rational *>(o)->isZero()) {
152  return replaceWith(new Rational(0), true);
153  }
154  }
155 
156  // Step 3: Sort the operands
157  sortOperands(SimplificationOrder, canBeInterrupted);
158 
159 #if MATRIX_EXACT_REDUCING
160  /* Step 3bis: get rid of matrix */
161  int n = 1;
162  int m = 1;
163  /* All operands have been simplified so if any operand contains a matrix, it
164  * is at the root node of the operand. Moreover, thanks to the simplification
165  * order, all matrix operands (if any) are the last operands. */
166  Expression * lastOperand = editableOperand(numberOfOperands()-1);
167  if (lastOperand->type() == Type::Matrix) {
168  Matrix * resultMatrix = static_cast<Matrix *>(lastOperand);
169  // Use the last matrix operand as the final matrix
170  n = resultMatrix->numberOfRows();
171  m = resultMatrix->numberOfColumns();
172  /* Scan accross the multiplication operands to find any other matrix:
173  * (the last operand is the result matrix so we start at
174  * numberOfOperands()-2)*/
175  int k = numberOfOperands()-2;
176  while (k >= 0 && operand(k)->type() == Type::Matrix) {
177  Matrix * currentMatrix = static_cast<Matrix *>(editableOperand(k));
178  int on = currentMatrix->numberOfRows();
179  int om = currentMatrix->numberOfColumns();
180  if (om != n) {
181  return replaceWith(new Undefined(), true);
182  }
183  // Create the matrix resulting of the multiplication of the current matrix and the result matrix
184  /* resultMatrix
185  * i2= 0..m
186  * +-+-+-+-+-+
187  * | | | | | |
188  * +-+-+-+-+-+
189  * j=0..n | | | | | |
190  * +-+-+-+-+-+
191  * | | | | | |
192  * +-+-+-+-+-+
193  * currentMatrix
194  * j=0..om
195  * +---+---+---+ +-+-+-+-+-+
196  * |  |   |  | | | | | | |
197  * +---+---+---+ +-+-+-+-+-+
198  *i1=0..on |  |   |  | | |e| | | |
199  * +---+---+---+ +-+-+-+-+-+
200  * |   |   | | | | | | | |
201  * +---+---+---+ +-+-+-+-+-+
202  * */
203  Expression ** newMatrixOperands = new Expression * [on*m];
204  for (int e = 0; e < on*m; e++) {
205  newMatrixOperands[e] = new Addition();
206  int i2 = e%m;
207  int i1 = e/m;
208  for (int j = 0; j < n; j++) {
209  Expression * mult = new Multiplication(currentMatrix->editableOperand(j+om*i1), resultMatrix->editableOperand(j*m+i2), true);
210  static_cast<Addition *>(newMatrixOperands[e])->addOperand(mult);
211  mult->shallowReduce(context, angleUnit);
212  }
213  Reduce(&newMatrixOperands[e], context, angleUnit, false);
214  }
215  n = on;
216  removeOperand(currentMatrix, true);
217  resultMatrix = static_cast<Matrix *>(resultMatrix->replaceWith(new Matrix(newMatrixOperands, n, m, false), true));
218  k--;
219  }
220  removeOperand(resultMatrix, false);
221  // Distribute the remaining multiplication on matrix operands
222  for (int i = 0; i < n*m; i++) {
223  Multiplication * m = static_cast<Multiplication *>(clone());
224  Expression * entryI = resultMatrix->editableOperand(i);
225  resultMatrix->replaceOperand(entryI, m, false);
226  m->addOperand(entryI);
227  m->shallowReduce(context, angleUnit);
228  }
229  return replaceWith(resultMatrix, true)->shallowReduce(context, angleUnit);
230  }
231 #endif
232 
233  /* Step 4: Gather like terms. For example, turn pi^2*pi^3 into pi^5. Thanks to
234  * the simplification order, such terms are guaranteed to be next to each
235  * other. */
236  int i = 0;
237  while (i < numberOfOperands()-1) {
238  Expression * oi = editableOperand(i);
239  Expression * oi1 = editableOperand(i+1);
240  if (TermsHaveIdenticalBase(oi, oi1)) {
241  bool shouldFactorizeBase = true;
242  if (TermHasRationalBase(oi)) {
243  /* Combining powers of a given rational isn't straightforward. Indeed,
244  * there are two cases we want to deal with:
245  * - 2*2^(1/2) or 2*2^pi, we want to keep as-is
246  * - 2^(1/2)*2^(3/2) we want to combine. */
247  shouldFactorizeBase = oi->type() == Type::Power && oi1->type() == Type::Power;
248  }
249  if (shouldFactorizeBase) {
250  factorizeBase(oi, oi1, context, angleUnit);
251  continue;
252  }
253  } else if (TermHasRationalBase(oi) && TermHasRationalBase(oi1) && TermsHaveIdenticalExponent(oi, oi1)) {
254  factorizeExponent(oi, oi1, context, angleUnit);
255  continue;
256  }
257  i++;
258  }
259 
260  /* Step 5: We look for terms of form sin(x)^p*cos(x)^q with p, q rational of
261  *opposite signs. We replace them by either:
262  * - tan(x)^p*cos(x)^(p+q) if |p|<|q|
263  * - tan(x)^(-q)*sin(x)^(p+q) otherwise */
264  for (int i = 0; i < numberOfOperands(); i++) {
265  Expression * o1 = editableOperand(i);
266  if (Base(o1)->type() == Type::Sine && TermHasRationalExponent(o1)) {
267  const Expression * x = Base(o1)->operand(0);
268  /* Thanks to the SimplificationOrder, Cosine-base factors are after
269  * Sine-base factors */
270  for (int j = i+1; j < numberOfOperands(); j++) {
271  Expression * o2 = editableOperand(j);
272  if (Base(o2)->type() == Type::Cosine && TermHasRationalExponent(o2) && Base(o2)->operand(0)->isIdenticalTo(x)) {
273  factorizeSineAndCosine(o1, o2, context, angleUnit);
274  break;
275  }
276  }
277  }
278  }
279  /* Replacing sin/cos by tan factors may have mixed factors and factors are
280  * guaranteed to be sorted (according ot SimplificationOrder) at the end of
281  * shallowReduce */
283 
284  /* Step 6: We remove rational operands that appeared in the middle of sorted
285  * operands. It's important to do this after having factorized because
286  * factorization can lead to new ones. Indeed:
287  * pi^(-1)*pi-> 1
288  * i*i -> -1
289  * 2^(1/2)*2^(1/2) -> 2
290  * sin(x)*cos(x) -> 1*tan(x)
291  * Last, we remove the only rational operand if it is one and not the only
292  * operand. */
293  i = 1;
294  while (i < numberOfOperands()) {
295  Expression * o = editableOperand(i);
296  if (o->type() == Type::Rational && static_cast<Rational *>(o)->isOne()) {
297  removeOperand(o, true);
298  continue;
299  }
300  if (o->type() == Type::Rational) {
301  if (operand(0)->type() == Type::Rational) {
302  Rational * o0 = static_cast<Rational *>(editableOperand(0));
303  Rational m = Rational::Multiplication(*o0, *(static_cast<Rational *>(o)));
304  replaceOperand(o0, new Rational(m), true);
305  removeOperand(o, true);
306  } else {
307  removeOperand(o, false);
308  addOperandAtIndex(o, 0);
309  }
310  continue;
311  }
312  i++;
313  }
314  if (operand(0)->type() == Type::Rational && static_cast<Rational *>(editableOperand(0))->isOne() && numberOfOperands() > 1) {
315  removeOperand(editableOperand(0), true);
316  }
317 
318 
319  /* Step 7: Expand multiplication over addition operands if any. For example,
320  * turn (a+b)*c into a*c + b*c. We do not want to do this step right now if
321  * the parent is a multiplication to avoid missing factorization such as
322  * (x+y)^(-1)*((a+b)*(x+y)).
323  * Note: This step must be done after Step 4, otherwise we wouldn't be able to
324  * reduce expressions such as (x+y)^(-1)*(x+y)(a+b). */
325  if (shouldExpand && parent()->type() != Type::Multiplication) {
326  for (int i=0; i<numberOfOperands(); i++) {
327  if (operand(i)->type() == Type::Addition) {
328  return distributeOnOperandAtIndex(i, context, angleUnit);
329  }
330  }
331  }
332 
333  // Step 8: Let's remove the multiplication altogether if it has one operand
334  Expression * result = squashUnaryHierarchy();
335 
336  return result;
337 }
338 
339 void Multiplication::mergeMultiplicationOperands() {
340  // Multiplication is associative: a*(b*c)->a*b*c
341  int i = 0;
342  int initialNumberOfOperands = numberOfOperands();
343  while (i < initialNumberOfOperands) {
344  Expression * o = editableOperand(i);
345  if (o->type() == Type::Multiplication) {
346  mergeOperands(static_cast<Multiplication *>(o)); // TODO: ensure that matrix operands are not swapped to implement MATRIX_EXACT_REDUCING
347  continue;
348  }
349  i++;
350  }
351 }
352 
353 void Multiplication::factorizeSineAndCosine(Expression * o1, Expression * o2, Context & context, AngleUnit angleUnit) {
354  assert(o1->parent() == this && o2->parent() == this);
355  /* This function turn sin(x)^p * cos(x)^q into either:
356  * - tan(x)^p*cos(x)^(p+q) if |p|<|q|
357  * - tan(x)^(-q)*sin(x)^(p+q) otherwise */
358  const Expression * x = Base(o1)->operand(0);
359  Rational p = o1->type() == Type::Power ? *(static_cast<Rational *>(o1->editableOperand(1))) : Rational(1);
360  Rational q = o2->type() == Type::Power ? *(static_cast<Rational *>(o2->editableOperand(1))) : Rational(1);
361  /* If p and q have the same sign, we cannot replace them by a tangent */
362  if ((int)p.sign()*(int)q.sign() > 0) {
363  return;
364  }
365  Rational sumPQ = Rational::Addition(p, q);
366  Rational absP = p;
367  absP.setSign(Sign::Positive);
368  Rational absQ = q;
369  absQ.setSign(Sign::Positive);
370  Expression * tan = new Tangent(x, true);
371  if (Rational::NaturalOrder(absP, absQ) < 0) {
372  if (o1->type() == Type::Power) {
373  o1->replaceOperand(o1->operand(0), tan, true);
374  } else {
375  replaceOperand(o1, tan, true);
376  o1 = tan;
377  }
378  o1->shallowReduce(context, angleUnit);
379  if (o2->type() == Type::Power) {
380  o2->replaceOperand(o2->operand(1), new Rational(sumPQ), true);
381  } else {
382  Expression * newO2 = new Power(o2, new Rational(sumPQ), false);
383  replaceOperand(o2, newO2, false);
384  o2 = newO2;
385  }
386  o2->shallowReduce(context, angleUnit);
387  } else {
388  if (o2->type() == Type::Power) {
389  o2->replaceOperand(o2->operand(1), new Rational(Rational::Multiplication(q, Rational(-1))), true);
390  o2->replaceOperand(o2->operand(0), tan, true);
391  } else {
392  Expression * newO2 = new Power(tan, new Rational(-1), false);
393  replaceOperand(o2, newO2, true);
394  o2 = newO2;
395  }
396  o2->shallowReduce(context, angleUnit);
397  if (o1->type() == Type::Power) {
398  o1->replaceOperand(o1->operand(1), new Rational(sumPQ), true);
399  } else {
400  Expression * newO1 = new Power(o1, new Rational(sumPQ), false);
401  replaceOperand(o1, newO1, false);
402  o1 = newO1;
403  }
404  o1->shallowReduce(context, angleUnit);
405  }
406 }
407 
408 void Multiplication::factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) {
409  /* This function factorizes two operands which have a common base. For example
410  * if this is Multiplication(pi^2, pi^3), then pi^2 and pi^3 could be merged
411  * and this turned into Multiplication(pi^5). */
412  assert(TermsHaveIdenticalBase(e1, e2));
413 
414  // Step 1: Find the new exponent
415  Expression * s = new Addition(CreateExponent(e1), CreateExponent(e2), false);
416 
417  // Step 2: Get rid of one of the operands
418  removeOperand(e2, true);
419 
420  // Step 3: Use the new exponent
421  Power * p = nullptr;
422  if (e1->type() == Type::Power) {
423  // If e1 is a power, replace the initial exponent with the new one
424  e1->replaceOperand(e1->operand(1), s, true);
425  p = static_cast<Power *>(e1);
426  } else {
427  // Otherwise, create a new Power node
428  p = new Power(e1, s, false);
429  replaceOperand(e1, p, false);
430  }
431 
432  // Step 4: Reduce the new power
433  s->shallowReduce(context, angleUnit); // pi^2*pi^3 -> pi^(2+3) -> pi^5
434  Expression * reducedP = p->shallowReduce(context, angleUnit); // pi^2*pi^-2 -> pi^0 -> 1
435  /* Step 5: Reducing the new power might have turned it into a multiplication,
436  * ie: 12^(1/2) -> 2*3^(1/2). In that case, we need to merge the multiplication
437  * node with this. */
438  if (reducedP->type() == Type::Multiplication) {
439  mergeMultiplicationOperands();
440  }
441 }
442 
443 void Multiplication::factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) {
444  /* This function factorizes operands which share a common exponent. For
445  * example, it turns Multiplication(2^x,3^x) into Multiplication(6^x). */
446  assert(e1->parent() == this && e2->parent() == this);
447 
448  const Expression * base1 = e1->operand(0)->clone();
449  const Expression * base2 = e2->operand(0);
450  e2->detachOperand(base2);
451  Expression * m = new Multiplication(base1, base2, false);
452  removeOperand(e2, true);
453  e1->replaceOperand(e1->operand(0), m, true);
454 
455  m->shallowReduce(context, angleUnit); // 2^x*3^x -> (2*3)^x -> 6^x
456  Expression * reducedE1 = e1->shallowReduce(context, angleUnit); // 2^x*(1/2)^x -> (2*1/2)^x -> 1
457  /* Reducing the new power might have turned it into a multiplication,
458  * ie: 12^(1/2) -> 2*3^(1/2). In that case, we need to merge the multiplication
459  * node with this. */
460  if (reducedE1->type() == Type::Multiplication) {
461  mergeMultiplicationOperands();
462  }
463 }
464 
465 Expression * Multiplication::distributeOnOperandAtIndex(int i, Context & context, AngleUnit angleUnit) {
466  // This function turns a*(b+c) into a*b + a*c
467  // We avoid deleting and creating a new addition
468  Addition * a = static_cast<Addition *>(editableOperand(i));
469  removeOperand(a, false);
470  for (int j = 0; j < a->numberOfOperands(); j++) {
471  Multiplication * m = static_cast<Multiplication *>(clone());
472  Expression * termJ = a->editableOperand(j);
473  a->replaceOperand(termJ, m, false);
474  m->addOperand(termJ);
475  m->shallowReduce(context, angleUnit); // pi^(-1)*(pi + x) -> pi^(-1)*pi + pi^(-1)*x -> 1 + pi^(-1)*x
476  }
477  replaceWith(a, true);
478  return a->shallowReduce(context, angleUnit); // Order terms, put under a common denominator if needed
479 }
480 
481 const Expression * Multiplication::CreateExponent(Expression * e) {
482  return e->type() == Type::Power ? e->operand(1)->clone() : new Rational(1);
483 }
484 
485 bool Multiplication::TermsHaveIdenticalBase(const Expression * e1, const Expression * e2) {
486  return Base(e1)->isIdenticalTo(Base(e2));
487 }
488 
489 bool Multiplication::TermsHaveIdenticalExponent(const Expression * e1, const Expression * e2) {
490  /* Note: We will return false for e1=2 and e2=Pi, even though one could argue
491  * that these have the same exponent whose value is 1. */
492  return e1->type() == Type::Power && e2->type() == Type::Power && (e1->operand(1)->isIdenticalTo(e2->operand(1)));
493 }
494 
495 bool Multiplication::TermHasRationalBase(const Expression * e) {
496  return Base(e)->type() == Type::Rational;
497 }
498 
499 bool Multiplication::TermHasRationalExponent(const Expression * e) {
500  if (e->type() != Type::Power) {
501  return true;
502  }
503  if (e->operand(1)->type() == Type::Rational) {
504  return true;
505  }
506  return false;
507 }
508 
509 Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleUnit) {
510  /* Beautifying a Multiplication consists in several possible operations:
511  * - Add Opposite ((-3)*x -> -(3*x), useful when printing fractions)
512  * - Adding parenthesis if needed (a*(b+c) is not a*b+c)
513  * - Creating a Division if there's either a term with a power of -1 (a.b^(-1)
514  * shall become a/b) or a non-integer rational term (3/2*a -> (3*a)/2). */
515 
516  // Step 1: Turn -n*A into -(n*A)
517  if (operand(0)->type() == Type::Rational && operand(0)->sign() == Sign::Negative) {
518  if (static_cast<const Rational *>(operand(0))->isMinusOne()) {
519  removeOperand(editableOperand(0), true);
520  } else {
521  editableOperand(0)->setSign(Sign::Positive, context, angleUnit);
522  }
524  Opposite * o = new Opposite(e, true);
525  e->replaceWith(o, true);
526  o->editableOperand(0)->shallowBeautify(context, angleUnit);
527  return o;
528  }
529 
530  /* Step 2: Merge negative powers: a*b^(-1)*c^(-pi)*d = a*(b*c^pi)^(-1)
531  * This also turns 2/3*a into 2*a*3^(-1) */
532  Expression * e = mergeNegativePower(context, angleUnit);
533  if (e->type() == Type::Power) {
534  return e->shallowBeautify(context, angleUnit);
535  }
536  assert(e == this);
537 
538  // Step 3: Add Parenthesis if needed
539  for (int i = 0; i < numberOfOperands(); i++) {
540  const Expression * o = operand(i);
541  if (o->type() == Type::Addition ) {
542  Parenthesis * p = new Parenthesis(o, false);
543  replaceOperand(o, p, false);
544  }
545  }
546 
547  // Step 4: Create a Division if needed
548  for (int i = 0; i < numberOfOperands(); i++) {
549  if (!(operand(i)->type() == Type::Power && operand(i)->operand(1)->type() == Type::Rational && static_cast<const Rational *>(operand(i)->operand(1))->isMinusOne())) {
550  continue;
551  }
552 
553  // Let's remove the denominator-to-be from this
554  Power * p = static_cast<Power *>(editableOperand(i));
555  Expression * denominatorOperand = p->editableOperand(0);
556  p->detachOperand(denominatorOperand);
557  removeOperand(p, true);
558 
559  Expression * numeratorOperand = shallowReduce(context, angleUnit);
560  // Delete parenthesis unnecessary on numerator
561  if (numeratorOperand->type() == Type::Parenthesis) {
562  numeratorOperand = numeratorOperand->replaceWith(numeratorOperand->editableOperand(0), true);
563  }
564  Expression * originalParent = numeratorOperand->parent();
565  Division * d = new Division(numeratorOperand, denominatorOperand, false);
566  originalParent->replaceOperand(numeratorOperand, d, false);
567  return d->shallowBeautify(context, angleUnit);
568  }
569 
570  return this;
571 }
572 
573 Expression * Multiplication::cloneDenominator(Context & context, AngleUnit angleUnit) const {
574  // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1
575  // WARNING: we do not want to change the expression but to create a new one.
576  SimplificationRoot root(clone());
577  Expression * e = ((Multiplication *)root.operand(0))->mergeNegativePower(context, angleUnit);
578  Expression * result = nullptr;
579  if (e->type() == Type::Power) {
580  result = static_cast<Power *>(e)->cloneDenominator(context, angleUnit);
581  } else {
582  assert(e->type() == Type::Multiplication);
583  for (int i = 0; i < e->numberOfOperands(); i++) {
584  // a*b^(-1)*... -> a*.../b
585  if (e->operand(i)->type() == Type::Power && e->operand(i)->operand(1)->type() == Type::Rational && static_cast<const Rational *>(e->operand(i)->operand(1))->isMinusOne()) {
586  Power * p = static_cast<Power *>(e->editableOperand(i));
587  result = p->editableOperand(0);
588  p->detachOperand((result));
589  }
590  }
591  }
592  root.detachOperand(e);
593  delete e;
594  return result;
595 }
596 
597 Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit angleUnit) {
598  Multiplication * m = new Multiplication();
599  // Special case for rational p/q: if q != 1, q should be at denominator
600  if (operand(0)->type() == Type::Rational && !static_cast<const Rational *>(operand(0))->denominator().isOne()) {
601  Rational * r = static_cast<Rational *>(editableOperand(0));
602  m->addOperand(new Rational(r->denominator()));
603  if (r->numerator().isOne()) {
604  removeOperand(r, true);
605  } else {
606  replaceOperand(r, new Rational(r->numerator()), true);
607  }
608  }
609  int i = 0;
610  while (i < numberOfOperands()) {
611  if (operand(i)->type() == Type::Power && operand(i)->operand(1)->sign() == Sign::Negative) {
612  Expression * e = editableOperand(i);
613  e->editableOperand(1)->setSign(Sign::Positive, context, angleUnit);
614  removeOperand(e, false);
615  m->addOperand(e);
616  e->shallowReduce(context, angleUnit);
617  } else {
618  i++;
619  }
620  }
621  if (m->numberOfOperands() == 0) {
622  delete m;
623  return this;
624  }
625  Power * p = new Power(m, new Rational(-1), false);
626  m->sortOperands(SimplificationOrder, true);
627  m->squashUnaryHierarchy();
628  addOperand(p);
630  return squashUnaryHierarchy();
631 }
632 
633 void Multiplication::addMissingFactors(Expression * factor, Context & context, AngleUnit angleUnit) {
634  if (factor->type() == Type::Multiplication) {
635  for (int j = 0; j < factor->numberOfOperands(); j++) {
636  addMissingFactors(factor->editableOperand(j), context, angleUnit);
637  }
638  return;
639  }
640  /* Special case when factor is a Rational: if 'this' has already a rational
641  * operand, we replace it by its LCM with factor ; otherwise, we simply add
642  * factor as an operand. */
643  if (numberOfOperands() > 0 && operand(0)->type() == Type::Rational && factor->type() == Type::Rational) {
644  Rational * f = static_cast<Rational *>(factor);
645  Rational * o = static_cast<Rational *>(editableOperand(0));
646  assert(f->denominator().isOne());
647  assert(o->denominator().isOne());
648  Integer i = f->numerator();
649  Integer j = o->numerator();
650  return replaceOperand(o, new Rational(Arithmetic::LCM(&i, &j)));
651  }
652  if (factor->type() != Type::Rational) {
653  /* If factor is not a rational, we merge it with the operand of identical
654  * base if any. Otherwise, we add it as an new operand. */
655  for (int i = 0; i < numberOfOperands(); i++) {
656  if (TermsHaveIdenticalBase(operand(i), factor)) {
657  Expression * sub = new Subtraction(CreateExponent(editableOperand(i)), CreateExponent(factor), false);
658  Reduce((Expression **)&sub, context, angleUnit);
659  if (sub->sign() == Sign::Negative) { // index[0] < index[1]
660  if (factor->type() == Type::Power) {
661  factor->replaceOperand(factor->editableOperand(1), new Opposite(sub, true), true);
662  } else {
663  factor = new Power(factor, new Opposite(sub, true), false);
664  }
665  factor->editableOperand(1)->shallowReduce(context, angleUnit);
666  factorizeBase(editableOperand(i), factor, context, angleUnit);
667  editableOperand(i)->shallowReduce(context, angleUnit);
668  } else if (sub->sign() == Sign::Unknown) {
669  factorizeBase(editableOperand(i), factor, context, angleUnit);
670  editableOperand(i)->shallowReduce(context, angleUnit);
671  } else {}
672  delete sub;
673  /* Reducing the new operand i can lead to creating a new multiplication
674  * (ie 2^(1+2*3^(1/2)) -> 2*2^(2*3^(1/2)). We thus have to get rid of
675  * nested multiplication: */
676  mergeMultiplicationOperands();
677  return;
678  }
679  }
680  }
681  addOperand(factor->clone());
683 }
684 
685 template Matrix * Multiplication::computeOnComplexAndMatrix<float>(Complex<float> const*, const Matrix*);
686 template Matrix * Multiplication::computeOnComplexAndMatrix<double>(Complex<double> const*, const Matrix*);
687 template Complex<float> Multiplication::compute<float>(Complex<float>, Complex<float>);
688 template Complex<double> Multiplication::compute<double>(Complex<double>, Complex<double>);
689 
690 }
int numberOfColumns() const
Definition: matrix.cpp:40
static int writeInfixExpressionTextInBuffer(const Expression *expression, char *buffer, int bufferSize, int numberOfDigits, const char *operatorName)
void removeOperand(const Expression *e, bool deleteAfterRemoval=true)
void addOperand(Expression *operand)
Expression * parent() const
Definition: expression.h:185
static Integer LCM(const Integer *i, const Integer *j)
Definition: arithmetic.cpp:6
static Complex< T > Cartesian(T a, T b)
Definition: complex.cpp:28
#define assert(e)
Definition: assert.h:9
friend class Multiplication
Definition: rational.h:12
Expression * replaceWith(Expression *newOperand, bool deleteAfterReplace=true)
Definition: expression.cpp:85
static Matrix * computeOnMatrices(const Matrix *m, const Matrix *n)
friend class SimplificationRoot
Definition: expression.h:74
#define T(x)
Definition: events.cpp:26
T a() const
Definition: complex.cpp:99
friend class Tangent
Definition: expression.h:29
static Rational Addition(const Rational &i, const Rational &j)
Definition: rational.cpp:104
Expression * clone() const override
c(generic_all_nodes)
Expression * editableOperand(int i)
Definition: expression.h:176
friend class Rational
Definition: expression.h:18
void addOperandAtIndex(Expression *operand, int index)
static int SimplificationOrder(const Expression *e1, const Expression *e2, bool canBeInterrupted=false)
Definition: expression.cpp:226
virtual int numberOfOperands() const =0
bool isIdenticalTo(const Expression *e) const
Definition: expression.h:219
static int NaturalOrder(const Rational &i, const Rational &j)
Definition: rational.cpp:127
friend class Multiplication
Definition: expression.h:20
const Expression *const * operands() const override
void mergeOperands(DynamicHierarchy *d)
int numberOfRows() const
Definition: matrix.cpp:36
static ExpressionLayout * createInfixLayout(const Expression *expression, PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat, const char *operatorName)
Type type() const override
static Complex< T > compute(const Complex< T > c, const Complex< T > d)
friend class Matrix
Definition: expression.h:73
virtual Sign sign() const
Definition: expression.h:195
void sortOperands(ExpressionOrder order, bool canBeInterrupted)
int polynomialDegree(char symbolName) const override
friend class Parenthesis
Definition: expression.h:63
Sign sign() const override
int numberOfOperands() const override
const Expression * operand(int i) const
Definition: expression.cpp:78
virtual int polynomialDegree(char symbolName) const
Definition: expression.cpp:202
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
#define tan(x)
Definition: math.h:197