Numworks Epsilon  1.4.1
Graphing Calculator Operating System
logarithm.cpp
Go to the documentation of this file.
1 #include <poincare/logarithm.h>
2 #include <poincare/division.h>
3 #include <poincare/undefined.h>
4 #include <poincare/rational.h>
5 #include <poincare/addition.h>
7 #include <poincare/symbol.h>
8 #include <poincare/arithmetic.h>
9 #include <poincare/power.h>
13 #include <cmath>
14 #include <ion.h>
15 extern "C" {
16 #include <assert.h>
17 #include <stdlib.h>
18 }
22 #include "layout/string_layout.h"
23 
24 namespace Poincare {
25 
27  return Type::Logarithm;
28 }
29 
31  return new Logarithm(operands(), numberOfOperands(), true);
32 }
33 
34 template<typename T>
35 Complex<T> Logarithm::computeOnComplex(const Complex<T> c, AngleUnit angleUnit) {
36  if (c.b() != 0) {
37  return Complex<T>::Float(NAN);
38  }
39  return Complex<T>::Float(std::log10(c.a()));
40 }
41 
42 Expression * Logarithm::simpleShallowReduce(Context & context, AngleUnit angleUnit) {
43  Expression * op = editableOperand(0);
44  if (op->sign() == Sign::Negative || (numberOfOperands() == 2 && operand(1)->sign() == Sign::Negative)) {
45  return replaceWith(new Undefined(), true);
46  }
47  // log(x,x)->1
48  if (numberOfOperands() == 2 && op->isIdenticalTo(operand(1))) {
49  return replaceWith(new Rational(1), true);
50  }
51  if (op->type() == Type::Rational) {
52  const Rational * r = static_cast<const Rational *>(operand(0));
53  // log(0) = undef
54  if (r->isZero()) {
55  return replaceWith(new Undefined(), true);
56  }
57  // log(1) = 0;
58  if (r->isOne()) {
59  return replaceWith(new Rational(0), true);
60  }
61  // log(10) ->1
62  if (numberOfOperands() == 1 && r->isTen()) {
63  return replaceWith(new Rational(1), true);
64  }
65  }
66  return this;
67 }
68 
69 Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) {
70  Expression * e = Expression::shallowReduce(context, angleUnit);
71  if (e != this) {
72  return e;
73  }
74  Expression * op = editableOperand(0);
75 #if MATRIX_EXACT_REDUCING
76  if (numberOfOperands() == 1 && op->type() == Type::Matrix) {
77  return SimplificationEngine::map(this, context, angleUnit);
78  }
79  if (numberOfOperands() == 2 && (op->type() == Type::Matrix || operand(1)->type() == Type::Matrix)) {
80  return replaceWith(new Undefined(), true);
81  }
82 #endif
83  Expression * f = simpleShallowReduce(context, angleUnit);
84  if (f != this) {
85  return f;
86  }
87 
88  /* We do not apply some rules if the parent node is a power of b. In this
89  * case there is a simplication of form e^ln(3^(1/2))->3^(1/2) */
90  bool letLogAtRoot = parentIsAPowerOfSameBase();
91  // log(x^y, b)->y*log(x, b) if x>0
92  if (!letLogAtRoot && op->type() == Type::Power && op->operand(0)->sign() == Sign::Positive) {
93  Power * p = static_cast<Power *>(op);
94  Expression * x = p->editableOperand(0);
95  Expression * y = p->editableOperand(1);
96  p->detachOperands();
97  replaceOperand(p, x, true);
98  Expression * newLog = shallowReduce(context, angleUnit);
99  newLog = newLog->replaceWith(new Multiplication(y, newLog->clone(), false), true);
100  return newLog->shallowReduce(context, angleUnit);
101  }
102  // log(x*y, b)->log(x,b)+log(y, b) if x,y>0
103  if (!letLogAtRoot && op->type() == Type::Multiplication) {
104  Addition * a = new Addition();
105  for (int i = 0; i<op->numberOfOperands()-1; i++) {
106  Expression * factor = op->editableOperand(i);
107  if (factor->sign() == Sign::Positive) {
108  Expression * newLog = clone();
109  static_cast<Multiplication *>(op)->removeOperand(factor, false);
110  newLog->replaceOperand(newLog->editableOperand(0), factor, true);
111  a->addOperand(newLog);
112  newLog->shallowReduce(context, angleUnit);
113  }
114  }
115  if (a->numberOfOperands() > 0) {
116  op->shallowReduce(context, angleUnit);
117  Expression * reducedLastLog = shallowReduce(context, angleUnit);
118  reducedLastLog->replaceWith(a, false);
119  a->addOperand(reducedLastLog);
120  return a->shallowReduce(context, angleUnit);
121  } else {
122  delete a;
123  }
124  }
125  // log(r) = a0log(p0)+a1log(p1)+... with r = p0^a0*p1^a1*... (Prime decomposition)
126  if (!letLogAtRoot && op->type() == Type::Rational) {
127  const Rational * r = static_cast<const Rational *>(operand(0));
128  Expression * n = splitInteger(r->numerator(), false, context, angleUnit);
129  Expression * d = splitInteger(r->denominator(), true, context, angleUnit);
130  Addition * a = new Addition(n, d, false);
131  replaceWith(a, true);
132  return a->shallowReduce(context, angleUnit);
133  }
134  return this;
135 }
136 
137 bool Logarithm::parentIsAPowerOfSameBase() const {
138  // We look for expressions of types e^ln(x) or e^(ln(x)) where ln is this
139  const Expression * parentExpression = parent();
140  bool thisIsPowerExponent = parentExpression->type() == Type::Power ? parentExpression->operand(1) == this : false;
141  if (parentExpression->type() == Type::Parenthesis) {
142  const Expression * parentParentExpression = parentExpression->parent();
143  if (parentExpression == nullptr) {
144  return false;
145  }
146  thisIsPowerExponent = parentParentExpression->type() == Type::Power ? parentParentExpression->operand(1) == parentExpression : false;
147  parentExpression = parentParentExpression;
148  }
149  if (thisIsPowerExponent) {
150  const Expression * powerOperand0 = parentExpression->operand(0);
151  if (numberOfOperands() == 1) {
152  if (powerOperand0->type() == Type::Rational && static_cast<const Rational *>(powerOperand0)->isTen()) {
153  return true;
154  }
155  }
156  if (numberOfOperands() == 2) {
157  if (powerOperand0->isIdenticalTo(operand(1))){
158  return true;
159  }
160  }
161  }
162  return false;
163 }
164 
165 Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & context, AngleUnit angleUnit) {
166  assert(!i.isZero());
167  assert(!i.isNegative());
168  if (i.isOne()) {
169  return new Rational(0);
170  }
171  assert(!i.isOne());
172  Integer factors[Arithmetic::k_maxNumberOfPrimeFactors];
173  Integer coefficients[Arithmetic::k_maxNumberOfPrimeFactors];
175  if (coefficients[0].isMinusOne()) {
176  /* We could not break i in prime factor (either it might take too many
177  * factors or too much time). */
178  Expression * e = clone();
179  e->replaceOperand(e->operand(0), new Rational(i), true);
180  if (!isDenominator) {
181  return e;
182  }
183  Multiplication * m = new Multiplication(new Rational(-1), e, false);
184  return m;
185  }
186  Addition * a = new Addition();
187  int index = 0;
188  while (!coefficients[index].isZero() && index < Arithmetic::k_maxNumberOfPrimeFactors) {
189  if (isDenominator) {
190  coefficients[index].setNegative(true);
191  }
192  Expression * e = clone();
193  e->replaceOperand(e->operand(0), new Rational(factors[index]), true);
194  Multiplication * m = new Multiplication(new Rational(coefficients[index]), e, false);
195  static_cast<Logarithm *>(e)->simpleShallowReduce(context, angleUnit);
196  a->addOperand(m);
197  m->shallowReduce(context, angleUnit);
198  index++;
199  }
200  return a;
201 }
202 
203 Expression * Logarithm::shallowBeautify(Context & context, AngleUnit angleUnit) {
205  const Expression * op = operand(0);
206  Rational one(1);
207  if (numberOfOperands() == 2 && (operand(1)->isIdenticalTo(&e) || operand(1)->isIdenticalTo(&one))) {
208  detachOperand(op);
209  Expression * nl = operand(1)->isIdenticalTo(&e) ? static_cast<Expression *>(new NaperianLogarithm(op, false)) : static_cast<Expression *> (new Logarithm(op, false));
210  return replaceWith(nl, true);
211  }
212  return this;
213 }
214 
215 template<typename T>
216 Expression * Logarithm::templatedApproximate(Context& context, AngleUnit angleUnit) const {
217  if (numberOfOperands() == 1) {
218  return ApproximationEngine::map(this, context, angleUnit, computeOnComplex<T>);
219  }
220  Expression * x = operand(0)->approximate<T>(context, angleUnit);
221  Expression * n = operand(1)->approximate<T>(context, angleUnit);
222  Complex<T> result = Complex<T>::Float(NAN);
223  if (x->type() == Type::Complex && n->type() == Type::Complex) {
224  Complex<T> * xc = static_cast<Complex<T> *>(x);
225  Complex<T> * nc = static_cast<Complex<T> *>(n);
226  result = Division::compute<T>(computeOnComplex(*xc, angleUnit), computeOnComplex(*nc, angleUnit));
227  }
228  delete x;
229  delete n;
230  return new Complex<T>(result);
231 }
232 
233 ExpressionLayout * Logarithm::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const {
234  assert(floatDisplayMode != PrintFloat::Mode::Default);
235  assert(complexFormat != ComplexFormat::Default);
236  if (numberOfOperands() == 1) {
237  return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "log");
238  }
239  ExpressionLayout * childrenLayouts[2];
240  childrenLayouts[0] = new BaselineRelativeLayout(new StringLayout("log", strlen("log")), operand(1)->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript);
241  childrenLayouts[1] = new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat));
242  return new HorizontalLayout(childrenLayouts, 2);
243 }
244 
245 }
friend class Addition
Definition: expression.h:22
Expression * parent() const
Definition: expression.h:185
#define NAN
Definition: math.h:30
friend class Logarithm
Definition: expression.h:55
#define assert(e)
Definition: assert.h:9
Expression * replaceWith(Expression *newOperand, bool deleteAfterReplace=true)
Definition: expression.cpp:85
Expression * approximate(Context &context, AngleUnit angleUnit=AngleUnit::Default) const
Definition: expression.cpp:338
#define T(x)
Definition: events.cpp:26
friend class Symbol
Definition: expression.h:72
#define one
Definition: k_tan.c:68
const Expression *const * operands() const override
Type type() const override
Definition: logarithm.cpp:26
c(generic_all_nodes)
Expression * editableOperand(int i)
Definition: expression.h:176
friend class Rational
Definition: expression.h:18
size_t strlen(const char *s)
Definition: strlen.c:3
friend class Power
Definition: expression.h:21
friend class NaperianLogarithm
Definition: logarithm.h:12
bool isIdenticalTo(const Expression *e) const
Definition: expression.h:219
static void PrimeFactorization(const Integer *i, Integer *outputFactors, Integer *outputCoefficients, int outputLength)
Definition: arithmetic.cpp:39
friend class Multiplication
Definition: expression.h:20
static constexpr int k_maxNumberOfPrimeFactors
Definition: arithmetic.h:15
static ExpressionLayout * createPrefixLayout(const Expression *expression, PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat, const char *operatorName)
#define log10(x)
Definition: math.h:186
ExpressionLayout * createLayout(PrintFloat::Mode floatDisplayMode=PrintFloat::Mode::Default, ComplexFormat complexFormat=ComplexFormat::Default) const
Definition: expression.cpp:244
static Complex< T > Float(T x)
Definition: complex.cpp:23
Expression * clone() const override
Definition: logarithm.cpp:30
virtual Sign sign() const
Definition: expression.h:195
void detachOperand(const Expression *e)
Definition: expression.cpp:115
const Expression * operand(int i) const
Definition: expression.cpp:78
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
static Expression * map(const Expression *expression, Context &context, Expression::AngleUnit angleUnit, ComplexCompute< T > compute)