Numworks Epsilon  1.4.1
Graphing Calculator Operating System
expression.h
Go to the documentation of this file.
1 #ifndef POINCARE_EXPRESSION_H
2 #define POINCARE_EXPRESSION_H
3 
5 #include <poincare/print_float.h>
6 extern "C" {
7 #include <assert.h>
8 }
9 
10 namespace Poincare {
11 
12 class Context;
13 template<class T> class Complex;
14 class Rational;
15 
16 class Expression {
17  friend class Undefined;
18  friend class Rational;
19  friend class Decimal;
20  friend class Multiplication;
21  friend class Power;
22  friend class Addition;
23  friend class Factorial;
24  friend class Factor;
25  friend class Division;
26  friend class Store;
27  friend class Sine;
28  friend class Cosine;
29  friend class Tangent;
30  friend class AbsoluteValue;
31  friend class ArcCosine;
32  friend class ArcSine;
33  friend class ArcTangent;
34  friend class BinomialCoefficient;
35  friend class Ceiling;
36  friend class ComplexArgument;
37  friend class ConfidenceInterval;
38  friend class Conjugate;
39  friend class Derivative;
40  friend class Determinant;
41  friend class DivisionQuotient;
42  friend class DivisionRemainder;
43  friend class Floor;
44  friend class FracPart;
45  friend class GreatCommonDivisor;
46  friend class HyperbolicArcCosine;
47  friend class HyperbolicArcSine;
48  friend class HyperbolicArcTangent;
49  friend class HyperbolicCosine;
50  friend class HyperbolicSine;
51  friend class HyperbolicTangent;
52  friend class ImaginaryPart;
53  friend class Integral;
54  friend class LeastCommonMultiple;
55  friend class Logarithm;
56  friend class MatrixDimension;
57  friend class MatrixInverse;
58  friend class MatrixTrace;
59  friend class MatrixTranspose;
60  friend class NaperianLogarithm;
61  friend class NthRoot;
62  friend class Opposite;
63  friend class Parenthesis;
64  friend class PermuteCoefficient;
65  friend class PredictionInterval;
66  friend class Product;
67  friend class RealPart;
68  friend class Round;
69  friend class SquareRoot;
70  friend class Subtraction;
71  friend class Sum;
72  friend class Symbol;
73  friend class Matrix;
74  friend class SimplificationRoot;
75  friend class Sequence;
76  friend class Trigonometry;
77  friend class ApproximationEngine;
78  friend class SimplificationEngine;
79  friend class LayoutEngine;
80  friend class Complex<float>;
81  friend class Complex<double>;
82 
83 public:
84  enum class Type : uint8_t {
85  Undefined = 0,
86  Rational = 1,
87  Decimal,
89  Power,
90  Addition,
91  Factorial,
92  Division,
93  Store,
94  Sine,
95  Cosine,
96  Tangent,
98  ArcCosine,
99  ArcSine,
100  ArcTangent,
102  Ceiling,
104  Conjugate,
105  Derivative,
106  Determinant,
109  Factor,
110  Floor,
111  FracPart,
120  Integral,
122  Logarithm,
123  MatrixTrace,
125  NthRoot,
126  Opposite,
127  Parenthesis,
129  Product,
130  Random,
131  Randint,
132  RealPart,
133  Round,
134  SquareRoot,
135  Subtraction,
136  Sum,
137  Symbol,
138 
139  Complex,
140  Matrix,
147  };
148  enum class ComplexFormat {
149  Cartesian = 0,
150  Polar = 1,
151  Default = 2
152  };
153  enum class AngleUnit {
154  Degree = 0,
155  Radian = 1,
156  Default = 2
157  };
158 
159  /* Constructor & Destructor */
160  static Expression * parse(char const * string);
161  static void ReplaceSymbolWithExpression(Expression ** expressionAddress, char symbol, Expression * expression);
162  virtual ~Expression() = default;
163  virtual Expression * clone() const = 0;
164 
165  /* Poor man's RTTI */
166  virtual Type type() const = 0;
167 
168  /* Circuit breaker */
169  typedef bool (*CircuitBreaker)();
170  static void setCircuitBreaker(CircuitBreaker cb);
171  static bool shouldStopProcessing();
172 
173  /* Hierarchy */
174  virtual const Expression * const * operands() const = 0;
175  const Expression * operand(int i) const;
176  Expression * editableOperand(int i) { return const_cast<Expression *>(operand(i)); }
177  virtual int numberOfOperands() const = 0;
178 
179  Expression * replaceWith(Expression * newOperand, bool deleteAfterReplace = true);
180  void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true);
181  void detachOperand(const Expression * e); // Removes an operand WITHOUT deleting it
182  void detachOperands(); // Removes all operands WITHOUT deleting them
183  void swapOperands(int i, int j);
184 
185  Expression * parent() const { return m_parent; }
186  void setParent(Expression * parent) { m_parent = parent; }
187  bool hasAncestor(const Expression * e) const;
188 
189  /* Properties */
190  enum class Sign {
191  Negative = -1,
192  Unknown = 0,
193  Positive = 1
194  };
195  virtual Sign sign() const { return Sign::Unknown; }
196  typedef bool (*ExpressionTest)(const Expression * e, Context & context);
197  bool recursivelyMatches(ExpressionTest test, Context & context) const;
198  bool isApproximate(Context & context) const;
199  /* 'characteristicXRange' tries to assess the range on x where the expression
200  * (considered as a function on x) has an interesting evolution. For example,
201  * the period of the function on 'x' if it is periodic. If
202  * the function is x-independent, the return value is 0.0f (because any
203  * x-range is equivalent). If the function does not have an interesting range,
204  * the return value is NAN.
205  * NB: so far, we consider that the only way of building a periodic function
206  * is to use sin/tan/cos(f(x)) with f a linear function. */
207  virtual float characteristicXRange(Context & context, AngleUnit angleUnit = AngleUnit::Default) const;
208  static bool IsMatrix(const Expression * e, Context & context);
209 
210  /* polynomialDegree returns:
211  * - (-1) if the expression is not a polynome
212  * - the degree of the polynome otherwise */
213  virtual int polynomialDegree(char symbolName) const;
214 
215  /* Comparison */
216  /* isIdenticalTo is the "easy" equality, it returns true if both trees have
217  * same structures and all their nodes have same types and values (ie,
218  * sqrt(pi^2) is NOT identical to pi). */
219  bool isIdenticalTo(const Expression * e) const {
220  /* We use the simplification order only because it is a already-coded total
221  * order on expresssions. */
222  return SimplificationOrder(this, e, true) == 0;
223  }
224 
225  /* Layout Engine */
226  ExpressionLayout * createLayout(PrintFloat::Mode floatDisplayMode = PrintFloat::Mode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted
227  virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const = 0;
228 
229  /* Simplification */
230  static Expression * ParseAndSimplify(const char * text, Context & context, AngleUnit angleUnit = AngleUnit::Default);
231  static void Simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default);
232 
233  /* Evaluation Engine
234  * The function evaluate creates a new expression and thus mallocs memory.
235  * Do not forget to delete the new expression to avoid leaking. */
236  template<typename T> Expression * approximate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const;
237  template<typename T> T approximateToScalar(Context& context, AngleUnit angleUnit = AngleUnit::Default) const;
238  template<typename T> static T approximateToScalar(const char * text, Context& context, AngleUnit angleUnit = AngleUnit::Default);
239 protected:
240  /* Constructor */
241  Expression() : m_parent(nullptr) {}
242  /* Hierarchy */
243  void detachOperandAtIndex(int i);
244  /* Evaluation Engine */
245  typedef float SinglePrecision;
246  typedef double DoublePrecision;
247  template<typename T> static T epsilon();
248  constexpr static int k_maxNumberOfSteps = 10000;
249 
250  /* Simplification */
251  /* SimplificationOrder returns:
252  * 1 if e1 > e2
253  * -1 if e1 < e2
254  * 0 if e1 == e
255  * The order groups like terms together to avoid quadratic complexity when
256  * factorizing addition or multiplication. For example, it groups terms with
257  * same bases together (ie Pi, Pi^3) and with same non-rational factors
258  * together (ie Pi, 2*Pi).
259  * Because SimplificationOrder is a recursive call, we sometimes enable its
260  * interruption to avoid freezing in the simplification process. */
261  static int SimplificationOrder(const Expression * e1, const Expression * e2, bool canBeInterrupted = false);
262 private:
263  virtual Expression * replaceSymbolWithExpression(char symbol, Expression * expression);
264  /* Properties */
265  virtual Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) { assert(false); return nullptr; }
266  bool isOfType(Type * types, int length) const;
267  virtual bool needParenthesisWithParent(const Expression * e) const;
268  /* Comparison */
269  /* In the simplification order, most expressions are compared by only
270  * comparing their types. However hierarchical expressions of same type would
271  * compare their operands and thus need to reimplement
272  * simplificationOrderSameType. Besides, operations that can be simplified
273  * (ie +, *, ^, !) have specific rules to group like terms together and thus
274  * reimplement simplificationOrderGreaterType. */
275  virtual int simplificationOrderGreaterType(const Expression * e, bool canBeInterrupted) const { return -1; }
276  //TODO: What should be the implementation for complex?
277  virtual int simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const { return 0; }
278  /* Layout Engine */
279  virtual ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const = 0;
280  /* Simplification */
281  static void Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit, bool recursively = true);
282  Expression * deepBeautify(Context & context, AngleUnit angleUnit);
283  Expression * deepReduce(Context & context, AngleUnit angleUnit);
284  // TODO: should be virtual pure
285  virtual Expression * shallowReduce(Context & context, AngleUnit angleUnit);
286  virtual Expression * shallowBeautify(Context & context, AngleUnit angleUnit) { return this; };
287 
288  // Private methods used in simplification process
289  virtual Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const {
290  return nullptr;
291  }
292  /* Evaluation Engine */
293  virtual Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0;
294  virtual Expression * privateApproximate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0;
295 
296  Expression * m_parent;
297 };
298 
299 }
300 
301 #endif
static bool shouldStopProcessing()
Definition: expression.cpp:65
Expression * parent() const
Definition: expression.h:185
#define assert(e)
Definition: assert.h:9
Expression * replaceWith(Expression *newOperand, bool deleteAfterReplace=true)
Definition: expression.cpp:85
virtual ~Expression()=default
Expression * approximate(Context &context, AngleUnit angleUnit=AngleUnit::Default) const
Definition: expression.cpp:338
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
unsigned char uint8_t
Definition: stdint.h:4
virtual const Expression *const * operands() const =0
virtual Expression * clone() const =0
static Expression * parse(char const *string)
Definition: expression.cpp:25
static void setCircuitBreaker(CircuitBreaker cb)
Definition: expression.cpp:61
static constexpr int k_maxNumberOfSteps
Definition: expression.h:248
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
bool isIdenticalTo(const Expression *e) const
Definition: expression.h:219
char bool
Definition: stdbool.h:6
ExpressionLayout * createLayout(PrintFloat::Mode floatDisplayMode=PrintFloat::Mode::Default, ComplexFormat complexFormat=ComplexFormat::Default) const
Definition: expression.cpp:244
bool isApproximate(Context &context) const
Definition: expression.cpp:173
friend class SimplificationEngine
Definition: expression.h:78
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
bool(* ExpressionTest)(const Expression *e, Context &context)
Definition: expression.h:196
void setParent(Expression *parent)
Definition: expression.h:186
void swapOperands(int i, int j)
Definition: expression.cpp:139
Definition: app.cpp:7
virtual Sign sign() const
Definition: expression.h:195
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
void replaceOperand(const Expression *oldOperand, Expression *newOperand, bool deleteOldOperand=true)
Definition: expression.cpp:91
virtual int writeTextInBuffer(char *buffer, int bufferSize, int numberOfSignificantDigits=PrintFloat::k_numberOfStoredSignificantDigits) const =0
static Expression * ParseAndSimplify(const char *text, Context &context, AngleUnit angleUnit=AngleUnit::Default)
Definition: expression.cpp:265