Numworks Epsilon  1.4.1
Graphing Calculator Operating System
symbol.cpp
Go to the documentation of this file.
1 #include <poincare/symbol.h>
2 #include <poincare/context.h>
3 #include <poincare/complex.h>
4 #include <poincare/division.h>
6 #include <poincare/parenthesis.h>
7 #include <poincare/power.h>
10 #include "layout/string_layout.h"
11 #include <ion.h>
12 extern "C" {
13 #include <assert.h>
14 }
15 #include <cmath>
16 
17 namespace Poincare {
18 
19 const char * Symbol::textForSpecialSymbols(char name) const {
20  switch (name) {
22  return "ans";
23  case SpecialSymbols::un:
24  return "u(n)";
25  case SpecialSymbols::un1:
26  return "u(n+1)";
27  case SpecialSymbols::vn:
28  return "v(n)";
29  case SpecialSymbols::vn1:
30  return "v(n+1)";
31  case SpecialSymbols::M0:
32  return "M0";
33  case SpecialSymbols::M1:
34  return "M1";
35  case SpecialSymbols::M2:
36  return "M2";
37  case SpecialSymbols::M3:
38  return "M3";
39  case SpecialSymbols::M4:
40  return "M4";
41  case SpecialSymbols::M5:
42  return "M5";
43  case SpecialSymbols::M6:
44  return "M6";
45  case SpecialSymbols::M7:
46  return "M7";
47  case SpecialSymbols::M8:
48  return "M8";
49  case SpecialSymbols::M9:
50  return "M9";
51  default:
52  assert(false);
53  return nullptr;
54  }
55 }
56 
57 
59  switch (index - '0') {
60  case 0:
61  return SpecialSymbols::M0;
62  case 1:
63  return SpecialSymbols::M1;
64  case 2:
65  return SpecialSymbols::M2;
66  case 3:
67  return SpecialSymbols::M3;
68  case 4:
69  return SpecialSymbols::M4;
70  case 5:
71  return SpecialSymbols::M5;
72  case 6:
73  return SpecialSymbols::M6;
74  case 7:
75  return SpecialSymbols::M7;
76  case 8:
77  return SpecialSymbols::M8;
78  case 9:
79  return SpecialSymbols::M9;
80  default:
81  assert(false);
82  return SpecialSymbols::M0;
83  }
84 }
85 
86 Symbol::Symbol(char name) :
87  m_name(name)
88 {
89 }
90 
92  m_name(other.m_name)
93 {
94 }
95 
96 Symbol::Symbol(const Symbol& other) :
97  m_name(other.m_name)
98 {
99 }
100 
102  return new Symbol(m_name);
103 }
104 
105 int Symbol::polynomialDegree(char symbol) const {
106  if (m_name == symbol) {
107  return 1;
108  }
109  return 0;
110 }
111 
112 Expression * Symbol::replaceSymbolWithExpression(char symbol, Expression * expression) {
113  if (m_name == symbol) {
114  Expression * value = expression->clone();
115  if (parent() && value->needParenthesisWithParent(parent())) {
116  value = new Parenthesis(value, false);
117  }
118  return replaceWith(value, true);
119  }
120  return this;
121 }
122 
124  /* TODO: Maybe, we will want to know that from a context given in parameter:
125  if (context.expressionForSymbol(this) != nullptr) {
126  return context.expressionForSymbol(this)->sign(context);
127  }*/
128  if (m_name == Ion::Charset::SmallPi) {
129  return Sign::Positive;
130  }
131  if (m_name == Ion::Charset::Exponential) {
132  return Sign::Positive;
133  }
134  return Sign::Unknown;
135 }
136 
137 bool Symbol::isApproximate(Context & context) const {
138  // TODO: so far, all symbols A to Z, M0->M9 hold an approximate values. But they should be able to hold exact values later.
139  if (isScalarSymbol() || isMatrixSymbol()) {
140  return true;
141  }
142  return false;
143 }
144 
145 float Symbol::characteristicXRange(Context & context, AngleUnit angleUnit) const {
146  if (m_name == 'x') {
147  return NAN;
148  }
149  return 0.0;
150 }
151 
153  if (m_name == Ion::Charset::IComplex) {
154  return true;
155  }
156  // TODO: so far, no symbols can be exact but A, ..Z should be able to hold exact values later.
157  return false;
158 }
159 
160 Expression * Symbol::shallowReduce(Context& context, AngleUnit angleUnit) {
161  // Do not replace symbols in expression of type: 3->A
162  if (parent()->type() == Type::Store && parent()->operand(1) == this) {
163  return this;
164  }
165  const Expression * e = context.expressionForSymbol(this);
166  if (e != nullptr && hasAnExactRepresentation(context)) { // TODO: later A...Z should be replaced.
167  /* The stored expression had been beautified which forces to call deepReduce. */
168  return replaceWith(e->clone(), true)->deepReduce(context, angleUnit);
169  }
170  return this;
171 }
172 
173 template<typename T>
174 Expression * Symbol::templatedApproximate(Context& context, AngleUnit angleUnit) const {
175  if (context.expressionForSymbol(this) != nullptr) {
176  return context.expressionForSymbol(this)->approximate<T>(context, angleUnit);
177  }
178  return new Complex<T>(Complex<T>::Float(NAN));
179 }
180 
183 }
184 
185 char Symbol::name() const {
186  return m_name;
187 }
188 
189 ExpressionLayout * Symbol::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const {
190  assert(floatDisplayMode != PrintFloat::Mode::Default);
191  assert(complexFormat != ComplexFormat::Default);
192  if (m_name == SpecialSymbols::Ans) {
193  return new StringLayout("ans", 3);
194  }
195  if (m_name == SpecialSymbols::un) {
196  return new BaselineRelativeLayout(new StringLayout("u", 1), new StringLayout("n",1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
197  }
198  if (m_name == SpecialSymbols::un1) {
199  return new BaselineRelativeLayout(new StringLayout("u", 1), new StringLayout("n+1",3, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
200  }
201  if (m_name == SpecialSymbols::vn) {
202  return new BaselineRelativeLayout(new StringLayout("v", 1), new StringLayout("n",1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
203  }
204  if (m_name == SpecialSymbols::vn1) {
205  return new BaselineRelativeLayout(new StringLayout("v", 1), new StringLayout("n+1",3, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
206  }
207  if (isMatrixSymbol()) {
208  const char mi[] = { 'M', (char)(m_name-(char)SpecialSymbols::M0+'0') };
209  return new StringLayout(mi, sizeof(mi));
210  }
211  return new StringLayout(&m_name, 1);
212 }
213 
214 int Symbol::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const {
215  if (bufferSize == 0) {
216  return -1;
217  }
218  if (bufferSize == 1) {
219  buffer[bufferSize-1] = 0;
220  return 0;
221  }
222  /* Special cases for all special symbols */
223  if (m_name >0 && m_name < 32) {
224  return strlcpy(buffer, textForSpecialSymbols(m_name), bufferSize);
225  }
226  buffer[0] = m_name;
227  buffer[1] = 0;
228  return 1;
229 }
230 
232  if (m_name >= (char)SpecialSymbols::M0 && m_name <= (char)SpecialSymbols::M9) {
233  return true;
234  }
235  return false;
236 }
237 
239  if (m_name >= 'A' && m_name <= 'Z') {
240  return true;
241  }
242  return false;
243 }
244 
245 int Symbol::simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const {
247  if ((uint8_t)m_name == ((uint8_t)static_cast<const Symbol *>(e)->name())) {
248  return 0;
249  }
250  if ((uint8_t)m_name > ((uint8_t)static_cast<const Symbol *>(e)->name())) {
251  return 1;
252  }
253  return -1;
254 }
255 
256 }
virtual const Expression * expressionForSymbol(const Symbol *symbol)=0
Expression * parent() const
Definition: expression.h:185
#define NAN
Definition: math.h:30
#define assert(e)
Definition: assert.h:9
Expression * replaceWith(Expression *newOperand, bool deleteAfterReplace=true)
Definition: expression.cpp:85
Sign sign() const override
Definition: symbol.cpp:123
char name() const
Definition: symbol.cpp:185
float characteristicXRange(Context &context, AngleUnit angleUnit=AngleUnit::Default) const override
Definition: symbol.cpp:145
bool isApproximate(Context &context) const
Definition: symbol.cpp:137
#define T(x)
Definition: events.cpp:26
int polynomialDegree(char symbolName) const override
Definition: symbol.cpp:105
size_t strlcpy(char *dst, const char *src, size_t len)
Definition: strlcpy.c:3
Type type() const override
Definition: symbol.cpp:181
Symbol(char name)
Definition: symbol.cpp:86
unsigned char uint8_t
Definition: stdint.h:4
virtual Expression * clone() const =0
constexpr Event Ans
Definition: events.h:113
static SpecialSymbols matrixSymbol(char index)
Definition: symbol.cpp:58
static Complex< T > Float(T x)
Definition: complex.cpp:23
bool hasAnExactRepresentation(Context &context) const
Definition: symbol.cpp:152
bool isScalarSymbol() const
Definition: symbol.cpp:238
friend class Parenthesis
Definition: expression.h:63
bool isMatrixSymbol() const
Definition: symbol.cpp:231
const Expression * operand(int i) const
Definition: expression.cpp:78
virtual Type type() const =0
Expression * clone() const override
Definition: symbol.cpp:101