Numworks Epsilon  1.4.1
Graphing Calculator Operating System
sequence.cpp
Go to the documentation of this file.
1 #include "sequence.h"
2 #include "sequence_store.h"
3 #include "cache_context.h"
4 #include "../../poincare/src/layout/string_layout.h"
5 #include "../../poincare/src/layout/baseline_relative_layout.h"
6 #include <string.h>
7 #include <cmath>
8 
9 using namespace Shared;
10 using namespace Poincare;
11 
12 namespace Sequence {
13 
14 Sequence::Sequence(const char * text, KDColor color) :
15  Function(text, color),
16  m_type(Type::Explicit),
17  m_firstInitialConditionText(),
18  m_secondInitialConditionText(),
19  m_firstInitialConditionExpression(nullptr),
20  m_secondInitialConditionExpression(nullptr),
21  m_firstInitialConditionLayout(nullptr),
22  m_secondInitialConditionLayout(nullptr),
23  m_nameLayout(nullptr),
24  m_definitionName(nullptr),
25  m_firstInitialConditionName(nullptr),
26  m_secondInitialConditionName(nullptr),
27  m_initialRank(0)
28 {
29 }
30 
31 Sequence::~Sequence() {
32  if (m_firstInitialConditionLayout != nullptr) {
33  delete m_firstInitialConditionLayout;
34  m_firstInitialConditionLayout = nullptr;
35  }
36  if (m_secondInitialConditionLayout != nullptr) {
37  delete m_secondInitialConditionLayout;
38  m_secondInitialConditionLayout = nullptr;
39  }
40  if (m_firstInitialConditionExpression != nullptr) {
41  delete m_firstInitialConditionExpression;
42  m_firstInitialConditionExpression = nullptr;
43  }
44  if (m_secondInitialConditionExpression != nullptr) {
45  delete m_secondInitialConditionExpression;
46  m_secondInitialConditionExpression = nullptr;
47  }
48  if (m_nameLayout != nullptr) {
49  delete m_nameLayout;
50  m_nameLayout = nullptr;
51  }
52  if (m_definitionName != nullptr) {
53  delete m_definitionName;
54  m_definitionName = nullptr;
55  }
56  if (m_firstInitialConditionName != nullptr) {
57  delete m_firstInitialConditionName;
58  m_firstInitialConditionName = nullptr;
59  }
60  if (m_secondInitialConditionName != nullptr) {
61  delete m_secondInitialConditionName;
62  m_secondInitialConditionName = nullptr;
63  }
64 }
65 
66 Sequence& Sequence::operator=(const Sequence& other) {
67  /* We temporarely store other's required features to be able to access them
68  * after setType (which erase all contents and index buffer) even in case of
69  * self assignement */
70  const char * contentText = other.text();
71  const char * firstInitialText = other.m_firstInitialConditionText;
72  const char * secondInitialText = other.m_secondInitialConditionText;
73  Function::operator=(other);
74  setType(other.m_type);
75  setInitialRank(other.m_initialRank);
76  setContent(contentText);
77  setFirstInitialConditionContent(firstInitialText);
78  setSecondInitialConditionContent(secondInitialText);
79  return *this;
80 }
81 
82 uint32_t Sequence::checksum() {
83  char data[k_dataLengthInBytes/sizeof(char)] = {};
85  strlcpy(data+TextField::maxBufferSize(), firstInitialConditionText(), TextField::maxBufferSize());
86  strlcpy(data+2*TextField::maxBufferSize(), secondInitialConditionText(), TextField::maxBufferSize());
87  int * intAdress = (int *)(&data[3*TextField::maxBufferSize()]);
88  *intAdress = m_initialRank;
89  data[k_dataLengthInBytes-3] = (char)m_type;
90  data[k_dataLengthInBytes-2] = name()!= nullptr ? name()[0] : 0;
91  data[k_dataLengthInBytes-1] = (char)(isActive() ? 1 : 0);
92  return Ion::crc32((uint32_t *)data, k_dataLengthInBytes/sizeof(uint32_t));
93 }
94 
95 const char * Sequence::firstInitialConditionText() {
96  return m_firstInitialConditionText;
97 }
98 
99 const char * Sequence::secondInitialConditionText() {
100  return m_secondInitialConditionText;
101 }
102 
103 Sequence::Type Sequence::type() {
104  return m_type;
105 }
106 
107 void Sequence::setType(Type type) {
108  if (m_type == Type::Explicit) {
109  setInitialRank(0);
110  }
111  m_type = type;
112  tidy();
113  /* Reset all contents */
114  switch (m_type) {
115  case Type::Explicit:
116  setContent("");
117  break;
118  case Type::SingleRecurrence:
119  {
120  char ex[5] = "u(n)";
121  ex[0] = name()[0];
122  setContent(ex);
123  break;
124  }
125  case Type::DoubleRecurrence:
126  {
127  char ex[12] = "u(n+1)+u(n)";
128  ex[0] = name()[0];
129  ex[7] = name()[0];
130  setContent(ex);
131  break;
132  }
133  }
134  setFirstInitialConditionContent("");
135  setSecondInitialConditionContent("");
136 }
137 
138 void Sequence::setInitialRank(int rank) {
139  m_initialRank = rank;
140  if (m_firstInitialConditionName != nullptr) {
141  delete m_firstInitialConditionName;
142  m_firstInitialConditionName = nullptr;
143  }
144  if (m_secondInitialConditionName != nullptr) {
145  delete m_secondInitialConditionName;
146  m_secondInitialConditionName = nullptr;
147  }
148 }
149 
150 Poincare::Expression * Sequence::firstInitialConditionExpression(Context * context) const {
151  if (m_firstInitialConditionExpression == nullptr) {
152  m_firstInitialConditionExpression = Poincare::Expression::ParseAndSimplify(m_firstInitialConditionText, *context);
153  }
154  return m_firstInitialConditionExpression;
155 }
156 
157 Poincare::Expression * Sequence::secondInitialConditionExpression(Context * context) const {
158  if (m_secondInitialConditionExpression == nullptr) {
159  m_secondInitialConditionExpression = Poincare::Expression::ParseAndSimplify(m_secondInitialConditionText, *context);
160  }
161  return m_secondInitialConditionExpression;
162 }
163 
164 Poincare::ExpressionLayout * Sequence::firstInitialConditionLayout() {
165  if (m_firstInitialConditionLayout == nullptr) {
166  Expression * nonSimplifedExpression = Expression::parse(m_firstInitialConditionText);
167  if (nonSimplifedExpression) {
168  m_firstInitialConditionLayout = nonSimplifedExpression->createLayout(PrintFloat::Mode::Decimal);
169  delete nonSimplifedExpression;
170  }
171  }
172  return m_firstInitialConditionLayout;
173 }
174 
175 Poincare::ExpressionLayout * Sequence::secondInitialConditionLayout() {
176  if (m_secondInitialConditionLayout == nullptr) {
177  Expression * nonSimplifedExpression = Expression::parse(m_secondInitialConditionText);
178  if (nonSimplifedExpression) {
179  m_secondInitialConditionLayout = nonSimplifedExpression->createLayout(PrintFloat::Mode::Decimal);
180  delete nonSimplifedExpression;
181  }
182  }
183  return m_secondInitialConditionLayout;
184 }
185 
186 void Sequence::setContent(const char * c) {
187  Function::setContent(c);
188 }
189 
190 void Sequence::setFirstInitialConditionContent(const char * c) {
191  strlcpy(m_firstInitialConditionText, c, sizeof(m_firstInitialConditionText));
192  if (m_firstInitialConditionExpression != nullptr) {
193  delete m_firstInitialConditionExpression;
194  m_firstInitialConditionExpression = nullptr;
195  }
196  if (m_firstInitialConditionLayout != nullptr) {
197  delete m_firstInitialConditionLayout;
198  m_firstInitialConditionLayout = nullptr;
199  }
200 }
201 
202 void Sequence::setSecondInitialConditionContent(const char * c) {
203  strlcpy(m_secondInitialConditionText, c, sizeof(m_secondInitialConditionText));
204  if (m_secondInitialConditionExpression != nullptr) {
205  delete m_secondInitialConditionExpression;
206  m_secondInitialConditionExpression = nullptr;
207  }
208  if (m_secondInitialConditionLayout != nullptr) {
209  delete m_secondInitialConditionLayout;
210  m_secondInitialConditionLayout = nullptr;
211  }
212 }
213 
214 char Sequence::symbol() const {
215  return 'n';
216 }
217 
218 int Sequence::numberOfElements() {
219  return (int)m_type + 1;
220 }
221 
222 Poincare::ExpressionLayout * Sequence::nameLayout() {
223  if (m_nameLayout == nullptr) {
224  m_nameLayout = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout("n", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
225  }
226  return m_nameLayout;
227 }
228 
229 Poincare::ExpressionLayout * Sequence::definitionName() {
230  if (m_definitionName == nullptr) {
231  if (m_type == Type::Explicit) {
232  m_definitionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout("n ", 2, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
233  }
234  if (m_type == Type::SingleRecurrence) {
235  m_definitionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout("n+1 ", 4, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
236  }
237  if (m_type == Type::DoubleRecurrence) {
238  m_definitionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout("n+2 ", 4, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
239  }
240  }
241  return m_definitionName;
242 }
243 
244 Poincare::ExpressionLayout * Sequence::firstInitialConditionName() {
245  char buffer[k_initialRankNumberOfDigits+1];
246  Integer(m_initialRank).writeTextInBuffer(buffer, k_initialRankNumberOfDigits+1);
247  if (m_firstInitialConditionName == nullptr) {
248  if (m_type == Type::SingleRecurrence) {
249  m_firstInitialConditionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
250  }
251  if (m_type == Type::DoubleRecurrence) {
252  m_firstInitialConditionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
253  }
254  }
255  return m_firstInitialConditionName;
256 }
257 
258 Poincare::ExpressionLayout * Sequence::secondInitialConditionName() {
259  char buffer[k_initialRankNumberOfDigits+1];
260  Integer(m_initialRank+1).writeTextInBuffer(buffer, k_initialRankNumberOfDigits+1);
261  if (m_secondInitialConditionName == nullptr) {
262  if (m_type == Type::DoubleRecurrence) {
263  m_secondInitialConditionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
264 
265  }
266  }
267  return m_secondInitialConditionName;
268 }
269 
270 bool Sequence::isDefined() {
271  switch (m_type) {
272  case Type::Explicit:
273  return strlen(text()) != 0;
274  case Type::SingleRecurrence:
275  return strlen(text()) != 0 && strlen(firstInitialConditionText()) != 0;
276  default:
277  return strlen(text()) != 0 && strlen(firstInitialConditionText()) != 0 && strlen(secondInitialConditionText()) != 0;
278  }
279 }
280 
281 bool Sequence::isEmpty() {
282  switch (m_type) {
283  case Type::Explicit:
284  return Function::isEmpty();
285  case Type::SingleRecurrence:
286  return Function::isEmpty() && strlen(m_firstInitialConditionText) == 0;
287  default:
288  return Function::isEmpty() && strlen(m_firstInitialConditionText) == 0 && strlen(m_secondInitialConditionText) == 0;
289  }
290 }
291 
292 template<typename T>
293 T Sequence::templatedApproximateAtAbscissa(T x, SequenceContext * sqctx) const {
294  T n = std::round(x);
295  int sequenceIndex = name()[0] == SequenceStore::k_sequenceNames[0][0] ? 0 : 1;
296  if (sqctx->iterateUntilRank<T>(n)) {
297  return sqctx->valueOfSequenceAtPreviousRank<T>(sequenceIndex, 0);
298  }
299  return NAN;
300 }
301 
302 template<typename T>
303 T Sequence::approximateToNextRank(int n, SequenceContext * sqctx) const {
304  if (n < m_initialRank || n < 0) {
305  return NAN;
306  }
307  CacheContext<T> ctx = CacheContext<T>(sqctx);
308  T un = sqctx->valueOfSequenceAtPreviousRank<T>(0, 0);
309  T unm1 = sqctx->valueOfSequenceAtPreviousRank<T>(0, 1);
310  T unm2 = sqctx->valueOfSequenceAtPreviousRank<T>(0, 2);
311  T vn = sqctx->valueOfSequenceAtPreviousRank<T>(1, 0);
312  T vnm1 = sqctx->valueOfSequenceAtPreviousRank<T>(1, 1);
313  T vnm2 = sqctx->valueOfSequenceAtPreviousRank<T>(1, 2);
314  Poincare::Symbol nSymbol(symbol());
315  Poincare::Symbol vnSymbol(Symbol::SpecialSymbols::vn);
316  Poincare::Symbol vn1Symbol(Symbol::SpecialSymbols::vn1);
317  Poincare::Symbol unSymbol(Symbol::SpecialSymbols::un);
318  Poincare::Symbol un1Symbol(Symbol::SpecialSymbols::un1);
319  switch (m_type) {
320  case Type::Explicit:
321  {
322  ctx.setValueForSymbol(un, &unSymbol);
323  ctx.setValueForSymbol(vn, &vnSymbol);
325  ctx.setExpressionForSymbolName(&e, &nSymbol, *sqctx);
326  return expression(sqctx)->template approximateToScalar<T>(ctx);
327  }
328  case Type::SingleRecurrence:
329  {
330  if (n == m_initialRank) {
331  return firstInitialConditionExpression(sqctx)->template approximateToScalar<T>(*sqctx);
332  }
333  ctx.setValueForSymbol(un, &un1Symbol);
334  ctx.setValueForSymbol(unm1, &unSymbol);
335  ctx.setValueForSymbol(vn, &vn1Symbol);
336  ctx.setValueForSymbol(vnm1, &vnSymbol);
338  ctx.setExpressionForSymbolName(&e, &nSymbol, *sqctx);
339  return expression(sqctx)->template approximateToScalar<T>(ctx);
340  }
341  default:
342  {
343  if (n == m_initialRank) {
344  return firstInitialConditionExpression(sqctx)->template approximateToScalar<T>(*sqctx);
345  }
346  if (n == m_initialRank+1) {
347  return secondInitialConditionExpression(sqctx)->template approximateToScalar<T>(*sqctx);
348  }
349  ctx.setValueForSymbol(unm1, &un1Symbol);
350  ctx.setValueForSymbol(unm2, &unSymbol);
351  ctx.setValueForSymbol(vnm1, &vn1Symbol);
352  ctx.setValueForSymbol(vnm2, &vnSymbol);
354  ctx.setExpressionForSymbolName(&e, &nSymbol, *sqctx);
355  return expression(sqctx)->template approximateToScalar<T>(ctx);
356  }
357  }
358 }
359 
360 double Sequence::sumBetweenBounds(double start, double end, Context * context) const {
361  double result = 0.0;
362  if (end-start > k_maxNumberOfTermsInSum || start + 1.0 == start) {
363  return NAN;
364  }
365  for (double i = std::round(start); i <= std::round(end); i = i + 1.0) {
366  /* When |start| >> 1.0, start + 1.0 = start. In that case, quit the
367  * infinite loop. */
368  if (i == i-1.0 || i == i+1.0) {
369  return NAN;
370  }
371  result += evaluateAtAbscissa(i, context);
372  }
373  return result;
374 }
375 
376 void Sequence::tidy() {
377  Function::tidy();
378  if (m_firstInitialConditionLayout != nullptr) {
379  delete m_firstInitialConditionLayout;
380  m_firstInitialConditionLayout = nullptr;
381  }
382  if (m_secondInitialConditionLayout != nullptr) {
383  delete m_secondInitialConditionLayout;
384  m_secondInitialConditionLayout = nullptr;
385  }
386  if (m_firstInitialConditionExpression != nullptr) {
387  delete m_firstInitialConditionExpression;
388  m_firstInitialConditionExpression = nullptr;
389  }
390  if (m_secondInitialConditionExpression != nullptr) {
391  delete m_secondInitialConditionExpression;
392  m_secondInitialConditionExpression = nullptr;
393  }
394  if (m_nameLayout != nullptr) {
395  delete m_nameLayout;
396  m_nameLayout = nullptr;
397  }
398  if (m_definitionName != nullptr) {
399  delete m_definitionName;
400  m_definitionName = nullptr;
401  }
402  if (m_firstInitialConditionName != nullptr) {
403  delete m_firstInitialConditionName;
404  m_firstInitialConditionName = nullptr;
405  }
406  if (m_secondInitialConditionName != nullptr) {
407  delete m_secondInitialConditionName;
408  m_secondInitialConditionName = nullptr;
409  }
410 }
411 
412 template double Sequence::templatedApproximateAtAbscissa<double>(double, SequenceContext*) const;
413 template float Sequence::templatedApproximateAtAbscissa<float>(float, SequenceContext*) const;
414 template double Sequence::approximateToNextRank<double>(int, SequenceContext*) const;
415 template float Sequence::approximateToNextRank<float>(int, SequenceContext*) const;
416 }
#define NAN
Definition: math.h:30
int writeTextInBuffer(char *buffer, int bufferSize) const
Definition: integer.cpp:545
static constexpr int maxBufferSize()
Definition: text_field.h:23
def data
Definition: i18n.py:176
const char * text() const
Definition: function.cpp:64
#define T(x)
Definition: events.cpp:26
size_t strlcpy(char *dst, const char *src, size_t len)
Definition: strlcpy.c:3
c(generic_all_nodes)
size_t strlen(const char *s)
Definition: strlen.c:3
unsigned int uint32_t
Definition: stdint.h:6
#define round(x)
Definition: math.h:192
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
void start()
Definition: rt0.cpp:31
Definition: color.h:6
Definition: app.cpp:7
uint32_t crc32(const uint32_t *data, size_t length)
Definition: device.cpp:37
static constexpr const char * k_sequenceNames[MaxNumberOfSequences]
T valueOfSequenceAtPreviousRank(int sequenceIndex, int rank) const
void setExpressionForSymbolName(const Expression *expression, const Symbol *symbol, Context &context) override
void setValueForSymbol(T value, const Poincare::Symbol *symbol)
static Expression * ParseAndSimplify(const char *text, Context &context, AngleUnit angleUnit=AngleUnit::Default)
Definition: expression.cpp:265