Random integer generation

Kevin Ryde user42@zip.com.au
Fri, 21 Feb 2003 09:44:28 +1000


--=-=-=

"Sisyphus" <kalinabears@hdc.com.au> writes:
>
> It was suggested to me (off list) that I read up on on linear congruential
> generators in Knuth.

Pedro Gimeno points out that it's not necessarily silly to have a
smallish "a", a poor choice of words on my part.

I had a go at improving the code, it should fix the case of small or
zero "a", with a bit of luck.


--=-=-=
Content-Disposition: attachment; filename=randraw.c.small-a.diff

--- randraw.c.old	2003-02-21 08:50:32.000000000 +1000
+++ randraw.c	2003-02-21 09:41:04.000000000 +1000
@@ -109,7 +109,9 @@
   seedp = PTR (rstate->_mp_seed);
   seedn = SIZ (rstate->_mp_seed);
 
-  if (seedn == 0)
+  an = SIZ (rstate->_mp_algdata._mp_lc->_mp_a);
+
+  if (seedn == 0 || an == 0)
     {
       /* Seed is 0.  Result is C % M.  Assume table is sensibly stored,
        with C smaller than M*/
@@ -121,13 +123,12 @@
     }
 
   ap = PTR (rstate->_mp_algdata._mp_lc->_mp_a);
-  an = SIZ (rstate->_mp_algdata._mp_lc->_mp_a);
 
   /* Allocate temporary storage.  Let there be room for calculation of
      (A * seed + C) % M, or M if bigger than that.  */
 
   TMP_MARK (mark);
-  ta = an + seedn + 1;
+  ta = MAX (m2exp/GMP_NUMB_BITS, an + seedn) + 1;
   tp = (mp_ptr) TMP_ALLOC (ta * BYTES_PER_MP_LIMB);
 
   /* t = a * seed */
@@ -137,12 +138,13 @@
     mpn_mul (tp, ap, an, seedp, seedn);
   tn = an + seedn;
 
+  if (tn < m2exp/GMP_NUMB_BITS)
+    MPN_ZERO (tp+tn, m2exp/GMP_NUMB_BITS - tn);
+
   /* t = t + c */
   tp[tn] = 0;			/* sentinel, stops MPN_INCR_U */
   MPN_INCR_U (tp, tn, c);
 
-  ASSERT_ALWAYS (m2exp / GMP_NUMB_BITS < ta);
-
   /* t = t % m */
   tp[m2exp / GMP_NUMB_BITS] &= ((mp_limb_t) 1 << m2exp % GMP_NUMB_BITS) - 1;
   tn = (m2exp + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;

--=-=-=--