[ODE] dRandInt Crash Fix

Adam D. Moss adam at gimp.org
Wed Jun 22 11:14:52 MST 2005


Jaroslav Sinecky wrote:
> I think there was someone on the list saying that he modified dRandInt to
> use only integer aritmetics and worked fine even with quite a gain in
> performance
> ... oh yes, I found it: http://q12.org/pipermail/ode/2005-May/015834.html

Put into ODE parlance and tweaked a bit, this simply reduces to
something like:

int dRandInt (int n)
{
   const unsigned long r = dRand();
   return ((r>>12)*n)>>20;
}

... which is basically the double-using algorithm converted to
fixed-point.  However, that's just not accurate enough -- try
it with n=5000 for example; it'll leave swathes of the range
untouched.  That's not incorrect behaviour per se, but QuickStep's
solution quality actually relies on dRandInt() not totally sucking.

For an all-int solution, I think it's better to xor-fold
dRand()'s output until we don't feel so bad taking the modulus.

Something like:

int dRandInt (unsigned long un)
{
   unsigned long r = dRand();

   /* probably more aggressive xor-folding than necessary, but...*/
   if (un <= 0x00010000UL) {
     r ^= (r >> 16);
     if (un <= 0x00000100UL) {
       r ^= (r >> 8);
       if (un <= 0x00000010UL) {
         r ^= (r >> 4);
         if (un <= 0x00000004UL) {
           r ^= (r >> 2);
           if (un <= 0x00000002UL) {
             r ^= (r >> 1);
           }
         }
       }
     }
   }

   return (int) (r % un);
}


--adam
-- 
Adam D. Moss   -   adam at gimp.org


More information about the ODE mailing list