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); } }
Loading
Please register or sign in to comment