Numworks Epsilon  1.4.1
Graphing Calculator Operating System
expression.cpp
Go to the documentation of this file.
1 #include <poincare/expression.h>
2 #include <poincare/preferences.h>
3 #include <poincare/symbol.h>
6 #include <poincare/list_data.h>
7 #include <poincare/matrix_data.h>
8 #include <poincare/undefined.h>
10 #include <poincare/rational.h>
11 #include <poincare/matrix.h>
12 #include <poincare/complex.h>
13 #include <cmath>
14 #include "expression_parser.hpp"
15 #include "expression_lexer.hpp"
16 
17 int poincare_expression_yyparse(Poincare::Expression ** expressionOutput);
18 
19 namespace Poincare {
20 
21 #include <stdio.h>
22 
23 /* Constructor & Destructor */
24 
25 Expression * Expression::parse(char const * string) {
26  if (string[0] == 0) {
27  return nullptr;
28  }
29  YY_BUFFER_STATE buf = poincare_expression_yy_scan_string(string);
30  Expression * expression = 0;
31  if (poincare_expression_yyparse(&expression) != 0) {
32  // Parsing failed because of invalid input or memory exhaustion
33  if (expression != nullptr) {
34  delete expression;
35  expression = nullptr;
36  }
37  }
38  poincare_expression_yy_delete_buffer(buf);
39 
40  return expression;
41 }
42 
43 void Expression::ReplaceSymbolWithExpression(Expression ** expressionAddress, char symbol, Expression * expression) {
44  SimplificationRoot root(*expressionAddress);
45  root.editableOperand(0)->replaceSymbolWithExpression(symbol, expression);
46  *expressionAddress = root.editableOperand(0);
47 }
48 
49 Expression * Expression::replaceSymbolWithExpression(char symbol, Expression * expression) {
50  for (int i = 0; i < numberOfOperands(); i++) {
51  editableOperand(i)->replaceSymbolWithExpression(symbol, expression);
52  }
53  return this;
54 }
55 
56 /* Circuit breaker */
57 
58 static Expression::CircuitBreaker sCircuitBreaker = nullptr;
59 static bool sSimplificationHasBeenInterrupted = false;
60 
61 void Expression::setCircuitBreaker(CircuitBreaker cb) {
62  sCircuitBreaker = cb;
63 }
64 
66  if (sCircuitBreaker == nullptr) {
67  return false;
68  }
69  if (sCircuitBreaker()) {
70  sSimplificationHasBeenInterrupted = true;
71  return true;
72  }
73  return false;
74 }
75 
76 /* Hierarchy */
77 
78 const Expression * Expression::operand(int i) const {
79  assert(i >= 0);
80  assert(i < numberOfOperands());
81  assert(operands()[i]->parent() == nullptr || operands()[i]->parent() == this);
82  return operands()[i];
83 }
84 
85 Expression * Expression::replaceWith(Expression * newOperand, bool deleteAfterReplace) {
86  assert(m_parent != nullptr);
87  m_parent->replaceOperand(this, newOperand, deleteAfterReplace);
88  return newOperand;
89 }
90 
91 void Expression::replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) {
92  assert(newOperand != nullptr);
93  // Caution: handle the case where we replace an operand with a descendant of ours.
94  if (newOperand->hasAncestor(this)) {
95  newOperand->parent()->detachOperand(newOperand);
96  }
97  Expression ** op = const_cast<Expression **>(operands());
98  for (int i=0; i<numberOfOperands(); i++) {
99  if (op[i] == oldOperand) {
100  if (oldOperand != nullptr && oldOperand->parent() == this) {
101  const_cast<Expression *>(oldOperand)->setParent(nullptr);
102  }
103  if (deleteOldOperand) {
104  delete oldOperand;
105  }
106  if (newOperand != nullptr) {
107  const_cast<Expression *>(newOperand)->setParent(this);
108  }
109  op[i] = newOperand;
110  break;
111  }
112  }
113 }
114 
116  Expression ** op = const_cast<Expression **>(operands());
117  for (int i=0; i<numberOfOperands(); i++) {
118  if (op[i] == e) {
120  }
121  }
122 }
123 
125  for (int i=0; i<numberOfOperands(); i++) {
127  }
128 }
129 
131  Expression ** op = const_cast<Expression **>(operands());
132  // When detachOperands is called, it's very likely that said operands have been stolen
133  if (op[i] != nullptr && op[i]->parent() == this) {
134  const_cast<Expression *>(op[i])->setParent(nullptr);
135  }
136  op[i] = nullptr;
137 }
138 
139 void Expression::swapOperands(int i, int j) {
140  assert(i >= 0 && i < numberOfOperands());
141  assert(j >= 0 && j < numberOfOperands());
142  Expression ** op = const_cast<Expression **>(operands());
143  Expression * temp = op[i];
144  op[i] = op[j];
145  op[j] = temp;
146 }
147 
148 bool Expression::hasAncestor(const Expression * e) const {
149  assert(m_parent != this);
150  if (m_parent == e) {
151  return true;
152  }
153  if (m_parent == nullptr) {
154  return false;
155  }
156  return m_parent->hasAncestor(e);
157 }
158 
159 /* Properties */
160 
161 bool Expression::recursivelyMatches(ExpressionTest test, Context & context) const {
162  if (test(this, context)) {
163  return true;
164  }
165  for (int i = 0; i < numberOfOperands(); i++) {
166  if (operand(i)->recursivelyMatches(test, context)) {
167  return true;
168  }
169  }
170  return false;
171 }
172 
173 bool Expression::isApproximate(Context & context) const {
174  return recursivelyMatches([](const Expression * e, Context & context) {
175  return e->type() == Expression::Type::Decimal || e->type() == Expression::Type::Complex || Expression::IsMatrix(e, context) || (e->type() == Expression::Type::Symbol && static_cast<const Symbol *>(e)->isApproximate(context));
176  }, context);
177 }
178 
179 float Expression::characteristicXRange(Context & context, AngleUnit angleUnit) const {
180  if (angleUnit == AngleUnit::Default) {
181  angleUnit = Preferences::sharedPreferences()->angleUnit();
182  }
183  /* A expression has a characteristic range if at least one of its operand has
184  * one and the other are x-independant. We keep the biggest interesting range
185  * among the operand interesting ranges. */
186  float range = 0.0f;
187  for (int i = 0; i < numberOfOperands(); i++) {
188  float opRange = operand(i)->characteristicXRange(context, angleUnit);
189  if (std::isnan(opRange)) {
190  return NAN;
191  } else if (range < opRange) {
192  range = opRange;
193  }
194  }
195  return range;
196 }
197 
198 bool Expression::IsMatrix(const Expression * e, Context & context) {
199  return e->type() == Type::Matrix || e->type() == Type::ConfidenceInterval || e->type() == Type::MatrixDimension || e->type() == Type::PredictionInterval || e->type() == Type::MatrixInverse || e->type() == Type::MatrixTranspose || (e->type() == Type::Symbol && static_cast<const Symbol *>(e)->isMatrixSymbol());
200 }
201 
202 int Expression::polynomialDegree(char symbolName) const {
203  for (int i = 0; i < numberOfOperands(); i++) {
204  if (operand(i)->polynomialDegree(symbolName) != 0) {
205  return -1;
206  }
207  }
208  return 0;
209 }
210 
211 bool Expression::isOfType(Type * types, int length) const {
212  for (int i = 0; i < length; i++) {
213  if (type() == types[i]) {
214  return true;
215  }
216  }
217  return false;
218 }
219 
220 bool Expression::needParenthesisWithParent(const Expression * e) const {
221  return false;
222 }
223 
224 /* Comparison */
225 
226 int Expression::SimplificationOrder(const Expression * e1, const Expression * e2, bool canBeInterrupted) {
227  if (e1->type() > e2->type()) {
228  if (canBeInterrupted && shouldStopProcessing()) {
229  return 1;
230  }
231  return -(e2->simplificationOrderGreaterType(e1, canBeInterrupted));
232  } else if (e1->type() == e2->type()) {
233  return e1->simplificationOrderSameType(e2, canBeInterrupted);
234  } else {
235  if (canBeInterrupted && shouldStopProcessing()) {
236  return -1;
237  }
238  return e1->simplificationOrderGreaterType(e2, canBeInterrupted);
239  }
240 }
241 
242 /* Layout */
243 
245  switch (floatDisplayMode) {
247  switch (complexFormat) {
249  return privateCreateLayout(Preferences::sharedPreferences()->displayMode(), Preferences::sharedPreferences()->complexFormat());
250  default:
251  return privateCreateLayout(Preferences::sharedPreferences()->displayMode(), complexFormat);
252  }
253  default:
254  switch (complexFormat) {
256  return privateCreateLayout(floatDisplayMode, Preferences::sharedPreferences()->complexFormat());
257  default:
258  return privateCreateLayout(floatDisplayMode, complexFormat);
259  }
260  }
261 }
262 
263 /* Simplification */
264 
265 Expression * Expression::ParseAndSimplify(const char * text, Context & context, AngleUnit angleUnit) {
266  Expression * exp = parse(text);
267  if (exp == nullptr) {
268  return new Undefined();
269  }
270  Simplify(&exp, context, angleUnit);
271  if (exp == nullptr) {
272  return parse(text);
273  }
274  return exp;
275 }
276 
277 void Expression::Simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) {
278  sSimplificationHasBeenInterrupted = false;
279  if (angleUnit == AngleUnit::Default) {
280  angleUnit = Preferences::sharedPreferences()->angleUnit();
281  }
282 #if MATRIX_EXACT_REDUCING
283 #else
284  if ((*expressionAddress)->recursivelyMatches(IsMatrix, context)) {
285  return;
286  }
287 #endif
288  SimplificationRoot root(*expressionAddress);
289  root.editableOperand(0)->deepReduce(context, angleUnit);
290  root.editableOperand(0)->deepBeautify(context, angleUnit);
291  *expressionAddress = root.editableOperand(0);
292  if (sSimplificationHasBeenInterrupted) {
293  root.detachOperands();
294  delete *expressionAddress;
295  *expressionAddress = nullptr;
296  }
297 }
298 
299 
300 void Expression::Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit, bool recursively) {
301  SimplificationRoot root(*expressionAddress);
302  if (recursively) {
303  root.editableOperand(0)->deepReduce(context, angleUnit);
304  } else {
305  root.editableOperand(0)->shallowReduce(context,angleUnit);
306  }
307  *expressionAddress = root.editableOperand(0);
308 }
309 
310 Expression * Expression::deepReduce(Context & context, AngleUnit angleUnit) {
311  assert(parent() != nullptr);
312  for (int i = 0; i < numberOfOperands(); i++) {
313  editableOperand(i)->deepReduce(context, angleUnit);
314  }
315  return shallowReduce(context, angleUnit);
316 }
317 
318 Expression * Expression::shallowReduce(Context & context, AngleUnit angleUnit) {
319  for (int i = 0; i < numberOfOperands(); i++) {
321  return replaceWith(new Undefined(), true);
322  }
323  }
324  return this;
325 }
326 
327 Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) {
328  assert(parent() != nullptr);
329  Expression * e = shallowBeautify(context, angleUnit);
330  for (int i = 0; i < e->numberOfOperands(); i++) {
331  e->editableOperand(i)->deepBeautify(context, angleUnit);
332  }
333  return e;
334 }
335 
336 /* Evaluation */
337 
338 template<typename T> Expression * Expression::approximate(Context& context, AngleUnit angleUnit) const {
339  switch (angleUnit) {
340  case AngleUnit::Default:
341  return privateApproximate(T(), context, Preferences::sharedPreferences()->angleUnit());
342  default:
343  return privateApproximate(T(), context, angleUnit);
344  }
345 }
346 
347 template<typename T> T Expression::approximateToScalar(Context& context, AngleUnit angleUnit) const {
348  Expression * evaluation = approximate<T>(context, angleUnit);
349  assert(evaluation->type() == Type::Complex || evaluation->type() == Type::Matrix);
350  T result = NAN;
351  if (evaluation->type() == Type::Complex) {
352  result = static_cast<const Complex<T> *>(evaluation)->toScalar();
353  }
354  /*if (evaluation->type() == Type::Matrix) {
355  if (numberOfOperands() == 1) {
356  result = static_cast<const Complex<T> *>(operand(0))->toScalar();
357  }
358  }*/
359  delete evaluation;
360  return result;
361 }
362 
363 template<typename T> T Expression::approximateToScalar(const char * text, Context& context, AngleUnit angleUnit) {
364  Expression * exp = ParseAndSimplify(text, context, angleUnit);
365  T result = exp->approximateToScalar<T>(context, angleUnit);
366  delete exp;
367  return result;
368 }
369 
370 template<typename T> T Expression::epsilon() {
371  static T epsilon = sizeof(T) == sizeof(double) ? 1E-15 : 1E-7f;
372  return epsilon;
373 }
374 
375 }
376 
377 template Poincare::Expression * Poincare::Expression::approximate<double>(Context& context, AngleUnit angleUnit) const;
378 template Poincare::Expression * Poincare::Expression::approximate<float>(Context& context, AngleUnit angleUnit) const;
379 template double Poincare::Expression::approximateToScalar<double>(char const*, Poincare::Context&, Poincare::Expression::AngleUnit);
380 template float Poincare::Expression::approximateToScalar<float>(char const*, Poincare::Context&, Poincare::Expression::AngleUnit);
381 template double Poincare::Expression::approximateToScalar<double>(Poincare::Context&, Poincare::Expression::AngleUnit) const;
382 template float Poincare::Expression::approximateToScalar<float>(Poincare::Context&, Poincare::Expression::AngleUnit) const;
383 template double Poincare::Expression::epsilon<double>();
384 template float Poincare::Expression::epsilon<float>();
static bool shouldStopProcessing()
Definition: expression.cpp:65
#define exp(x)
Definition: math.h:176
Expression * parent() const
Definition: expression.h:185
#define NAN
Definition: math.h:30
static Preferences * sharedPreferences()
Definition: preferences.cpp:14
#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
Expression::AngleUnit angleUnit() const
Definition: preferences.cpp:19
static bool IsMatrix(const Expression *e, Context &context)
Definition: expression.cpp:198
#define T(x)
Definition: events.cpp:26
bool recursivelyMatches(ExpressionTest test, Context &context) const
Definition: expression.cpp:161
bool hasAncestor(const Expression *e) const
Definition: expression.cpp:148
virtual const Expression *const * operands() const =0
static Expression * parse(char const *string)
Definition: expression.cpp:25
static void setCircuitBreaker(CircuitBreaker cb)
Definition: expression.cpp:61
Expression * editableOperand(int i)
Definition: expression.h:176
static int SimplificationOrder(const Expression *e1, const Expression *e2, bool canBeInterrupted=false)
Definition: expression.cpp:226
void detachOperandAtIndex(int i)
Definition: expression.cpp:130
virtual int numberOfOperands() const =0
ExpressionLayout * createLayout(PrintFloat::Mode floatDisplayMode=PrintFloat::Mode::Default, ComplexFormat complexFormat=ComplexFormat::Default) const
Definition: expression.cpp:244
int poincare_expression_yyparse(Poincare::Expression **expressionOutput)
#define isnan(x)
Definition: math.h:43
bool isApproximate(Context &context) const
Definition: expression.cpp:173
static void ReplaceSymbolWithExpression(Expression **expressionAddress, char symbol, Expression *expression)
Definition: expression.cpp:43
virtual float characteristicXRange(Context &context, AngleUnit angleUnit=AngleUnit::Default) const
Definition: expression.cpp:179
void setParent(Expression *parent)
Definition: expression.h:186
void swapOperands(int i, int j)
Definition: expression.cpp:139
static void Simplify(Expression **expressionAddress, Context &context, AngleUnit angleUnit=AngleUnit::Default)
Definition: expression.cpp:277
void detachOperand(const Expression *e)
Definition: expression.cpp:115
T approximateToScalar(Context &context, AngleUnit angleUnit=AngleUnit::Default) const
Definition: expression.cpp:347
bool(* CircuitBreaker)()
Definition: expression.h:169
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
static Expression * ParseAndSimplify(const char *text, Context &context, AngleUnit angleUnit=AngleUnit::Default)
Definition: expression.cpp:265