xref: /dflybsd-src/contrib/gmp/randlc2x.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /* Linear Congruential pseudo-random number generator functions.
286d7f5d3SJohn Marino 
386d7f5d3SJohn Marino Copyright 1999, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
486d7f5d3SJohn Marino 
586d7f5d3SJohn Marino This file is part of the GNU MP Library.
686d7f5d3SJohn Marino 
786d7f5d3SJohn Marino The GNU MP Library is free software; you can redistribute it and/or modify
886d7f5d3SJohn Marino it under the terms of the GNU Lesser General Public License as published by
986d7f5d3SJohn Marino the Free Software Foundation; either version 3 of the License, or (at your
1086d7f5d3SJohn Marino option) any later version.
1186d7f5d3SJohn Marino 
1286d7f5d3SJohn Marino The GNU MP Library is distributed in the hope that it will be useful, but
1386d7f5d3SJohn Marino WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1486d7f5d3SJohn Marino or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
1586d7f5d3SJohn Marino License for more details.
1686d7f5d3SJohn Marino 
1786d7f5d3SJohn Marino You should have received a copy of the GNU Lesser General Public License
1886d7f5d3SJohn Marino along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
1986d7f5d3SJohn Marino 
2086d7f5d3SJohn Marino #include "gmp.h"
2186d7f5d3SJohn Marino #include "gmp-impl.h"
2286d7f5d3SJohn Marino 
2386d7f5d3SJohn Marino 
2486d7f5d3SJohn Marino /* State structure for LC, the RNG_STATE() pointer in a gmp_randstate_t.
2586d7f5d3SJohn Marino 
2686d7f5d3SJohn Marino    _mp_seed holds the current seed value, in the range 0 to 2^m2exp-1.
2786d7f5d3SJohn Marino    SIZ(_mp_seed) is fixed at BITS_TO_LIMBS(_mp_m2exp) and the value is
2886d7f5d3SJohn Marino    padded with high zero limbs if necessary.  ALLOC(_mp_seed) is the current
2986d7f5d3SJohn Marino    size of PTR(_mp_seed) in the usual way.  There only needs to be
3086d7f5d3SJohn Marino    BITS_TO_LIMBS(_mp_m2exp) allocated, but the mpz functions in the
3186d7f5d3SJohn Marino    initialization and seeding end up making it a bit more than this.
3286d7f5d3SJohn Marino 
3386d7f5d3SJohn Marino    _mp_a is the "a" multiplier, in the range 0 to 2^m2exp-1.  SIZ(_mp_a) is
3486d7f5d3SJohn Marino    the size of the value in the normal way for an mpz_t, except that a value
3586d7f5d3SJohn Marino    of zero is held with SIZ(_mp_a)==1 and PTR(_mp_a)[0]==0.  This makes it
3686d7f5d3SJohn Marino    easy to call mpn_mul, and the case of a==0 is highly un-random and not
3786d7f5d3SJohn Marino    worth any trouble to optimize.
3886d7f5d3SJohn Marino 
3986d7f5d3SJohn Marino    {_cp,_cn} is the "c" addend.  Normally _cn is 1, but when nails are in
4086d7f5d3SJohn Marino    use a ulong can be bigger than one limb, and in this case _cn is 2 if
4186d7f5d3SJohn Marino    necessary.  c==0 is stored as _cp[0]==0 and _cn==1, which makes it easy
4286d7f5d3SJohn Marino    to call __GMPN_ADD.  c==0 is fairly un-random so isn't worth optimizing.
4386d7f5d3SJohn Marino 
4486d7f5d3SJohn Marino    _mp_m2exp gives the modulus, namely 2^m2exp.  We demand m2exp>=1, since
4586d7f5d3SJohn Marino    m2exp==0 would mean no bits at all out of each iteration, which makes no
4686d7f5d3SJohn Marino    sense.  */
4786d7f5d3SJohn Marino 
4886d7f5d3SJohn Marino typedef struct {
4986d7f5d3SJohn Marino   mpz_t          _mp_seed;
5086d7f5d3SJohn Marino   mpz_t          _mp_a;
5186d7f5d3SJohn Marino   mp_size_t      _cn;
5286d7f5d3SJohn Marino   mp_limb_t      _cp[LIMBS_PER_ULONG];
5386d7f5d3SJohn Marino   unsigned long  _mp_m2exp;
5486d7f5d3SJohn Marino } gmp_rand_lc_struct;
5586d7f5d3SJohn Marino 
5686d7f5d3SJohn Marino 
5786d7f5d3SJohn Marino /* lc (rp, state) -- Generate next number in LC sequence.  Return the
5886d7f5d3SJohn Marino    number of valid bits in the result.  Discards the lower half of the
5986d7f5d3SJohn Marino    result.  */
6086d7f5d3SJohn Marino 
6186d7f5d3SJohn Marino static unsigned long int
lc(mp_ptr rp,gmp_randstate_t rstate)6286d7f5d3SJohn Marino lc (mp_ptr rp, gmp_randstate_t rstate)
6386d7f5d3SJohn Marino {
6486d7f5d3SJohn Marino   mp_ptr tp, seedp, ap;
6586d7f5d3SJohn Marino   mp_size_t ta;
6686d7f5d3SJohn Marino   mp_size_t tn, seedn, an;
6786d7f5d3SJohn Marino   unsigned long int m2exp;
6886d7f5d3SJohn Marino   unsigned long int bits;
6986d7f5d3SJohn Marino   int cy;
7086d7f5d3SJohn Marino   mp_size_t xn;
7186d7f5d3SJohn Marino   gmp_rand_lc_struct *p;
7286d7f5d3SJohn Marino   TMP_DECL;
7386d7f5d3SJohn Marino 
7486d7f5d3SJohn Marino   p = (gmp_rand_lc_struct *) RNG_STATE (rstate);
7586d7f5d3SJohn Marino 
7686d7f5d3SJohn Marino   m2exp = p->_mp_m2exp;
7786d7f5d3SJohn Marino 
7886d7f5d3SJohn Marino   seedp = PTR (p->_mp_seed);
7986d7f5d3SJohn Marino   seedn = SIZ (p->_mp_seed);
8086d7f5d3SJohn Marino 
8186d7f5d3SJohn Marino   ap = PTR (p->_mp_a);
8286d7f5d3SJohn Marino   an = SIZ (p->_mp_a);
8386d7f5d3SJohn Marino 
8486d7f5d3SJohn Marino   /* Allocate temporary storage.  Let there be room for calculation of
8586d7f5d3SJohn Marino      (A * seed + C) % M, or M if bigger than that.  */
8686d7f5d3SJohn Marino 
8786d7f5d3SJohn Marino   TMP_MARK;
8886d7f5d3SJohn Marino 
8986d7f5d3SJohn Marino   ta = an + seedn + 1;
9086d7f5d3SJohn Marino   tn = BITS_TO_LIMBS (m2exp);
9186d7f5d3SJohn Marino   if (ta <= tn) /* that is, if (ta < tn + 1) */
9286d7f5d3SJohn Marino     {
9386d7f5d3SJohn Marino       mp_size_t tmp = an + seedn;
9486d7f5d3SJohn Marino       ta = tn + 1;
9586d7f5d3SJohn Marino       tp = TMP_ALLOC_LIMBS (ta);
9686d7f5d3SJohn Marino       MPN_ZERO (&tp[tmp], ta - tmp); /* mpn_mul won't zero it out.  */
9786d7f5d3SJohn Marino     }
9886d7f5d3SJohn Marino   else
9986d7f5d3SJohn Marino     tp = TMP_ALLOC_LIMBS (ta);
10086d7f5d3SJohn Marino 
10186d7f5d3SJohn Marino   /* t = a * seed.  NOTE: an is always > 0; see initialization.  */
10286d7f5d3SJohn Marino   ASSERT (seedn >= an && an > 0);
10386d7f5d3SJohn Marino   mpn_mul (tp, seedp, seedn, ap, an);
10486d7f5d3SJohn Marino 
10586d7f5d3SJohn Marino   /* t = t + c.  NOTE: tn is always >= p->_cn (precondition for __GMPN_ADD);
10686d7f5d3SJohn Marino      see initialization.  */
10786d7f5d3SJohn Marino   ASSERT (tn >= p->_cn);
10886d7f5d3SJohn Marino   __GMPN_ADD (cy, tp, tp, tn, p->_cp, p->_cn);
10986d7f5d3SJohn Marino 
11086d7f5d3SJohn Marino   /* t = t % m */
11186d7f5d3SJohn Marino   tp[m2exp / GMP_NUMB_BITS] &= (CNST_LIMB (1) << m2exp % GMP_NUMB_BITS) - 1;
11286d7f5d3SJohn Marino 
11386d7f5d3SJohn Marino   /* Save result as next seed.  */
11486d7f5d3SJohn Marino   MPN_COPY (PTR (p->_mp_seed), tp, tn);
11586d7f5d3SJohn Marino 
11686d7f5d3SJohn Marino   /* Discard the lower m2exp/2 of the result.  */
11786d7f5d3SJohn Marino   bits = m2exp / 2;
11886d7f5d3SJohn Marino   xn = bits / GMP_NUMB_BITS;
11986d7f5d3SJohn Marino 
12086d7f5d3SJohn Marino   tn -= xn;
12186d7f5d3SJohn Marino   if (tn > 0)
12286d7f5d3SJohn Marino     {
12386d7f5d3SJohn Marino       unsigned int cnt = bits % GMP_NUMB_BITS;
12486d7f5d3SJohn Marino       if (cnt != 0)
12586d7f5d3SJohn Marino 	{
12686d7f5d3SJohn Marino 	  mpn_rshift (tp, tp + xn, tn, cnt);
12786d7f5d3SJohn Marino 	  MPN_COPY_INCR (rp, tp, xn + 1);
12886d7f5d3SJohn Marino 	}
12986d7f5d3SJohn Marino       else			/* Even limb boundary.  */
13086d7f5d3SJohn Marino 	MPN_COPY_INCR (rp, tp + xn, tn);
13186d7f5d3SJohn Marino     }
13286d7f5d3SJohn Marino 
13386d7f5d3SJohn Marino   TMP_FREE;
13486d7f5d3SJohn Marino 
13586d7f5d3SJohn Marino   /* Return number of valid bits in the result.  */
13686d7f5d3SJohn Marino   return (m2exp + 1) / 2;
13786d7f5d3SJohn Marino }
13886d7f5d3SJohn Marino 
13986d7f5d3SJohn Marino 
14086d7f5d3SJohn Marino /* Obtain a sequence of random numbers.  */
14186d7f5d3SJohn Marino static void
randget_lc(gmp_randstate_t rstate,mp_ptr rp,unsigned long int nbits)14286d7f5d3SJohn Marino randget_lc (gmp_randstate_t rstate, mp_ptr rp, unsigned long int nbits)
14386d7f5d3SJohn Marino {
14486d7f5d3SJohn Marino   unsigned long int rbitpos;
14586d7f5d3SJohn Marino   int chunk_nbits;
14686d7f5d3SJohn Marino   mp_ptr tp;
14786d7f5d3SJohn Marino   mp_size_t tn;
14886d7f5d3SJohn Marino   gmp_rand_lc_struct *p;
14986d7f5d3SJohn Marino   TMP_DECL;
15086d7f5d3SJohn Marino 
15186d7f5d3SJohn Marino   p = (gmp_rand_lc_struct *) RNG_STATE (rstate);
15286d7f5d3SJohn Marino 
15386d7f5d3SJohn Marino   TMP_MARK;
15486d7f5d3SJohn Marino 
15586d7f5d3SJohn Marino   chunk_nbits = p->_mp_m2exp / 2;
15686d7f5d3SJohn Marino   tn = BITS_TO_LIMBS (chunk_nbits);
15786d7f5d3SJohn Marino 
15886d7f5d3SJohn Marino   tp = TMP_ALLOC_LIMBS (tn);
15986d7f5d3SJohn Marino 
16086d7f5d3SJohn Marino   rbitpos = 0;
16186d7f5d3SJohn Marino   while (rbitpos + chunk_nbits <= nbits)
16286d7f5d3SJohn Marino     {
16386d7f5d3SJohn Marino       mp_ptr r2p = rp + rbitpos / GMP_NUMB_BITS;
16486d7f5d3SJohn Marino 
16586d7f5d3SJohn Marino       if (rbitpos % GMP_NUMB_BITS != 0)
16686d7f5d3SJohn Marino 	{
16786d7f5d3SJohn Marino 	  mp_limb_t savelimb, rcy;
16886d7f5d3SJohn Marino 	  /* Target of new chunk is not bit aligned.  Use temp space
16986d7f5d3SJohn Marino 	     and align things by shifting it up.  */
17086d7f5d3SJohn Marino 	  lc (tp, rstate);
17186d7f5d3SJohn Marino 	  savelimb = r2p[0];
17286d7f5d3SJohn Marino 	  rcy = mpn_lshift (r2p, tp, tn, rbitpos % GMP_NUMB_BITS);
17386d7f5d3SJohn Marino 	  r2p[0] |= savelimb;
17486d7f5d3SJohn Marino 	  /* bogus */
17586d7f5d3SJohn Marino 	  if ((chunk_nbits % GMP_NUMB_BITS + rbitpos % GMP_NUMB_BITS)
17686d7f5d3SJohn Marino 	      > GMP_NUMB_BITS)
17786d7f5d3SJohn Marino 	    r2p[tn] = rcy;
17886d7f5d3SJohn Marino 	}
17986d7f5d3SJohn Marino       else
18086d7f5d3SJohn Marino 	{
18186d7f5d3SJohn Marino 	  /* Target of new chunk is bit aligned.  Let `lc' put bits
18286d7f5d3SJohn Marino 	     directly into our target variable.  */
18386d7f5d3SJohn Marino 	  lc (r2p, rstate);
18486d7f5d3SJohn Marino 	}
18586d7f5d3SJohn Marino       rbitpos += chunk_nbits;
18686d7f5d3SJohn Marino     }
18786d7f5d3SJohn Marino 
18886d7f5d3SJohn Marino   /* Handle last [0..chunk_nbits) bits.  */
18986d7f5d3SJohn Marino   if (rbitpos != nbits)
19086d7f5d3SJohn Marino     {
19186d7f5d3SJohn Marino       mp_ptr r2p = rp + rbitpos / GMP_NUMB_BITS;
19286d7f5d3SJohn Marino       int last_nbits = nbits - rbitpos;
19386d7f5d3SJohn Marino       tn = BITS_TO_LIMBS (last_nbits);
19486d7f5d3SJohn Marino       lc (tp, rstate);
19586d7f5d3SJohn Marino       if (rbitpos % GMP_NUMB_BITS != 0)
19686d7f5d3SJohn Marino 	{
19786d7f5d3SJohn Marino 	  mp_limb_t savelimb, rcy;
19886d7f5d3SJohn Marino 	  /* Target of new chunk is not bit aligned.  Use temp space
19986d7f5d3SJohn Marino 	     and align things by shifting it up.  */
20086d7f5d3SJohn Marino 	  savelimb = r2p[0];
20186d7f5d3SJohn Marino 	  rcy = mpn_lshift (r2p, tp, tn, rbitpos % GMP_NUMB_BITS);
20286d7f5d3SJohn Marino 	  r2p[0] |= savelimb;
20386d7f5d3SJohn Marino 	  if (rbitpos + tn * GMP_NUMB_BITS - rbitpos % GMP_NUMB_BITS < nbits)
20486d7f5d3SJohn Marino 	    r2p[tn] = rcy;
20586d7f5d3SJohn Marino 	}
20686d7f5d3SJohn Marino       else
20786d7f5d3SJohn Marino 	{
20886d7f5d3SJohn Marino 	  MPN_COPY (r2p, tp, tn);
20986d7f5d3SJohn Marino 	}
21086d7f5d3SJohn Marino       /* Mask off top bits if needed.  */
21186d7f5d3SJohn Marino       if (nbits % GMP_NUMB_BITS != 0)
21286d7f5d3SJohn Marino 	rp[nbits / GMP_NUMB_BITS]
21386d7f5d3SJohn Marino 	  &= ~(~CNST_LIMB (0) << nbits % GMP_NUMB_BITS);
21486d7f5d3SJohn Marino     }
21586d7f5d3SJohn Marino 
21686d7f5d3SJohn Marino   TMP_FREE;
21786d7f5d3SJohn Marino }
21886d7f5d3SJohn Marino 
21986d7f5d3SJohn Marino 
22086d7f5d3SJohn Marino static void
randseed_lc(gmp_randstate_t rstate,mpz_srcptr seed)22186d7f5d3SJohn Marino randseed_lc (gmp_randstate_t rstate, mpz_srcptr seed)
22286d7f5d3SJohn Marino {
22386d7f5d3SJohn Marino   gmp_rand_lc_struct *p = (gmp_rand_lc_struct *) RNG_STATE (rstate);
22486d7f5d3SJohn Marino   mpz_ptr seedz = p->_mp_seed;
22586d7f5d3SJohn Marino   mp_size_t seedn = BITS_TO_LIMBS (p->_mp_m2exp);
22686d7f5d3SJohn Marino 
22786d7f5d3SJohn Marino   /* Store p->_mp_seed as an unnormalized integer with size enough
22886d7f5d3SJohn Marino      for numbers up to 2^m2exp-1.  That size can't be zero.  */
22986d7f5d3SJohn Marino   mpz_fdiv_r_2exp (seedz, seed, p->_mp_m2exp);
23086d7f5d3SJohn Marino   MPN_ZERO (&PTR (seedz)[SIZ (seedz)], seedn - SIZ (seedz));
23186d7f5d3SJohn Marino   SIZ (seedz) = seedn;
23286d7f5d3SJohn Marino }
23386d7f5d3SJohn Marino 
23486d7f5d3SJohn Marino 
23586d7f5d3SJohn Marino static void
randclear_lc(gmp_randstate_t rstate)23686d7f5d3SJohn Marino randclear_lc (gmp_randstate_t rstate)
23786d7f5d3SJohn Marino {
23886d7f5d3SJohn Marino   gmp_rand_lc_struct *p = (gmp_rand_lc_struct *) RNG_STATE (rstate);
23986d7f5d3SJohn Marino 
24086d7f5d3SJohn Marino   mpz_clear (p->_mp_seed);
24186d7f5d3SJohn Marino   mpz_clear (p->_mp_a);
24286d7f5d3SJohn Marino   (*__gmp_free_func) (p, sizeof (gmp_rand_lc_struct));
24386d7f5d3SJohn Marino }
24486d7f5d3SJohn Marino 
24586d7f5d3SJohn Marino static void randiset_lc __GMP_PROTO ((gmp_randstate_ptr dst, gmp_randstate_srcptr src));
24686d7f5d3SJohn Marino 
24786d7f5d3SJohn Marino static const gmp_randfnptr_t Linear_Congruential_Generator = {
24886d7f5d3SJohn Marino   randseed_lc,
24986d7f5d3SJohn Marino   randget_lc,
25086d7f5d3SJohn Marino   randclear_lc,
25186d7f5d3SJohn Marino   randiset_lc
25286d7f5d3SJohn Marino };
25386d7f5d3SJohn Marino 
25486d7f5d3SJohn Marino static void
randiset_lc(gmp_randstate_ptr dst,gmp_randstate_srcptr src)25586d7f5d3SJohn Marino randiset_lc (gmp_randstate_ptr dst, gmp_randstate_srcptr src)
25686d7f5d3SJohn Marino {
25786d7f5d3SJohn Marino   gmp_rand_lc_struct *dstp, *srcp;
25886d7f5d3SJohn Marino 
25986d7f5d3SJohn Marino   srcp = (gmp_rand_lc_struct *) RNG_STATE (src);
26086d7f5d3SJohn Marino   dstp = (*__gmp_allocate_func) (sizeof (gmp_rand_lc_struct));
26186d7f5d3SJohn Marino 
26286d7f5d3SJohn Marino   RNG_STATE (dst) = (void *) dstp;
26386d7f5d3SJohn Marino   RNG_FNPTR (dst) = (void *) &Linear_Congruential_Generator;
26486d7f5d3SJohn Marino 
26586d7f5d3SJohn Marino   /* _mp_seed and _mp_a might be unnormalized (high zero limbs), but
26686d7f5d3SJohn Marino      mpz_init_set won't worry about that */
26786d7f5d3SJohn Marino   mpz_init_set (dstp->_mp_seed, srcp->_mp_seed);
26886d7f5d3SJohn Marino   mpz_init_set (dstp->_mp_a,    srcp->_mp_a);
26986d7f5d3SJohn Marino 
27086d7f5d3SJohn Marino   dstp->_cn = srcp->_cn;
27186d7f5d3SJohn Marino 
27286d7f5d3SJohn Marino   dstp->_cp[0] = srcp->_cp[0];
27386d7f5d3SJohn Marino   if (LIMBS_PER_ULONG > 1)
27486d7f5d3SJohn Marino     dstp->_cp[1] = srcp->_cp[1];
27586d7f5d3SJohn Marino   if (LIMBS_PER_ULONG > 2)  /* usually there's only 1 or 2 */
27686d7f5d3SJohn Marino     MPN_COPY (dstp->_cp + 2, srcp->_cp + 2, LIMBS_PER_ULONG - 2);
27786d7f5d3SJohn Marino 
27886d7f5d3SJohn Marino   dstp->_mp_m2exp = srcp->_mp_m2exp;
27986d7f5d3SJohn Marino }
28086d7f5d3SJohn Marino 
28186d7f5d3SJohn Marino 
28286d7f5d3SJohn Marino void
gmp_randinit_lc_2exp(gmp_randstate_t rstate,mpz_srcptr a,unsigned long int c,mp_bitcnt_t m2exp)28386d7f5d3SJohn Marino gmp_randinit_lc_2exp (gmp_randstate_t rstate,
28486d7f5d3SJohn Marino 		      mpz_srcptr a,
28586d7f5d3SJohn Marino 		      unsigned long int c,
28686d7f5d3SJohn Marino 		      mp_bitcnt_t m2exp)
28786d7f5d3SJohn Marino {
28886d7f5d3SJohn Marino   gmp_rand_lc_struct *p;
28986d7f5d3SJohn Marino   mp_size_t seedn = BITS_TO_LIMBS (m2exp);
29086d7f5d3SJohn Marino 
29186d7f5d3SJohn Marino   ASSERT_ALWAYS (m2exp != 0);
29286d7f5d3SJohn Marino 
29386d7f5d3SJohn Marino   p = __GMP_ALLOCATE_FUNC_TYPE (1, gmp_rand_lc_struct);
29486d7f5d3SJohn Marino   RNG_STATE (rstate) = (void *) p;
29586d7f5d3SJohn Marino   RNG_FNPTR (rstate) = (void *) &Linear_Congruential_Generator;
29686d7f5d3SJohn Marino 
29786d7f5d3SJohn Marino   /* allocate m2exp bits of space for p->_mp_seed, and initial seed "1" */
29886d7f5d3SJohn Marino   mpz_init2 (p->_mp_seed, m2exp);
29986d7f5d3SJohn Marino   MPN_ZERO (PTR (p->_mp_seed), seedn);
30086d7f5d3SJohn Marino   SIZ (p->_mp_seed) = seedn;
30186d7f5d3SJohn Marino   PTR (p->_mp_seed)[0] = 1;
30286d7f5d3SJohn Marino 
30386d7f5d3SJohn Marino   /* "a", forced to 0 to 2^m2exp-1 */
30486d7f5d3SJohn Marino   mpz_init (p->_mp_a);
30586d7f5d3SJohn Marino   mpz_fdiv_r_2exp (p->_mp_a, a, m2exp);
30686d7f5d3SJohn Marino 
30786d7f5d3SJohn Marino   /* Avoid SIZ(a) == 0 to avoid checking for special case in lc().  */
30886d7f5d3SJohn Marino   if (SIZ (p->_mp_a) == 0)
30986d7f5d3SJohn Marino     {
31086d7f5d3SJohn Marino       SIZ (p->_mp_a) = 1;
31186d7f5d3SJohn Marino       PTR (p->_mp_a)[0] = CNST_LIMB (0);
31286d7f5d3SJohn Marino     }
31386d7f5d3SJohn Marino 
31486d7f5d3SJohn Marino   MPN_SET_UI (p->_cp, p->_cn, c);
31586d7f5d3SJohn Marino 
31686d7f5d3SJohn Marino   /* Internally we may discard any bits of c above m2exp.  The following
31786d7f5d3SJohn Marino      code ensures that __GMPN_ADD in lc() will always work.  */
31886d7f5d3SJohn Marino   if (seedn < p->_cn)
31986d7f5d3SJohn Marino     p->_cn = (p->_cp[0] != 0);
32086d7f5d3SJohn Marino 
32186d7f5d3SJohn Marino   p->_mp_m2exp = m2exp;
32286d7f5d3SJohn Marino }
323