# Catching every Nth FOR/NEXT iteration

Hi, I’m a little rusty and embarrassed to ask, but here we go:
In this code what condition expression in the IF statement will be true for every 4th value of X ?
Note:
all numbers are Double (so no Mod() ), and the FOR/NEXT loop steps in fractional numbers.

``````  //---------SCALE GRADUATION LINES------
LayerAll.graphics.ForeColor = RGB(254, 254, 254)
LayerAll.graphics.PenWidth = 1
FOR X = 0 to 101 step ( 25000 / 20000)'*270'(100/MaxRPM*250)/10  '4 fine lines pr. coarse line
Vector = 90 - (135 + (X * 2.7))
Vector = (3.14159 / 180) * Vector
//-----
LayerAll.graphics.PenWidth = 1
LineStartX = (Size / 2) + sin(Vector) * LimitSectorRi
LineEndX   = (Size / 2) + sin(Vector) * LimitSectorRo
LineStartY = (Size / 2) + cos(Vector) * LimitSectorRi
LineEndY   = (Size / 2) + cos(Vector) * LimitSectorRo
LayerAll.graphics.DrawLine LineStartX, LineStartY, LineEndX, LineEndY
//-----

If X =  ?????????? Then 'catch every 4th iteration of X
Vector = 270 - (X * 2.7 ) + 45
Vector = (3.14159 / 180) * Vector 'convert to radians
LayerAll.graphics.PenWidth = 3
LineStartX = (Size / 2) + sin(Vector) * LimitSectorRi * 0.8
LineEndX = (Size / 2) + (Sin(Vector)) * LimitSectorRo
LineStartY = (Size / 2) + cos(Vector) * LimitSectorRi * 0.8
LineEndY = (Size / 2) + (Cos(Vector)) * LimitSectorRo
LayerAll.graphics.DrawLine LineStartX, LineStartY, LineEndX, LineEndY
End if

next X
//-------------------------------
``````

The easiest way I’ve found:

``````var count as integer

for x ...

count = count + 1
if count = 4 then
count = 0
end if
next
``````
1 Like

Doubles represent floating point numbers that can not always be precisely represented so maybe using x to compare could lead to missing steps.

Use a separate value as Kem says

Yupp, works great. Thanks.

Yes I had problems with missing “matches”

``````for x = startNumber to endNumber

if x mod 4 = 0 then
//do stuff
end

next
``````

Not with the loop he’s using though.

Ah, good point. Still, I wonder if this might be faster than your IF, since there is no assignment:

``````for x = startNumber to endNumber

counter = counter + 1

if counter mod 4 = 0 then
//do stuff
end

next
``````

I suppose there’s a theoretical hazard that counter would overflow and go bonkers since it isn’t being reset to 0. But that doesn’t seem possible, at least not in this case.

Is a mod calculation faster than a static assignment? I’d guess no, but that’s easy enough to test.

In practice, I doubt it would be a significant difference either way.

Also I would have to check but I don’t think the rollover would matter either since we’re calculating against a power of two.

Good points, all.

I checked and tested. First, as I thought, the rollover, even if it could get that high, is irrelevant, `mod` will still work as desired.

But color me shocked, `mod` is about twice as fast as resetting the variable.

My test code:

``````#if not DebugBuild
#pragma NilObjectChecking False
#pragma StackOverflowChecking False
#pragma BoundsChecking False
#endif

dim msg as string
dim sw as new Stopwatch_MTC
sw.Start

var count as integer
var total as integer

count = 0
total = 0

for i as integer = 0 to 10000000
count = count + 1
if count = 4 then
total = total + count
count = 0
end if
next

sw.Stop

msg = format( sw.ElapsedMicroseconds, "#," ) + " microsecs"

sw.Reset
sw.Start

count = 0
total = 0

for i as integer = 0 to 10000000
count = count + 1
if ( count mod 4 ) = 0 then
total = total + count
end if
next

sw.Stop

msg = format( sw.ElapsedMicroseconds, "#," ) + " microsecs"
``````

That the results of the two calculations don’t match is unimportant. The only reason `total` is there at all is to keep the compiler from doing away with the whole loop.

A typical result:

``````10000000
15,026 microsecs
12500005000000
6,983 microsecs
``````

Tested in a compiled app using Aggressive.

2 Likes

WTF? It is a fixed lenght datatype, It should just overwrite in the same memory addres and be ultra fast.

If this is a bottleneck every time a variable change its value in xojo, they need to look at this ASAP

What OS? What xojo release?

I tested on windows with xojo 2019r2.1 and resetting the variable is about twice as fast. Added another zero to the loop and it is the same.

Since I dont have a licence for most recent releases, I tested in debug mode, it was 19 seconds for resetting the variable and 18 for mod.

BUT, same code in xojo 2023r3 it was 42 seconds for resetting the variable and 40 for mod.

Looks like xojo really messed up the debug performance in half after 2019

Fascinating.

Try changing the modulus to a non-power-of-2 like 5 or 7. I wonder if there’s some amazing optimization that kicks in with powers of 2.

Also - try something like:

``````dim zero as Integer = 0

...

count = zero
``````

…because there’s a chance that the compiler is representing that 0 as a double and doing a conversion every time you assign it.

That makes sense, it might just be shifting bits.

I did try using constants, but that made no difference.