Annotation of OpenXM_contrib/gmp/randraw.c, Revision 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>