nano2tick_hack() now gives exactly correct answer (rounded down to nearest integer)
authorFrank Mori Hess <fmhess@speakeasy.net>
Fri, 11 May 2001 16:00:22 +0000 (16:00 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Fri, 11 May 2001 16:00:22 +0000 (16:00 +0000)
comedi/drivers/comedi_rt_timer.c

index 0574f84645615f9ec375723e78eaa97e8e83c6f2..6550b00e229b2b7127018f17457d545fdf209f79 100644 (file)
 // begin hack to fix HRT_TO_8254() function on rtlinux
 #undef HRT_TO_8254(x)
 #define HRT_TO_8254(x) nano2tick_hack(x)
-long long nano2tick_hack(long long ns)
+// this function sole purpose is to divide a long long by 838
+inline long long nano2tick_hack(long long ns)
 {
-       unsigned long most = ns >> 32;
-       unsigned long least = ns;
-       unsigned long denom = 838;
-       unsigned long remainder = (most % denom);
-
-       most /= denom;
-       least = remainder * (0xffffffff / denom) + (remainder + least) / denom;
-
-       ns = (long long) most * (long long) 0x100000000 + (long long) least;
+       unsigned long denom = 838;      // divisor
+       long ms32 = ns >> 32;   // most significant 32 bits
+       unsigned long ms32rem = ms32 % denom;   // remainder of ms32 / denom
+       unsigned long ls32 = ns;        // least significant 32 bits
+       unsigned long ls32rem = ls32 % denom;
+       unsigned long big = 0xffffffff;
+       unsigned long big_rem = big % denom;
+       unsigned long rem_rem;
+
+       // divide most significant bits
+       ns = ms32 / denom;
+       ns = ns << 32;
+       // add corrections due to rounding errors
+       ns += ms32rem * (big / denom) + (ms32rem * (big_rem + 1)) / denom;
+       // divide least significant bits
+       ns += ls32 / denom;
+       // add really small correction
+       rem_rem = (ms32rem * (big_rem+1)) % denom;
+       ns += (ls32rem + rem_rem) / denom;
 
        return ns;
 }