MATLAB: Is an infinite for loop infinite

for loopinfinityMATLAB

This is a rather theoretical Question: If i have a for loop i=1:Inf, will the loop run forever or stop, when the loop index exceeds realmax? The loop index still grows after reaching 2^53, so matlab seems to have some internal measures to counter precision loss in this case…

Best Answer

We can always try it. Perhaps we can learn something about how the loop works, done by a careful test. Remember that doubles are not well defined as integers when you bypass flintmax. This is important.
L1 = flintmax - 5;
L2 = flintmax + 10;
Below flintmax, indexing is easy. All is good. You do need to recognize that a loop even anywhere close to a number even as small as flintmax will indeed take literally forever. inf is WAY bigger. So a loop to flintmax, even if your computer running MATLAB processes 1e9 loops per second would
flintmax/(1e9*60*60*24*365)
ans =
0.28562
still take on the order of a few months to terminate. So a loop to beyond realmax would take well beyond the point where your computer crumbles to dust, even if the earth was able to survive the sun turning into a red giant only a few billion years from now. I hope you have really good batteries in your laptop.
Disregarding the impossible, start with just getting past flintmax, a really small number in context.
L1 = flintmax - 5;
L2 = flintmax + 10;
Now, once you go beyond flintmax, numbers get confused with the next larger number. We can see that reflected in eps.
eps([L1,L2])
ans =
1 2
Colon seems a little confused how to get there too.
(L1:L2) - flintmax
ans =
-5 -4 -3 -2 -1 0 0 2 4 4 4 6 8 8 8 10
As I said, below flintmax, MATLAB counts perfectly, incrementing by 1 each time. Above flintmax however, sometime the increment is 0, sometimes the increment is 2. Worse, you can't even reliably predict when the increment would be 0 or 2.
I would expect 16 elements in that vector.
numel(L1:L2)
ans =
16
Now, if I increase the upper limit by 1, we see that MATLAB actually creates a vector that has length 18 elements, not 17.
L2 = flintmax + 11;
L2 - flintmax
ans =
12
numel(L1:L2)
ans =
18
So what can we learn from this experiment? In a for loop,
count = 0;
for i = L1:L2
count = count + 1;
end
count
count =
18
So, indeed, the loop ran through 18 iterations, not 17. It was as if MATLAB generated the vector L1:L2, operating on each element of that vector. MATLAB does not actually generate the vector itself, but it does use the same internal logic that colon uses.
Let me try another test, that may be an illuminating test. (I hope.)
count = 0;
for ind = 1:realmax
count = count + 1;
end
Warning: Too many FOR loop iterations. Stopping after 9223372036854775806 iterations.
>> count
count =
5.2576e+09
I broke out of the loop afterr a couple of seconds, so after it had managed to process 5e9 iterations. Note the warning message that was issued.
"Stopping after 9223372036854775806 iterations"
What is that number?
9223372036854775806/flintmax
ans =
1024
log2(9223372036854775806)
ans =
63
sym(2)^63
ans =
9223372036854775808
It looks like the real iteration limit would have been 2^63-2 iterations.
So even though I told it perform an infinite loop, MATLAB would have indeed given up in only something on the order of roughly 280 years on my computer.
The point is, MATLAB can indeed process a loop that runs beyond even flintmax. You won't have any degree of confidence how many iterations will be performed however. That is because as I showed above, for x beyond flintmax, eps(x) is larger than 1. So you cannot reliably predict how many iterations will be performed when an end point of the loop is greater than flintmax.
The one thing we should understand is the real maximum number of loop iterations seems to be 2^63-2. It looks like a 64 bit counter of some sort will be used internally, inside that for loop.
Will this change if the loop were to be run in single precision? I saw this conjecture made by Rik, that things will be different if run in single precision. Maybe not completely so.
L1 = single(1);
L2 = realmax('single')
L2 =
single
3.4028e+38
count = 0;
for ind = L1:L2 % both endpoints of the loop are singles
count = count + 1; % just to give it something to do
end
Warning: Too many FOR loop iterations. Stopping after 9223372036854775806 iterations.
Again, I broke out of the loop long before MATLAB gave up. But as you should see, it still tells me the same upper limit of iterations it would have allowed the loop to proceed before stopping it artificially, even though the loop was to operate on a single precision index. So the same 64 bit internal counter. Therefore I would not assume single precision loops will have a shorter limit on how many iterations they will really run.
Rik suggests the use of while may be a better choice. Is that true? Yes.
count = 0;
while true
count = count + 1;
end
count
count =
1.6164e+10
As you can see, I took a few seconds before breaking the loop this time (my internal clock said it was on the order of 10 seconds before I got bored), but even so, no warning message was ever issued. So indeed if you want a loop to run until far beyond when your computer (with that massive, multi-megaton lithium battery) has long since crumbled to dust, use while true.