Rust, execute a function, when a f64 iterative counter passes an integer value

Can anyone point me to an example, or show me the Rust code that would execute a function, only when a f64 counter value passes integer values?

I have an iterative ode solver object and I think the rk4 solver algorithm can adjust and optimize the value of the step size dependent variable, time in this case, that it can move ahead at each iteration. I give it settings for start time, end time, and max step size. For example if I want it to start at t=0, and run for a total of 10 minutes, with a max step size of 0.1 minutes, it would integrate the state variables a minimum of 10/0.1 = 100 times. However if it chooses to it could reduce the step size, and do > 100 evaluations. If I wanted to execute function, lets say for example a simple println! macro at approximately t=0,1,2,3 ... 10 this would return the output from the println! macro 11 times. Because the solver algorithm is variable, and f64, the actual value of time most likely won't hit even integer values to execute the macro so I need the test to check what value it executed at last time, and then execute again at the next value greater than or equal to the next integer. Any thoughts or suggestions welcome. There might be a simpler logic/algorithm? Thx. J.

I suggest using an integer for the counter, not a float.

1 Like

I don't think I have that choice, I think the value of the independent variable has to be a float, but I'll check. Thx. J

If you're not able to determine "without any memory" whether a given float crossed an integer, then you're going to need to remember the previous value to compare (as you said). Do I understand correctly that you're asking how to do this in a Fn like context without memory?

Use an accumulator. Add each interval to the accumulator and run your function when it crosses the threshold. Subtract the threshold until the difference in the accumulator is below the threshold. This handles cases where the interval task is both slower and faster than the print task.

The technique is commonly used for synchronizing independently progressing tasks (like running fine grained physics simulation steps and coarse grained drawing steps: Fix Your Timestep! | Gaffer On Games)

Here's a demo using a uniform PRNG:

3 Likes

I think this will work so thanks a bunch. I'm just surprised that it takes so much code to get the job done?

Instead of

// Keep the accumulator below THRESHOLD
while acc >= THRESHOLD {
    acc -= THRESHOLD;
}

you could just do

acc %= THRESHOLD;
2 Likes

So much code relative to what? The == operator? If you look at it that way, then it could seem surprising. It's only half a dozen lines of code. In absolute terms, that's nothing.

Note that everything outside of main is there just to simulate the variable step size you were describing.

2 Likes