Walter Lenk wrote: > I have for some time now been using a milliSecond timing routine > derived from the Mac's microSecond clock in many of my projects, and > have recently been wondering about some of the 64 bit to 32 bit math > involved. The process is fairly simple (complete code follows): > > 1. The current uS time is read into 'TimeuS' > 2a. IF this is the first call after the program starts (gStartTimeuS > == 0), > THEN 'TimeuS' is stored in 'gStartTimeuS' and 0 is returned. > 2b, ELSE 'gStartTimeuS' is subtracted from 'TimeuS' to get the uS > time from > program start. I do this because one of my clients leaves his > machines > running 24 hours a day, and the unsigned long output will only > hold > 24.9 days worth of mS before it goes negative. > 3. Turn 'TimeuS' into the long 'mSecs&' by dividing by 1000 -> this > is what I'm not sure of. A 32 bit ms counter will overflow (i.e. start again from zero) after 49.7 days. You need to maintain more bits. fn a_mSeconds# below will "never" overflow. Note that fn a_mSeconds# returns a double; don't assign this to a integer type variable, or you'll be in overflow territory again. Robert P. '-------------------------- include "Tlbx Timer.incl" toolbox U64Subtract( UInt64 * out, UInt32 inLeftHi, UInt32 inLeftLo, UInt32 inRightHi, UInt32 inRightLo ) // UInt64out = UInt64a - UInt64b local fn U64Subtract( @out as ^UInt64, @a as ^UInt64, @b as ^UInt64 ) '~'1 U64Subtract( #out, a.hi, a.lo, b.hi, b.lo ) end fn local fn DoubleFromUInt64#( @u as ^UInt64 ) '~'1 dim as double tmp tmp = u.lo if ( u.lo < 0 ) then tmp += 4294967296.0 //if ( u.hi > 2097152 ) or ( u.hi < 0 ) then stop "Loss of precision in DoubleFromUInt64#" end fn = 4294967296.0*u.hi + tmp /* ms since first call, as double value */ local fn a_mSeconds# '~'1 dim as UnsignedWide rawMicroseconds, diffMicroseconds begin globals dim as UnsignedWide sStartMicroseconds end globals Microseconds( @rawMicroseconds ) long if ( sStartMicroseconds.lo == 0 and sStartMicroseconds.hi == 0 ) sStartMicroseconds = rawMicroseconds end if fn U64Subtract( @diffMicroseconds, @rawMicroseconds, @sStartMicroseconds ) // convert diffMicroseconds to ms as integer-valued double end fn = fix( fn DoubleFromUInt64#( diffMicroseconds ) * 0.001 ) // demo main print fn a_mSeconds# print fn a_mSeconds# print fn a_mSeconds# delay 1000 print fn a_mSeconds# stop '--------------------------