[BACK]Return to randraw.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp

Annotation of OpenXM_contrib/gmp/randraw.c, Revision 1.1.1.1

1.1       maekawa     1: /* _gmp_rand (rp, state, nbits) -- Generate a random bitstream of
                      2:    length NBITS in RP.  RP must have enough space allocated to hold
                      3:    NBITS.
                      4:
                      5: Copyright (C) 1999, 2000 Free Software Foundation, Inc.
                      6:
                      7: This file is part of the GNU MP Library.
                      8:
                      9: The GNU MP Library is free software; you can redistribute it and/or modify
                     10: it under the terms of the GNU Lesser General Public License as published by
                     11: the Free Software Foundation; either version 2.1 of the License, or (at your
                     12: option) any later version.
                     13:
                     14: The GNU MP Library is distributed in the hope that it will be useful, but
                     15: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     16: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
                     17: License for more details.
                     18:
                     19: You should have received a copy of the GNU Lesser General Public License
                     20: along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
                     21: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     22: MA 02111-1307, USA. */
                     23:
                     24: #include "gmp.h"
                     25: #include "gmp-impl.h"
                     26: #include "longlong.h"
                     27:
                     28: /* For linear congruential (LC), we use one of algorithms (1) or (2).
                     29:    (gmp-3.0 uses algorithm (1) with 'm' as a power of 2.)
                     30:
                     31: LC algorithm (1).
                     32:
                     33:        X = (aX + c) mod m
                     34:
                     35: [D. Knuth, "The Art of Computer Programming: Volume 2, Seminumerical Algorithms",
                     36: Third Edition, Addison Wesley, 1998, pp. 184-185.]
                     37:
                     38:        X is the seed and the result
                     39:        a is chosen so that
                     40:            a mod 8 = 5 [3.2.1.2] and [3.2.1.3]
                     41:            .01m < a < .99m
                     42:            its binary or decimal digits is not a simple, regular pattern
                     43:            it has no large quotients when Euclid's algorithm is used to find
                     44:              gcd(a, m) [3.3.3]
                     45:            it passes the spectral test [3.3.4]
                     46:            it passes several tests of [3.3.2]
                     47:        c has no factor in common with m (c=1 or c=a can be good)
                     48:        m is large (2^30)
                     49:          is a power of 2 [3.2.1.1]
                     50:
                     51: The least significant digits of the generated number are not very
                     52: random.  It should be regarded as a random fraction X/m.  To get a
                     53: random integer between 0 and n-1, multiply X/m by n and truncate.
                     54: (Don't use X/n [ex 3.4.1-3])
                     55:
                     56: The ``accuracy'' in t dimensions is one part in ``the t'th root of m'' [3.3.4].
                     57:
                     58: Don't generate more than about m/1000 numbers without changing a, c, or m.
                     59:
                     60: The sequence length depends on chosen a,c,m.
                     61:
                     62:
                     63: LC algorithm (2).
                     64:
                     65:        X = a * (X mod q) - r * (long) (X/q)
                     66:        if X<0 then X+=m
                     67:
                     68: [Knuth, pp. 185-186.]
                     69:
                     70:        X is the seed and the result
                     71:          as a seed is nonzero and less than m
                     72:        a is a primitive root of m (which means that a^2 <= m)
                     73:        q is (long) m / a
                     74:        r is m mod a
                     75:        m is a prime number near the largest easily computed integer
                     76:
                     77: which gives
                     78:
                     79:        X = a * (X % ((long) m / a)) -
                     80:            (M % a) * ((long) (X / ((long) m / a)))
                     81:
                     82: Since m is prime, the least-significant bits of X are just as random as
                     83: the most-significant bits. */
                     84:
                     85: /* Blum, Blum, and Shub.
                     86:
                     87:    [Bruce Schneier, "Applied Cryptography", Second Edition, John Wiley
                     88:    & Sons, Inc., 1996, pp. 417-418.]
                     89:
                     90:    "Find two large prime numbers, p and q, which are congruent to 3
                     91:    modulo 4.  The product of those numbers, n, is a blum integer.
                     92:    Choose another random integer, x, which is relatively prime to n.
                     93:    Compute
                     94:        x[0] = x^2 mod n
                     95:    That's the seed for the generator."
                     96:
                     97:    To generate a random bit, compute
                     98:        x[i] = x[i-1]^2 mod n
                     99:    The least significant bit of x[i] is the one we want.
                    100:
                    101:    We can use more than one bit from x[i], namely the
                    102:        log2(bitlength of x[i])
                    103:    least significant bits of x[i].
                    104:
                    105:    So, for a 32-bit seed we get 5 bits per computation.
                    106:
                    107:    The non-predictability of this generator is based on the difficulty
                    108:    of factoring n.
                    109:  */
                    110:
                    111: /* -------------------------------------------------- */
                    112:
                    113: /* lc (rp, state) -- Generate next number in LC sequence.  Return the
                    114:    number of valid bits in the result.  NOTE: If 'm' is a power of 2
                    115:    (m2exp != 0), discard the lower half of the result.  */
                    116:
                    117: static
                    118: unsigned long int
                    119: #if __STDC__
                    120: lc (mp_ptr rp, gmp_randstate_t rstate)
                    121: #else
                    122: lc (rp, rstate)
                    123:      mp_ptr rp;
                    124:      gmp_randstate_t rstate;
                    125: #endif
                    126: {
                    127:   mp_ptr tp, seedp, ap;
                    128:   mp_size_t ta;
                    129:   mp_size_t tn, seedn, an;
                    130:   mp_size_t retval;
                    131:   int shiftcount = 0;
                    132:   unsigned long int m2exp;
                    133:   mp_limb_t c;
                    134:   TMP_DECL (mark);
                    135:
                    136:   m2exp = rstate->algdata.lc->m2exp;
                    137:   c = (mp_limb_t) rstate->algdata.lc->c;
                    138:
                    139:   seedp = PTR (rstate->seed);
                    140:   seedn = SIZ (rstate->seed);
                    141:
                    142:   if (seedn == 0)
                    143:     {
                    144:       /* Seed is 0.  Result is C % M.  */
                    145:       *rp = c;
                    146:
                    147:       if (m2exp != 0)
                    148:        {
                    149:          /* M is a power of 2.  */
                    150:          if (m2exp < BITS_PER_MP_LIMB)
                    151:            {
                    152:              /* Only necessary when M may be smaller than C.  */
                    153:              *rp &= (((mp_limb_t) 1 << m2exp) - 1);
                    154:            }
                    155:        }
                    156:       else
                    157:        {
                    158:          /* M is not a power of 2.  */
                    159:          abort ();             /* FIXME.  */
                    160:        }
                    161:
                    162:       /* Save result as next seed.  */
                    163:       *seedp = *rp;
                    164:       SIZ (rstate->seed) = 1;
                    165:       return BITS_PER_MP_LIMB;
                    166:     }
                    167:
                    168:   ap = PTR (rstate->algdata.lc->a);
                    169:   an = SIZ (rstate->algdata.lc->a);
                    170:
                    171:   /* Allocate temporary storage.  Let there be room for calculation of
                    172:      (A * seed + C) % M, or M if bigger than that.  */
                    173:
                    174:   ASSERT_ALWAYS (m2exp != 0);  /* FIXME.  */
                    175:
                    176:   TMP_MARK (mark);
                    177:   ta = an + seedn + 1;
                    178:   tp = (mp_ptr) TMP_ALLOC (ta * BYTES_PER_MP_LIMB);
                    179:   MPN_ZERO (tp, ta);
                    180:
                    181:   /* t = a * seed */
                    182:   if (seedn >= an)
                    183:     mpn_mul_basecase (tp, seedp, seedn, ap, an);
                    184:   else
                    185:     mpn_mul_basecase (tp, ap, an, seedp, seedn);
                    186:   tn = an + seedn;
                    187:
                    188:   /* t = t + c */
                    189:   mpn_incr_u (tp, c);
                    190:
                    191:   /* t = t % m */
                    192:   if (m2exp != 0)
                    193:     {
                    194:       /* M is a power of 2.  The mod operation is trivial.  */
                    195:
                    196:       tp[m2exp / BITS_PER_MP_LIMB] &= ((mp_limb_t) 1 << m2exp % BITS_PER_MP_LIMB) - 1;
                    197:       tn = (m2exp + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB;
                    198:     }
                    199:   else
                    200:     {
                    201:       abort ();                        /* FIXME.  */
                    202:     }
                    203:
                    204:   /* Save result as next seed.  */
                    205:   MPN_COPY (PTR (rstate->seed), tp, tn);
                    206:   SIZ (rstate->seed) = tn;
                    207:
                    208:   if (m2exp != 0)
                    209:     {
                    210:       /* Discard the lower half of the result.  */
                    211:       unsigned long int discardb = m2exp / 2;
                    212:       mp_size_t discardl = discardb / BITS_PER_MP_LIMB;
                    213:
                    214:       tn -= discardl;
                    215:       if (tn > 0)
                    216:        {
                    217:          if (discardb % BITS_PER_MP_LIMB != 0)
                    218:            {
                    219:              mpn_rshift (tp, tp + discardl, tn, discardb % BITS_PER_MP_LIMB);
                    220:              MPN_COPY (rp, tp, (discardb + BITS_PER_MP_LIMB -1) / BITS_PER_MP_LIMB);
                    221:            }
                    222:          else                  /* Even limb boundary.  */
                    223:            MPN_COPY_INCR (rp, tp + discardl, tn);
                    224:        }
                    225:     }
                    226:   else
                    227:     {
                    228:       MPN_COPY (rp, tp, tn);
                    229:     }
                    230:
                    231:   TMP_FREE (mark);
                    232:
                    233:   /* Return number of valid bits in the result.  */
                    234:   if (m2exp != 0)
                    235:     retval = (m2exp + 1) / 2;
                    236:   else
                    237:     retval = SIZ (rstate->algdata.lc->m) * BITS_PER_MP_LIMB - shiftcount;
                    238:   return retval;
                    239: }
                    240:
                    241: #ifdef RAWRANDEBUG
                    242: /* Set even bits to EVENBITS and odd bits to ! EVENBITS in RP.
                    243:    Number of bits is m2exp in state.  */
                    244: /* FIXME: Remove.  */
                    245: unsigned long int
                    246: lc_test (mp_ptr rp, gmp_randstate_t s, const int evenbits)
                    247: {
                    248:   unsigned long int rn, nbits;
                    249:   int f;
                    250:
                    251:   nbits = s->algdata.lc->m2exp / 2;
                    252:   rn = nbits / BITS_PER_MP_LIMB + (nbits % BITS_PER_MP_LIMB != 0);
                    253:   MPN_ZERO (rp, rn);
                    254:
                    255:   for (f = 0; f < nbits; f++)
                    256:     {
                    257:       mpn_lshift (rp, rp, rn, 1);
                    258:       if (f % 2 == ! evenbits)
                    259:        rp[0] += 1;
                    260:     }
                    261:
                    262:   return nbits;
                    263: }
                    264: #endif /* RAWRANDEBUG */
                    265:
                    266: void
                    267: #if __STDC__
                    268: _gmp_rand (mp_ptr rp, gmp_randstate_t rstate, unsigned long int nbits)
                    269: #else
                    270: _gmp_rand (rp, rstate, nbits)
                    271:      mp_ptr rp;
                    272:      gmp_randstate_t rstate;
                    273:      unsigned long int nbits;
                    274: #endif
                    275: {
                    276:   mp_size_t rn;                        /* Size of R.  */
                    277:
                    278:   rn = (nbits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB;
                    279:
                    280:   switch (rstate->alg)
                    281:     {
                    282:     case GMP_RAND_ALG_LC:
                    283:       {
                    284:        unsigned long int rbitpos;
                    285:        int chunk_nbits;
                    286:        mp_ptr tp;
                    287:        mp_size_t tn;
                    288:        TMP_DECL (lcmark);
                    289:
                    290:        TMP_MARK (lcmark);
                    291:
                    292:        chunk_nbits = rstate->algdata.lc->m2exp / 2;
                    293:        tn = (chunk_nbits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB;
                    294:
                    295:        tp = (mp_ptr) TMP_ALLOC (tn * BYTES_PER_MP_LIMB);
                    296:
                    297:        rbitpos = 0;
                    298:        while (rbitpos + chunk_nbits <= nbits)
                    299:          {
                    300:            mp_ptr r2p = rp + rbitpos / BITS_PER_MP_LIMB;
                    301:
                    302:            if (rbitpos % BITS_PER_MP_LIMB != 0)
                    303:              {
                    304:                mp_limb_t savelimb, rcy;
                    305:                /* Target of of new chunk is not bit aligned.  Use temp space
                    306:                   and align things by shifting it up.  */
                    307:                lc (tp, rstate);
                    308:                savelimb = r2p[0];
                    309:                rcy = mpn_lshift (r2p, tp, tn, rbitpos % BITS_PER_MP_LIMB);
                    310:                r2p[0] |= savelimb;
                    311: /* bogus */    if ((chunk_nbits % BITS_PER_MP_LIMB + rbitpos % BITS_PER_MP_LIMB)
                    312:                    > BITS_PER_MP_LIMB)
                    313:                  r2p[tn] = rcy;
                    314:              }
                    315:            else
                    316:              {
                    317:                /* Target of of new chunk is bit aligned.  Let `lc' put bits
                    318:                   directly into our target variable.  */
                    319:                lc (r2p, rstate);
                    320:              }
                    321:            rbitpos += chunk_nbits;
                    322:          }
                    323:
                    324:        /* Handle last [0..chunk_nbits) bits.  */
                    325:        if (rbitpos != nbits)
                    326:          {
                    327:            mp_ptr r2p = rp + rbitpos / BITS_PER_MP_LIMB;
                    328:            int last_nbits = nbits - rbitpos;
                    329:            tn = (last_nbits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB;
                    330:            lc (tp, rstate);
                    331:            if (rbitpos % BITS_PER_MP_LIMB != 0)
                    332:              {
                    333:                mp_limb_t savelimb, rcy;
                    334:                /* Target of of new chunk is not bit aligned.  Use temp space
                    335:                   and align things by shifting it up.  */
                    336:                savelimb = r2p[0];
                    337:                rcy = mpn_lshift (r2p, tp, tn, rbitpos % BITS_PER_MP_LIMB);
                    338:                r2p[0] |= savelimb;
                    339:                if (rbitpos + tn * BITS_PER_MP_LIMB - rbitpos % BITS_PER_MP_LIMB < nbits)
                    340:                  r2p[tn] = rcy;
                    341:              }
                    342:            else
                    343:              {
                    344:                MPN_COPY (r2p, tp, tn);
                    345:              }
                    346:            /* Mask off top bits if needed.  */
                    347:            if (nbits % BITS_PER_MP_LIMB != 0)
                    348:              rp[nbits / BITS_PER_MP_LIMB]
                    349:                &= ~ ((~(mp_limb_t) 0) << nbits % BITS_PER_MP_LIMB);
                    350:          }
                    351:
                    352:        TMP_FREE (lcmark);
                    353:        break;
                    354:       }
                    355:
                    356:     default:
                    357:       gmp_errno |= GMP_ERROR_UNSUPPORTED_ARGUMENT;
                    358:       break;
                    359:     }
                    360: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>