mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[apps/sequence] In model, use float buffers to avoid recomputing all the
sequence to find a recurrent sequence value at an abscissa n Change-Id: Ic476a5065bbf7aa45c06aa3e9b4d3caa79dd18af
This commit is contained in:
@@ -21,7 +21,11 @@ Sequence::Sequence(const char * text, KDColor color) :
|
||||
m_nameLayout(nullptr),
|
||||
m_definitionName(nullptr),
|
||||
m_firstInitialConditionName(nullptr),
|
||||
m_secondInitialConditionName(nullptr)
|
||||
m_secondInitialConditionName(nullptr),
|
||||
m_indexBuffer1(-1),
|
||||
m_indexBuffer2(-1),
|
||||
m_buffer1(NAN),
|
||||
m_buffer2(NAN)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -104,6 +108,8 @@ void Sequence::setType(Type type) {
|
||||
m_firstInitialConditionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout("0", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
|
||||
m_secondInitialConditionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout("1", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
|
||||
}
|
||||
m_indexBuffer1 = -1;
|
||||
m_indexBuffer2 = -1;
|
||||
}
|
||||
|
||||
Poincare::Expression * Sequence::firstInitialConditionExpression() {
|
||||
@@ -122,6 +128,12 @@ Poincare::ExpressionLayout * Sequence::secondInitialConditionLayout() {
|
||||
return m_secondInitialConditionLayout;
|
||||
}
|
||||
|
||||
void Sequence::setContent(const char * c) {
|
||||
Function::setContent(c);
|
||||
m_indexBuffer1 = -1;
|
||||
m_indexBuffer2 = -1;
|
||||
}
|
||||
|
||||
void Sequence::setFirstInitialConditionContent(const char * c) {
|
||||
strlcpy(m_firstInitialConditionText, c, sizeof(m_firstInitialConditionText));
|
||||
if (m_firstInitialConditionExpression != nullptr) {
|
||||
@@ -135,6 +147,8 @@ void Sequence::setFirstInitialConditionContent(const char * c) {
|
||||
if (m_firstInitialConditionExpression) {
|
||||
m_firstInitialConditionLayout = m_firstInitialConditionExpression->createLayout(Expression::FloatDisplayMode::Decimal);
|
||||
}
|
||||
m_indexBuffer1 = -1;
|
||||
m_indexBuffer2 = -1;
|
||||
}
|
||||
|
||||
void Sequence::setSecondInitialConditionContent(const char * c) {
|
||||
@@ -150,6 +164,8 @@ void Sequence::setSecondInitialConditionContent(const char * c) {
|
||||
if (m_secondInitialConditionExpression) {
|
||||
m_secondInitialConditionLayout = m_secondInitialConditionExpression->createLayout(Expression::FloatDisplayMode::Decimal);
|
||||
}
|
||||
m_indexBuffer1 = -1;
|
||||
m_indexBuffer2 = -1;
|
||||
}
|
||||
|
||||
char Sequence::symbol() const {
|
||||
@@ -197,39 +213,49 @@ float Sequence::evaluateAtAbscissa(float x, Poincare::Context * context) const {
|
||||
return Shared::Function::evaluateAtAbscissa(n, context);
|
||||
case Type::SingleRecurrence:
|
||||
{
|
||||
if (n < 0) {
|
||||
if (n < 0 || n > k_maxRecurrentRank) {
|
||||
return NAN;
|
||||
}
|
||||
if (n == 0) {
|
||||
return m_firstInitialConditionExpression->approximate(*context);
|
||||
m_indexBuffer1 = 0;
|
||||
m_buffer1 = m_firstInitialConditionExpression->approximate(*context);
|
||||
return m_buffer1;
|
||||
}
|
||||
float un = m_firstInitialConditionExpression->approximate(*context);
|
||||
LocalContext subContext = LocalContext(context);
|
||||
Poincare::Symbol nSymbol = Poincare::Symbol(symbol());
|
||||
for (int i = 0; i < n; i++) {
|
||||
int start = m_indexBuffer1 < 0 || m_indexBuffer1 > n ? 0 : m_indexBuffer1;
|
||||
float un = m_indexBuffer1 < 0 || m_indexBuffer1 > n ? m_firstInitialConditionExpression->approximate(*context) : m_buffer1;
|
||||
for (int i = start; i < n; i++) {
|
||||
subContext.setSequenceRankValue(un, 0);
|
||||
Poincare::Complex e = Poincare::Complex::Float(i);
|
||||
subContext.setExpressionForSymbolName(&e, &nSymbol);
|
||||
un = m_expression->approximate(subContext);
|
||||
}
|
||||
m_buffer1 = un;
|
||||
m_indexBuffer1 = n;
|
||||
return un;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (n < 0) {
|
||||
if (n < 0 || n > k_maxRecurrentRank) {
|
||||
return NAN;
|
||||
}
|
||||
if (n == 0) {
|
||||
return m_firstInitialConditionExpression->approximate(*context);
|
||||
}
|
||||
if (n == 1) {
|
||||
return m_secondInitialConditionExpression->approximate(*context);
|
||||
m_indexBuffer1 = 0;
|
||||
m_buffer1 = m_firstInitialConditionExpression->approximate(*context);
|
||||
m_indexBuffer2 = 1;
|
||||
m_buffer2 = m_secondInitialConditionExpression->approximate(*context);
|
||||
return m_buffer2;
|
||||
}
|
||||
float un = m_firstInitialConditionExpression->approximate(*context);
|
||||
float un1 = m_secondInitialConditionExpression->approximate(*context);
|
||||
LocalContext subContext = LocalContext(context);
|
||||
Poincare::Symbol nSymbol = Poincare::Symbol(symbol());
|
||||
for (int i = 0; i < n-1; i++) {
|
||||
int start = m_indexBuffer1 >= 0 && m_indexBuffer1 < n && m_indexBuffer2 > 0 && m_indexBuffer2 <= n && m_indexBuffer1 + 1 == m_indexBuffer2 ? m_indexBuffer1 : 0;
|
||||
float un = m_indexBuffer1 >= 0 && m_indexBuffer1 < n && m_indexBuffer2 > 0 && m_indexBuffer2 <= n && m_indexBuffer1 + 1 == m_indexBuffer2 ? m_buffer1 : m_firstInitialConditionExpression->approximate(*context);
|
||||
float un1 = m_indexBuffer1 >= 0 && m_indexBuffer1 < n && m_indexBuffer2 > 0 && m_indexBuffer2 <= n && m_indexBuffer1 + 1 == m_indexBuffer2 ? m_buffer2 : m_secondInitialConditionExpression->approximate(*context);
|
||||
for (int i = start; i < n-1; i++) {
|
||||
subContext.setSequenceRankValue(un, 0);
|
||||
subContext.setSequenceRankValue(un1, 1);
|
||||
Poincare::Complex e = Poincare::Complex::Float(i);
|
||||
@@ -237,6 +263,10 @@ float Sequence::evaluateAtAbscissa(float x, Poincare::Context * context) const {
|
||||
un = un1;
|
||||
un1 = m_expression->approximate(subContext);
|
||||
}
|
||||
m_buffer1 = un;
|
||||
m_indexBuffer1 = n-1;
|
||||
m_buffer2 = un1;
|
||||
m_indexBuffer2 = n;
|
||||
return un1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ public:
|
||||
Poincare::Expression * secondInitialConditionExpression();
|
||||
Poincare::ExpressionLayout * firstInitialConditionLayout();
|
||||
Poincare::ExpressionLayout * secondInitialConditionLayout();
|
||||
void setContent(const char * c) override;
|
||||
void setFirstInitialConditionContent(const char * c);
|
||||
void setSecondInitialConditionContent(const char * c);
|
||||
int numberOfElements();
|
||||
@@ -33,6 +34,7 @@ public:
|
||||
float evaluateAtAbscissa(float x, Poincare::Context * context) const override;
|
||||
float sumOfTermsBetweenAbscissa(float start, float end, Poincare::Context * context);
|
||||
private:
|
||||
constexpr static int k_maxRecurrentRank = 10000;
|
||||
char symbol() const override;
|
||||
Type m_type;
|
||||
char m_firstInitialConditionText[Shared::Function::k_bodyLength];
|
||||
@@ -45,6 +47,10 @@ private:
|
||||
Poincare::ExpressionLayout * m_definitionName;
|
||||
Poincare::ExpressionLayout * m_firstInitialConditionName;
|
||||
Poincare::ExpressionLayout * m_secondInitialConditionName;
|
||||
mutable int m_indexBuffer1;
|
||||
mutable int m_indexBuffer2;
|
||||
mutable float m_buffer1;
|
||||
mutable float m_buffer2;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
virtual bool isDefined();
|
||||
bool isActive();
|
||||
void setActive(bool active);
|
||||
void setContent(const char * c);
|
||||
virtual void setContent(const char * c);
|
||||
void setColor(KDColor m_color);
|
||||
virtual float evaluateAtAbscissa(float x, Poincare::Context * context) const;
|
||||
protected:
|
||||
|
||||
Reference in New Issue
Block a user