Math equation to find number of iterations in asymptotic loop?

267 views Asked by At

I have a loop that decreases in growth as the iterations go up. I need to calculate the number of iterations it'll go through (I explain why I need this at the bottom of this question). The first 6 steps are

0.50, 1.50, 1.83, 2.11, 2.34, 2.55, ...

X-axis: iterations, Y-axis: count X-axis: iterations, Y-axis: count

The count starts at 0.5 and grows at a decreasing rate until it reaches 20. The loop boils down to this:

var SCALE = 0.5; // Starting value, also affects increment
var MAX = 20;    // Maximum value
var i = 0;       // Just for counting

for (var count = SCALE; count < MAX; count += SCALE / count) {
    console.log(count, i);
    i++;
}

You can see the graph grows more slowly as it progresses because of count += SCALE / count, so as count increases, the denominator increases too.

I thought it followed an exponential pow(MAX, 1 / SCALE) line, but not quite:

MAX = 5 :  23 iterations      Math.pow(5, 2) = 25
MAX = 10 : 97 iterations      Math.pow(10, 2) = 100
MAX = 15 : 222 iterations     Math.pow(15, 2) = 225
MAX = 20 : 397 iterations     Math.pow(20, 2) = 400

Plus this approach falls apart when SCALE isn't 0.5.

Question

What equation can I use that takes both SCALE and MAX into account to get the iteration count?

Why do I need this?

I'm trying to convert the sample code at the bottom of this article into GLSL shader code. The problem is that graphics cards can only perform for-loops with integers counting up to a constant, so I need to know how many iterations the loop will take before starting the loop.

I need something like this: for(int i = 0; i < MAX_COUNT; i++) but first I need to know what MAX_COUNT will be.

2

There are 2 answers

0
M - On BEST ANSWER

As suggested by several people in the comments, this pattern doesn't follow a log graph, a harmonic graph, or any recognizable pattern. To solve it I had to go with a "brute-force" approach of just running the loop once, then using the iteration count as the result. There was no elegant math equation.

function calculateSampleCount() {
    const SCALE = 0.5; // Starting value, also affects increment
    const MAX = 20;    // Maximum value
    let i = 0;
    for (let r = SCALE; r < MAX; r += SCALE / r) {
        i++;
    }
    return i;
}
2
Makogan On

So I have 2 solutions, first the math:

As mentioned in the comments what you have is the harmonic series, which does not have a simple closed form. So getting the upper bound of the loop analytically will be a challenge.

However that doesn't mean you can't solve the issue.

Solutions:

Option one is, as suggested in the comments run your code on the CPU until you find the maximum number of iterations and then send that number as the upper bound of your loop (e.g as a uniform).

Another solution that is perhaps better is, set the maximum number of iterations to a huge number and then, inside the body of the loop, break if you have exceeded your threshold (this is possible in modern. i.e 4+ versions of GLSL).