mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-20 09:17:23 +01:00
[sequence] Changed sequences behavior
Sequences can now be defined using specific terms form other sequences : Un = n Vn = u(3) Initial values can also depend on other sequences. Should there be a circular dependency, the sequences concerned will display "undef" as value Change-Id: I6fe1f3ff7b500f35d480ddefb42de729c327432e
This commit is contained in:
committed by
Émilie Feral
parent
688394abce
commit
8434da60ef
@@ -1,5 +1,7 @@
|
||||
#include "sequence_context.h"
|
||||
#include "sequence_store.h"
|
||||
#include "cache_context.h"
|
||||
#include "../shared/poincare_helpers.h"
|
||||
#include <cmath>
|
||||
|
||||
using namespace Poincare;
|
||||
@@ -9,63 +11,104 @@ namespace Sequence {
|
||||
|
||||
template<typename T>
|
||||
TemplatedSequenceContext<T>::TemplatedSequenceContext() :
|
||||
m_rank(-1),
|
||||
m_values{{NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}}
|
||||
m_commonRank(-1),
|
||||
m_commonRankValues{{NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}},
|
||||
m_independantRanks{-1, -1, -1},
|
||||
m_independantRankValues{{NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}}
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T TemplatedSequenceContext<T>::valueOfSequenceAtPreviousRank(int sequenceIndex, int rank) const {
|
||||
return m_values[sequenceIndex][rank];
|
||||
return m_commonRankValues[sequenceIndex][rank];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void TemplatedSequenceContext<T>::resetCache() {
|
||||
m_rank = -1;
|
||||
/* We only need to reset the ranks. Indeed, when we compute the values of the
|
||||
* sequences, we use ranks as memoization indexes. Therefore, we know that the
|
||||
* values stored in m_commomValues and m_independantRankValues are dirty
|
||||
* and do not use them. */
|
||||
m_commonRank = -1;
|
||||
for (int i = 0; i < MaxNumberOfSequences; i ++) {
|
||||
m_independantRanks[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool TemplatedSequenceContext<T>::iterateUntilRank(int n, SequenceStore * sequenceStore, SequenceContext * sqctx) {
|
||||
if (m_rank > n) {
|
||||
m_rank = -1;
|
||||
if (m_commonRank > n) {
|
||||
m_commonRank = -1;
|
||||
}
|
||||
if (n < 0 || n-m_rank > k_maxRecurrentRank) {
|
||||
if (n < 0 || n-m_commonRank > k_maxRecurrentRank) {
|
||||
return false;
|
||||
}
|
||||
while (m_rank++ < n) {
|
||||
step(sequenceStore, sqctx);
|
||||
while (m_commonRank < n) {
|
||||
step(sqctx);
|
||||
}
|
||||
m_rank--;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void TemplatedSequenceContext<T>::step(SequenceStore * sequenceStore, SequenceContext * sqctx) {
|
||||
/* Shift values */
|
||||
for (int i = 0; i < MaxNumberOfSequences; i++) {
|
||||
void TemplatedSequenceContext<T>::step(SequenceContext * sqctx, int sequenceIndex) {
|
||||
// First we increment the rank
|
||||
bool stepMultipleSequences = sequenceIndex == -1;
|
||||
if (stepMultipleSequences) {
|
||||
m_commonRank++;
|
||||
} else {
|
||||
setIndependantSequenceRank(independantSequenceRank(sequenceIndex) + 1, sequenceIndex);
|
||||
}
|
||||
|
||||
// Then we shift the values stored in the arrays
|
||||
int start, stop, rank;
|
||||
T * sequenceArray;
|
||||
if (stepMultipleSequences) {
|
||||
start = 0;
|
||||
stop = MaxNumberOfSequences;
|
||||
sequenceArray = reinterpret_cast<T*>(&m_commonRankValues);
|
||||
rank = m_commonRank;
|
||||
} else {
|
||||
start = sequenceIndex;
|
||||
stop = sequenceIndex + 1;
|
||||
sequenceArray = reinterpret_cast<T*>(&m_independantRankValues);
|
||||
rank = independantSequenceRank(sequenceIndex);
|
||||
}
|
||||
|
||||
for (int i = start; i < stop; i++) {
|
||||
T * rowPointer = sequenceArray + i * (MaxRecurrenceDepth + 1);
|
||||
for (int j = MaxRecurrenceDepth; j > 0; j--) {
|
||||
m_values[i][j] = m_values[i][j-1];
|
||||
*(rowPointer + j) = *(rowPointer + j - 1);
|
||||
}
|
||||
m_values[i][0] = NAN;
|
||||
*rowPointer= NAN;
|
||||
}
|
||||
|
||||
/* Evaluate new u(n) and v(n) */
|
||||
// sequences hold u, v, w in this order
|
||||
// We create an array containing the sequences we want to update
|
||||
Sequence * sequences[MaxNumberOfSequences] = {nullptr, nullptr, nullptr};
|
||||
for (int i = 0; i < sequenceStore->numberOfModels(); i++) {
|
||||
int usedSize = stepMultipleSequences ? MaxNumberOfSequences : 1;
|
||||
SequenceStore * sequenceStore = sqctx->sequenceStore();
|
||||
stop = stepMultipleSequences ? sequenceStore->numberOfModels() : start + 1;
|
||||
for (int i = start; i < stop; i++) {
|
||||
Sequence * u = sequenceStore->modelForRecord(sequenceStore->recordAtIndex(i));
|
||||
sequences[SequenceStore::sequenceIndexForName(u->fullName()[0])] = u->isDefined() ? u : nullptr;
|
||||
int index = stepMultipleSequences ? SequenceStore::sequenceIndexForName(u->fullName()[0]) : 0;
|
||||
sequences[index] = u->isDefined() ? u : nullptr;
|
||||
}
|
||||
|
||||
/* Approximate u, v and w at the new rank. We have to evaluate all sequences
|
||||
* MaxNumberOfSequences times in case the evaluations depend on each other.
|
||||
// We approximate the value of the next rank for each sequence we want to update
|
||||
stop = stepMultipleSequences ? MaxNumberOfSequences : sequenceIndex + 1;
|
||||
/* In case stop is MaxNumberOfSequences, we approximate u, v and w at the new
|
||||
* rank. We have to evaluate all sequences MaxNumberOfSequences times in case
|
||||
* the evaluations depend on each other.
|
||||
* For example, if u expression depends on v and v depends on w. At the first
|
||||
* iteration, we can only evaluate w, at the second iteration we evaluate v
|
||||
* and u can only be known at the third iteration . */
|
||||
for (int k = 0; k < MaxNumberOfSequences; k++) {
|
||||
for (int i = 0; i < MaxNumberOfSequences; i++) {
|
||||
if (std::isnan(m_values[i][0])) {
|
||||
m_values[i][0] = sequences[i] ? sequences[i]->approximateToNextRank<T>(m_rank, sqctx) : NAN;
|
||||
* and u can only be known at the third iteration.
|
||||
* In case stop is 1, there is only one sequence we want to update. Moreover,
|
||||
* the call to approximateToNextRank will handle potential dependencies. */
|
||||
for (int k = 0; k < usedSize; k++) {
|
||||
for (int i = start; i < stop; i++) {
|
||||
T * pointerToUpdate = sequenceArray + i * (MaxRecurrenceDepth + 1);
|
||||
if (std::isnan(*(pointerToUpdate))) {
|
||||
int j = stepMultipleSequences ? i : 0;
|
||||
*(pointerToUpdate) = sequences[j] ? sequences[j]->template approximateToNextRank<T>(rank, sqctx, sequenceIndex) : NAN;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,5 +116,7 @@ void TemplatedSequenceContext<T>::step(SequenceStore * sequenceStore, SequenceCo
|
||||
|
||||
template class TemplatedSequenceContext<float>;
|
||||
template class TemplatedSequenceContext<double>;
|
||||
template void * SequenceContext::helper<float>();
|
||||
template void * SequenceContext::helper<double>();
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user