Skip to content
Commit d226fd5c authored by Jeff Epler's avatar Jeff Epler
Browse files

mb2hal: compute timeouts with integer math

The prior code uses questionable casts to do what can be done with
modulo integer math.

The new code does not give *exactly* the same timeout, because the
calculation
    (int)(float)(this_mb_tx->mb_response_timeout_ms / 1000.0)
is subject to rounding errors, while
    timeout.tv_sec  = this_mb_tx->mb_response_timeout_ms / 1000;
is not.  For example for a response timeout of 2001ms, the old code
would actually give a timeout of 2.000999 seconds, while the new code
gives the correct result of 2.001000 seconds.  The new code begins
giving "radically" different (but again more correct) values around
65536 seconds due to the loss of precision in float arithmetic
(65536.000f == 65536.001f when you have a 24-bit mantissa)

Tested by cut&paste of old and new code into a test harness:

struct timeval fold(long arg)
{
    struct timeval timeout;
    timeout.tv_sec  = (int)(float)(arg / 1000.0);  //int part of the float
    timeout.tv_usec = ((float)(arg / 1000.0) - timeout.tv_sec) * 1000000;
    return timeout;
}

struct timeval fnew(long arg)
{
    struct timeval timeout;
    timeout.tv_sec  = arg / 1000;
    timeout.tv_usec = (arg % 1000) * 1000;
    return timeout;
}

void check(long timeout) {
    struct timeval ta = fold(timeout);
    struct timeval tb = fnew(timeout);

    double a = ta.tv_sec + ta.tv_usec * 1e-6;
    double b = tb.tv_sec + tb.tv_usec * 1e-6;
    if(fabs(a - b) > .001) {
    // if(ta.tv_sec != tb.tv_sec || ta.tv_usec != tb.tv_usec) {
        printf("fail tv_sec %lu: %lu.%06lu != %lu.%06lu\n", timeout,
            (long) ta.tv_sec, (long) ta.tv_usec,
            (long) tb.tv_sec, (long) tb.tv_usec);
    }
}

int main() {
    long i;
    for(i=0; i<1000*1000*1000; i += 500) {
        check(i);
        check(i+1);
        check(i+499);
    }
}
parent c2c5c067
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment