Numworks Epsilon  1.4.1
Graphing Calculator Operating System
division.cpp
Go to the documentation of this file.
1 extern "C" {
2 #include <assert.h>
3 #include <string.h>
4 #include <float.h>
5 }
6 
7 #include <poincare/division.h>
8 #include <poincare/power.h>
9 #include <poincare/rational.h>
10 #include <poincare/tangent.h>
12 #include <poincare/opposite.h>
13 #include "layout/fraction_layout.h"
14 #include <cmath>
15 
16 namespace Poincare {
17 
19  return Type::Division;
20 }
21 
23  return new Division(m_operands, true);
24 }
25 
26 int Division::polynomialDegree(char symbolName) const {
27  if (operand(1)->polynomialDegree(symbolName) != 0) {
28  return -1;
29  }
30  return operand(0)->polynomialDegree(symbolName);
31 }
32 
33 bool Division::needParenthesisWithParent(const Expression * e) const {
35  return e->isOfType(types, 3);
36 }
37 
38 Expression * Division::shallowReduce(Context& context, AngleUnit angleUnit) {
39  Expression * e = Expression::shallowReduce(context, angleUnit);
40  if (e != this) {
41  return e;
42  }
43  Power * p = new Power(operand(1), new Rational(-1), false);
44  Multiplication * m = new Multiplication(operand(0), p, false);
46  p->shallowReduce(context, angleUnit);
47  replaceWith(m, true);
48  return m->shallowReduce(context, angleUnit);
49 }
50 
51 template<typename T>
53  /* We want to avoid multiplies in the middle of the calculation that could
54  * overflow.
55  * aa, ab, ba, bb, min, max = |d.a| <= |d.b| ? (c.a, c.b, -c.a, c.b, d.a, d.b)
56  * : (c.b, c.a, c.b, -c.a, d.b, d.a)
57  * c c.a+c.b*i d.a-d.b*i 1/max (c.a+c.b*i) * (d.a-d.b*i) / max
58  * - == --------- * --------- * ----- == -------------------------------
59  * d d.a+d.b*i d.a-d.b*i 1/max (d.a+d.b*i) * (d.a-d.b*i) / max
60  * (c.a*d.a - c.a*d.b*i + c.b*i*d.a - c.b*i*d.b*i) / max
61  * == -----------------------------------------------------
62  * (d.a*d.a - d.a*d.b*i + d.b*i*d.a - d.b*i*d.b*i) / max
63  * (c.a*d.a - c.b*d.b*i^2 + c.b*d.b*i - c.a*d.a*i) / max
64  * == -----------------------------------------------------
65  * (d.a*d.a - d.b*d.b*i^2) / max
66  * (c.a*d.a/max + c.b*d.b/max) + (c.b*d.b/max - c.a*d.a/max)*i
67  * == -----------------------------------------------------------
68  * d.a^2/max + d.b^2/max
69  * aa*min/max + ab*max/max bb*min/max + ba*max/max
70  * == ----------------------- + -----------------------*i
71  * min^2/max + max^2/max min^2/max + max^2/max
72  * min/max*aa + ab min/max*bb + ba
73  * == ----------------- + -----------------*i
74  * min/max*min + max min/max*min + max
75  * |min| <= |max| => |min/max| <= 1
76  * => |min/max*x| <= |x|
77  * => |min/max*x+y| <= |x|+|y|
78  * So the calculation is guaranteed to not overflow until the last divides as
79  * long as none of the input values have the representation's maximum exponent.
80  * Plus, the method does not propagate any error on real inputs: temp = 0,
81  * norm = d.a and then result = c.a/d.a. */
82  T aa = c.a(), ab = c.b(), ba = -aa, bb = ab;
83  T min = d.a(), max = d.b();
84  if (std::fabs(max) < std::fabs(min)) {
85  T temp = min;
86  min = max;
87  max = temp;
88  temp = aa;
89  aa = ab;
90  ab = temp;
91  temp = ba;
92  ba = bb;
93  bb = temp;
94  }
95  T temp = min/max;
96  T norm = temp*min + max;
97  return Complex<T>::Cartesian((temp*aa + ab) / norm, (temp*bb + ba) / norm);
98 }
99 
100 ExpressionLayout * Division::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const {
101  assert(floatDisplayMode != PrintFloat::Mode::Default);
102  assert(complexFormat != ComplexFormat::Default);
103  const Expression * numerator = operand(0)->type() == Type::Parenthesis ? operand(0)->operand(0) : operand(0);
104  const Expression * denominator = operand(1)->type() == Type::Parenthesis ? operand(1)->operand(0) : operand(1);
105  return new FractionLayout(numerator->createLayout(floatDisplayMode, complexFormat), denominator->createLayout(floatDisplayMode, complexFormat));
106 }
107 
108 template<typename T> Matrix * Division::computeOnComplexAndMatrix(const Complex<T> * c, const Matrix * n) {
109  Matrix * inverse = n->createInverse<T>();
110  if (inverse == nullptr) {
111  return nullptr;
112  }
113  Matrix * result = Multiplication::computeOnComplexAndMatrix<T>(c, inverse);
114  delete inverse;
115  return result;
116 }
117 
118 template<typename T> Matrix * Division::computeOnMatrices(const Matrix * m, const Matrix * n) {
119  if (m->numberOfColumns() != n->numberOfColumns()) {
120  return nullptr;
121  }
122  Matrix * inverse = n->createInverse<T>();
123  if (inverse == nullptr) {
124  return nullptr;
125  }
126  Matrix * result = Multiplication::computeOnMatrices<T>(m, inverse);
127  delete inverse;
128  return result;
129 }
130 
131 }
friend class Division
Definition: expression.h:25
static Complex< T > Cartesian(T a, T b)
Definition: complex.cpp:28
#define assert(e)
Definition: assert.h:9
Expression * replaceWith(Expression *newOperand, bool deleteAfterReplace=true)
Definition: expression.cpp:85
Type type() const override
Definition: division.cpp:18
#define T(x)
Definition: events.cpp:26
T a() const
Definition: complex.cpp:99
friend class Multiplication
Definition: division.h:12
#define fabs(x)
Definition: math.h:178
int polynomialDegree(char symbolName) const override
Definition: division.cpp:26
friend class Power
Definition: division.h:14
c(generic_all_nodes)
friend class Rational
Definition: expression.h:18
static Complex< T > compute(const Complex< T > c, const Complex< T > d)
Definition: division.cpp:52
const Expression * m_operands[T]
Expression * clone() const override
Definition: division.cpp:22
ExpressionLayout * createLayout(PrintFloat::Mode floatDisplayMode=PrintFloat::Mode::Default, ComplexFormat complexFormat=ComplexFormat::Default) const
Definition: expression.cpp:244
friend class Matrix
Definition: expression.h:73
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