#include "sequence_context.h" #include "sequence_store.h" #include using namespace Poincare; namespace Sequence { template TemplatedSequenceContext::TemplatedSequenceContext() : m_rank(-1), m_values{{NAN, NAN, NAN},{NAN, NAN, NAN}} { } template T TemplatedSequenceContext::valueOfSequenceAtPreviousRank(int sequenceIndex, int rank) const { return m_values[sequenceIndex][rank]; } template void TemplatedSequenceContext::resetCache() { m_rank = -1; } template bool TemplatedSequenceContext::iterateUntilRank(int n, SequenceStore * sequenceStore, SequenceContext * sqctx) { if (m_rank > n) { m_rank = -1; } if (n < 0 || n-m_rank > k_maxRecurrentRank) { return false; } while (m_rank++ < n) { step(sequenceStore, sqctx); } m_rank--; return true; } template void TemplatedSequenceContext::step(SequenceStore * sequenceStore, SequenceContext * sqctx) { /* Shift values */ for (int i = 0; i < MaxNumberOfSequences; i++) { for (int j = MaxRecurrenceDepth; j > 0; j--) { m_values[i][j] = m_values[i][j-1]; } m_values[i][0] = NAN; } /* Evaluate new u(n) and v(n) */ Sequence * u = sequenceStore->numberOfModels() > 0 ? sequenceStore->modelAtIndex(0) : nullptr; u = u && u->isDefined() ? u : nullptr; Sequence * v = sequenceStore->numberOfModels() > 1 ? sequenceStore->modelAtIndex(1) : nullptr; v = v && v->isDefined() ? v : nullptr; /* Switch u & v if the name of u is v */ if (u != nullptr && u->name()[0] == SequenceStore::k_sequenceNames[1][0]) { Sequence * temp = u; u = v; v = temp; } /* Approximate u & v at the new rank. We evaluate u twice in case its * expression depends on v. */ m_values[0][0] = u ? u->approximateToNextRank(m_rank, sqctx) : NAN; m_values[1][0] = v ? v->approximateToNextRank(m_rank, sqctx) : NAN; m_values[0][0] = u ? u->approximateToNextRank(m_rank, sqctx) : NAN; } template class TemplatedSequenceContext; template class TemplatedSequenceContext; }