Beispiel #1
0
/* Exercise values 2^n+1, while such a value fits the mantissa of a double. */
void
check_twobit (void)
{
  int        i, mant_bits;
  double     got, want;
  mp_size_t  nsize, sign;
  mp_ptr     np;

  mant_bits = tests_dbl_mant_bits ();
  if (mant_bits == 0)
    return;

  np = refmpn_malloc_limbs (BITS_TO_LIMBS (mant_bits));
  want = 3.0;
  for (i = 1; i < mant_bits; i++)
    {
      nsize = BITS_TO_LIMBS (i+1);
      refmpn_zero (np, nsize);
      np[i/GMP_NUMB_BITS] = CNST_LIMB(1) << (i % GMP_NUMB_BITS);
      np[0] |= 1;

      for (sign = 0; sign >= -1; sign--)
        {
          got = mpn_get_d (np, nsize, sign, 0);
          if (got != want)
            {
              printf    ("mpn_get_d wrong on 2^%d + 1\n", i);
              printf    ("   sign     %ld\n", (long) sign);
              mpn_trace ("   n        ", np, nsize);
              printf    ("   nsize    %ld\n", (long) nsize);
              d_trace   ("   want     ", want);
              d_trace   ("   got      ", got);
              abort();
            }
          want = -want;
        }

      want = 2.0 * want - 1.0;
    }

  free (np);
}
/* 
   c is the top bits of the inputs, (fully reduced)
   c & 2 is the top bit of y
   c & 1 is the top bit of z
*/
int
mpn_mulmod_2expp1_basecase (mp_ptr xp, mp_srcptr yp, mp_srcptr zp, 
                                           int c, mpir_ui b, mp_ptr tp)
{
  int cy, cz;
  mp_size_t n, k;

  cy = c & 2;
  cz = c & 1;

  n = BITS_TO_LIMBS (b);
  k = GMP_NUMB_BITS * n - b;

  ASSERT(b > 0);
  ASSERT(n > 0);
  ASSERT_MPN(yp, n);
  ASSERT_MPN(zp, n);
  ASSERT(!MPN_OVERLAP_P (tp, 2 * n, yp, n));
  ASSERT(!MPN_OVERLAP_P (tp, 2 * n, zp, n));
  ASSERT(MPN_SAME_OR_SEPARATE_P (xp, tp, n));
  ASSERT(MPN_SAME_OR_SEPARATE_P (xp, tp + n, n));
  ASSERT(k == 0 || yp[n - 1] >> (GMP_NUMB_BITS - k) == 0);
  ASSERT(k == 0 || zp[n - 1] >> (GMP_NUMB_BITS - k) == 0);

#if WANT_ASSERT
  {
     mp_size_t t = n;

     MPN_NORMALIZE(yp, t);
     ASSERT(cy == 0 || t == 0);
     
     t = n; 
     MPN_NORMALIZE(zp, t);
     ASSERT(cz == 0 || t == 0);
  }
#endif

  if (LIKELY (cy == 0))
    {
      if (LIKELY (cz == 0))
	{
	  c = mpn_mulmod_2expp1_internal (xp, yp, zp, b, tp);
	}
      else
	{
	  c = mpn_neg_n (xp, yp, n);
	  c = mpn_add_1 (xp, xp, n, c);
	  xp[n - 1] &= GMP_NUMB_MASK >> k;
	}
    }
  else
    {
      if (LIKELY (cz == 0))
Beispiel #3
0
void
mpz_urandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long int nbits)
{
  mp_ptr rp;
  mp_size_t size;

  size = BITS_TO_LIMBS (nbits);
  rp = MPZ_REALLOC (rop, size);

  _gmp_rand (rp, rstate, nbits);
  MPN_NORMALIZE (rp, size);
  SIZ (rop) = size;
}
Beispiel #4
0
static void
randseed_lc (gmp_randstate_t rstate, mpz_srcptr seed)
{
  gmp_rand_lc_struct *p = (gmp_rand_lc_struct *) RNG_STATE (rstate);
  mpz_ptr seedz = p->_mp_seed;
  mp_size_t seedn = BITS_TO_LIMBS (p->_mp_m2exp);

  /* Store p->_mp_seed as an unnormalized integer with size enough
     for numbers up to 2^m2exp-1.  That size can't be zero.  */
  mpz_fdiv_r_2exp (seedz, seed, p->_mp_m2exp);
  MPN_ZERO (&PTR (seedz)[SIZ (seedz)], seedn - SIZ (seedz));
  SIZ (seedz) = seedn;
}
Beispiel #5
0
void
mpz_rrandomb (mpz_ptr x, gmp_randstate_t rstate, mp_bitcnt_t nbits)
{
  mp_size_t nl;
  mp_ptr xp;

  nl = BITS_TO_LIMBS (nbits);
  if (nbits != 0)
    {
      xp = MPZ_NEWALLOC (x, nl);
      gmp_rrandomb (xp, rstate, nbits);
    }

  SIZ(x) = nl;
}
Beispiel #6
0
void
gmp_randinit_lc_2exp (gmp_randstate_t rstate,
		      mpz_srcptr a,
		      unsigned long int c,
		      mp_bitcnt_t m2exp)
{
  gmp_rand_lc_struct *p;
  mp_size_t seedn = BITS_TO_LIMBS (m2exp);

  ASSERT_ALWAYS (m2exp != 0);

  p = __GMP_ALLOCATE_FUNC_TYPE (1, gmp_rand_lc_struct);
  RNG_STATE (rstate) = (void *) p;
  RNG_FNPTR (rstate) = (void *) &Linear_Congruential_Generator;

  /* allocate m2exp bits of space for p->_mp_seed, and initial seed "1" */
  mpz_init2 (p->_mp_seed, m2exp);
  MPN_ZERO (PTR (p->_mp_seed), seedn);
  SIZ (p->_mp_seed) = seedn;
  PTR (p->_mp_seed)[0] = 1;

  /* "a", forced to 0 to 2^m2exp-1 */
  mpz_init (p->_mp_a);
  mpz_fdiv_r_2exp (p->_mp_a, a, m2exp);

  /* Avoid SIZ(a) == 0 to avoid checking for special case in lc().  */
  if (SIZ (p->_mp_a) == 0)
    {
      SIZ (p->_mp_a) = 1;
      PTR (p->_mp_a)[0] = CNST_LIMB (0);
    }

  MPN_SET_UI (p->_cp, p->_cn, c);

  /* Internally we may discard any bits of c above m2exp.  The following
     code ensures that __GMPN_ADD in lc() will always work.  */
  if (seedn < p->_cn)
    p->_cn = (p->_cp[0] != 0);

  p->_mp_m2exp = m2exp;
}
Beispiel #7
0
static void
gmp_rrandomb (mp_ptr rp, gmp_randstate_t rstate, mp_bitcnt_t nbits)
{
  mp_bitcnt_t bi;
  mp_limb_t ranm;		/* buffer for random bits */
  unsigned cap_chunksize, chunksize;
  mp_size_t i;

  /* Set entire result to 111..1  */
  i = BITS_TO_LIMBS (nbits) - 1;
  rp[i] = GMP_NUMB_MAX >> (GMP_NUMB_BITS - (nbits % GMP_NUMB_BITS)) % GMP_NUMB_BITS;
  for (i = i - 1; i >= 0; i--)
    rp[i] = GMP_NUMB_MAX;

  _gmp_rand (&ranm, rstate, BITS_PER_RANDCALL);
  cap_chunksize = nbits / (ranm % 4 + 1);
  cap_chunksize += cap_chunksize == 0; /* make it at least 1 */

  bi = nbits;

  for (;;)
    {
      _gmp_rand (&ranm, rstate, BITS_PER_RANDCALL);
      chunksize = 1 + ranm % cap_chunksize;
      bi = (bi < chunksize) ? 0 : bi - chunksize;

      if (bi == 0)
	break;			/* low chunk is ...1 */

      rp[bi / GMP_NUMB_BITS] ^= CNST_LIMB (1) << bi % GMP_NUMB_BITS;

      _gmp_rand (&ranm, rstate, BITS_PER_RANDCALL);
      chunksize = 1 + ranm % cap_chunksize;
      bi = (bi < chunksize) ? 0 : bi - chunksize;

      mpn_incr_u (rp + bi / GMP_NUMB_BITS, CNST_LIMB (1) << bi % GMP_NUMB_BITS);

      if (bi == 0)
	break;			/* low chunk is ...0 */
    }
}
/*
   ret + (xp, n) = (yp, n)*(zp, n) % 2^b + 1  
   needs (tp, 2n) temp space, everything reduced mod 2^b 
   inputs, outputs are fully reduced
  
   N.B: 2n is not the same as 2b rounded up to nearest limb!
*/
inline static int
mpn_mulmod_2expp1_internal (mp_ptr xp, mp_srcptr yp, mp_srcptr zp,
			                                         mpir_ui b, mp_ptr tp)
{
  mp_size_t n, k;
  mp_limb_t c;

  TMP_DECL;

  n = BITS_TO_LIMBS (b);
  k = GMP_NUMB_BITS * n - b;

  ASSERT(b > 0);
  ASSERT(n > 0);
  ASSERT_MPN(yp, n);
  ASSERT_MPN(zp, n);
  ASSERT(!MPN_OVERLAP_P (tp, 2 * n, yp, n));
  ASSERT(!MPN_OVERLAP_P (tp, 2 * n, zp, n));
  ASSERT(MPN_SAME_OR_SEPARATE_P (xp, tp, n));
  ASSERT(MPN_SAME_OR_SEPARATE_P (xp, tp + n, n));
  ASSERT(k == 0 || yp[n - 1] >> (GMP_NUMB_BITS - k) == 0);
  ASSERT(k == 0 || zp[n - 1] >> (GMP_NUMB_BITS - k) == 0);

#ifndef TUNE_PROGRAM_BUILD
  if (k == 0 && n > FFT_MULMOD_2EXPP1_CUTOFF && n == mpir_fft_adjust_limbs(n))
  {
      mp_bitcnt_t depth1, depth = 1;
      mp_size_t w1, off;
      mp_ptr tx, ty, tz;
      mp_limb_t ret;

      TMP_MARK;

      tx = TMP_BALLOC_LIMBS(3*n + 3);
      ty = tx + n + 1;
      tz = ty + n + 1;

      MPN_COPY(ty, yp, n);
      MPN_COPY(tz, zp, n);
      ty[n] = 0;
      tz[n] = 0;

      while ((((mp_limb_t)1)<<depth) < b) depth++;
   
      if (depth < 12) off = mulmod_2expp1_table_n[0];
      else off = mulmod_2expp1_table_n[MIN(depth, FFT_N_NUM + 11) - 12];
      depth1 = depth/2 - off;
   
      w1 = b/(((mp_limb_t)1)<<(2*depth1));

      mpir_fft_mulmod_2expp1(tx, ty, tz, n, depth1, w1);

      MPN_COPY(xp, tx, n);
      ret = tx[n];
      
      TMP_FREE;

	   return ret;
  }
#endif

  if (yp == zp)
     mpn_sqr(tp, yp, n);
  else
     mpn_mul_n (tp, yp, zp, n);

  if (k == 0)
    {
      c = mpn_sub_n (xp, tp, tp + n, n);

      return mpn_add_1 (xp, xp, n, c);
    }

  c = tp[n - 1];
  tp[n - 1] &= GMP_NUMB_MASK >> k;

#if HAVE_NATIVE_mpn_sublsh_nc
  c = mpn_sublsh_nc (xp, tp, tp + n, n, k, c);
#else
  {
    mp_limb_t c1;
    c1 = mpn_lshift (tp + n, tp + n, n, k);
    tp[n] |= c >> (GMP_NUMB_BITS - k);
    c = mpn_sub_n (xp, tp, tp + n, n) + c1;
  }
#endif

  c = mpn_add_1 (xp, xp, n, c);
  xp[n - 1] &= GMP_NUMB_MASK >> k;

  return c;
}
Beispiel #9
0
static unsigned long int
lc (mp_ptr rp, gmp_randstate_t rstate)
{
  mp_ptr tp, seedp, ap;
  mp_size_t ta;
  mp_size_t tn, seedn, an;
  unsigned long int m2exp;
  unsigned long int bits;
  int cy;
  mp_size_t xn;
  gmp_rand_lc_struct *p;
  TMP_DECL;

  p = (gmp_rand_lc_struct *) RNG_STATE (rstate);

  m2exp = p->_mp_m2exp;

  seedp = PTR (p->_mp_seed);
  seedn = SIZ (p->_mp_seed);

  ap = PTR (p->_mp_a);
  an = SIZ (p->_mp_a);

  /* Allocate temporary storage.  Let there be room for calculation of
     (A * seed + C) % M, or M if bigger than that.  */

  TMP_MARK;

  ta = an + seedn + 1;
  tn = BITS_TO_LIMBS (m2exp);
  if (ta <= tn) /* that is, if (ta < tn + 1) */
    {
      mp_size_t tmp = an + seedn;
      ta = tn + 1;
      tp = (mp_ptr) TMP_ALLOC (ta * BYTES_PER_MP_LIMB);
      MPN_ZERO (&tp[tmp], ta - tmp); /* mpn_mul won't zero it out.  */
    }
  else
    tp = (mp_ptr) TMP_ALLOC (ta * BYTES_PER_MP_LIMB);

  /* t = a * seed.  NOTE: an is always > 0; see initialization.  */
  ASSERT (seedn >= an && an > 0);
  mpn_mul (tp, seedp, seedn, ap, an);

  /* t = t + c.  NOTE: tn is always >= p->_cn (precondition for __GMPN_ADD);
     see initialization.  */
  ASSERT (tn >= p->_cn);
  __GMPN_ADD (cy, tp, tp, tn, p->_cp, p->_cn);

  /* t = t % m */
  tp[m2exp / GMP_NUMB_BITS] &= (CNST_LIMB (1) << m2exp % GMP_NUMB_BITS) - 1;

  /* Save result as next seed.  */
  MPN_COPY (PTR (p->_mp_seed), tp, tn);

  /* Discard the lower m2exp/2 of the result.  */
  bits = m2exp / 2;
  xn = bits / GMP_NUMB_BITS;

  tn -= xn;
  if (tn > 0)
    {
      unsigned int cnt = bits % GMP_NUMB_BITS;
      if (cnt != 0)
	{
	  mpn_rshift (tp, tp + xn, tn, cnt);
	  MPN_COPY_INCR (rp, tp, xn + 1);
	}
      else			/* Even limb boundary.  */
	MPN_COPY_INCR (rp, tp + xn, tn);
    }

  TMP_FREE;

  /* Return number of valid bits in the result.  */
  return (m2exp + 1) / 2;
}
Beispiel #10
0
/* Obtain a sequence of random numbers.  */
static void
randget_lc (gmp_randstate_t rstate, mp_ptr rp, unsigned long int nbits)
{
  unsigned long int rbitpos;
  int chunk_nbits;
  mp_ptr tp;
  mp_size_t tn;
  gmp_rand_lc_struct *p;
  TMP_DECL;

  p = (gmp_rand_lc_struct *) RNG_STATE (rstate);

  TMP_MARK;

  chunk_nbits = p->_mp_m2exp / 2;
  tn = BITS_TO_LIMBS (chunk_nbits);

  tp = (mp_ptr) TMP_ALLOC (tn * BYTES_PER_MP_LIMB);

  rbitpos = 0;
  while (rbitpos + chunk_nbits <= nbits)
    {
      mp_ptr r2p = rp + rbitpos / GMP_NUMB_BITS;

      if (rbitpos % GMP_NUMB_BITS != 0)
	{
	  mp_limb_t savelimb, rcy;
	  /* Target of new chunk is not bit aligned.  Use temp space
	     and align things by shifting it up.  */
	  lc (tp, rstate);
	  savelimb = r2p[0];
	  rcy = mpn_lshift (r2p, tp, tn, rbitpos % GMP_NUMB_BITS);
	  r2p[0] |= savelimb;
	  /* bogus */
	  if ((chunk_nbits % GMP_NUMB_BITS + rbitpos % GMP_NUMB_BITS)
	      > GMP_NUMB_BITS)
	    r2p[tn] = rcy;
	}
      else
	{
	  /* Target of new chunk is bit aligned.  Let `lc' put bits
	     directly into our target variable.  */
	  lc (r2p, rstate);
	}
      rbitpos += chunk_nbits;
    }

  /* Handle last [0..chunk_nbits) bits.  */
  if (rbitpos != nbits)
    {
      mp_ptr r2p = rp + rbitpos / GMP_NUMB_BITS;
      int last_nbits = nbits - rbitpos;
      tn = BITS_TO_LIMBS (last_nbits);
      lc (tp, rstate);
      if (rbitpos % GMP_NUMB_BITS != 0)
	{
	  mp_limb_t savelimb, rcy;
	  /* Target of new chunk is not bit aligned.  Use temp space
	     and align things by shifting it up.  */
	  savelimb = r2p[0];
	  rcy = mpn_lshift (r2p, tp, tn, rbitpos % GMP_NUMB_BITS);
	  r2p[0] |= savelimb;
	  if (rbitpos + tn * GMP_NUMB_BITS - rbitpos % GMP_NUMB_BITS < nbits)
	    r2p[tn] = rcy;
	}
      else
	{
	  MPN_COPY (r2p, tp, tn);
	}
      /* Mask off top bits if needed.  */
      if (nbits % GMP_NUMB_BITS != 0)
	rp[nbits / GMP_NUMB_BITS]
	  &= ~(~CNST_LIMB (0) << nbits % GMP_NUMB_BITS);
    }

  TMP_FREE;
}
Beispiel #11
0
/* Exercise various 2^n values, with various exponents and positive and
   negative.  */
void
check_onebit (void)
{
  static const int bit_table[] = {
    0, 1, 2, 3,
    GMP_NUMB_BITS - 2, GMP_NUMB_BITS - 1,
    GMP_NUMB_BITS,
    GMP_NUMB_BITS + 1, GMP_NUMB_BITS + 2,
    2 * GMP_NUMB_BITS - 2, 2 * GMP_NUMB_BITS - 1,
    2 * GMP_NUMB_BITS,
    2 * GMP_NUMB_BITS + 1, 2 * GMP_NUMB_BITS + 2,
    3 * GMP_NUMB_BITS - 2, 3 * GMP_NUMB_BITS - 1,
    3 * GMP_NUMB_BITS,
    3 * GMP_NUMB_BITS + 1, 3 * GMP_NUMB_BITS + 2,
    4 * GMP_NUMB_BITS - 2, 4 * GMP_NUMB_BITS - 1,
    4 * GMP_NUMB_BITS,
    4 * GMP_NUMB_BITS + 1, 4 * GMP_NUMB_BITS + 2,
    5 * GMP_NUMB_BITS - 2, 5 * GMP_NUMB_BITS - 1,
    5 * GMP_NUMB_BITS,
    5 * GMP_NUMB_BITS + 1, 5 * GMP_NUMB_BITS + 2,
    6 * GMP_NUMB_BITS - 2, 6 * GMP_NUMB_BITS - 1,
    6 * GMP_NUMB_BITS,
    6 * GMP_NUMB_BITS + 1, 6 * GMP_NUMB_BITS + 2,
  };
  static const int exp_table[] = {
    0, -100, -10, -1, 1, 10, 100,
  };

  /* FIXME: It'd be better to base this on the float format. */
  int     limit = 511;

  int        bit_i, exp_i, i;
  double     got, want;
  mp_size_t  nsize, sign;
  long       bit, exp, want_bit;
  mp_limb_t  np[20];

  for (bit_i = 0; bit_i < numberof (bit_table); bit_i++)
    {
      bit = bit_table[bit_i];

      nsize = BITS_TO_LIMBS (bit+1);
      refmpn_zero (np, nsize);
      np[bit/GMP_NUMB_BITS] = CNST_LIMB(1) << (bit % GMP_NUMB_BITS);

      for (exp_i = 0; exp_i < numberof (exp_table); exp_i++)
        {
          exp = exp_table[exp_i];

          want_bit = bit + exp;
          if (want_bit > limit || want_bit < -limit)
            continue;

          want = 1.0;
          for (i = 0; i < want_bit; i++)
            want *= 2.0;
          for (i = 0; i > want_bit; i--)
            want *= 0.5;

          for (sign = 0; sign >= -1; sign--, want = -want)
            {
              got = mpn_get_d (np, nsize, sign, exp);
              if (got != want)
                {
                  printf    ("mpn_get_d wrong on 2^n\n");
                  printf    ("   bit      %ld\n", bit);
                  printf    ("   exp      %ld\n", exp);
                  printf    ("   want_bit %ld\n", want_bit);
                  printf    ("   sign     %ld\n", (long) sign);
                  mpn_trace ("   n        ", np, nsize);
                  printf    ("   nsize    %ld\n", (long) nsize);
                  d_trace   ("   want     ", want);
                  d_trace   ("   got      ", got);
                  abort();
                }
            }
        }
    }
}
Beispiel #12
0
void
check_rand (void)
{
  gmp_randstate_t rands;
  int            rep, i;
  unsigned long  mant_bits;
  long           exp, exp_min, exp_max;
  double         got, want, d;
  mp_size_t      nalloc, nsize, sign;
  mp_limb_t      nhigh_mask;
  mp_ptr         np;
  
  gmp_randinit_default(rands);
  
  mant_bits = tests_dbl_mant_bits ();
  if (mant_bits == 0)
    return;

  /* Allow for vax D format with exponent 127 to -128 only.
     FIXME: Do something to probe for a valid exponent range.  */
  exp_min = -100 - mant_bits;
  exp_max =  100 - mant_bits;

  /* space for mant_bits */
  nalloc = BITS_TO_LIMBS (mant_bits);
  np = refmpn_malloc_limbs (nalloc);
  nhigh_mask = MP_LIMB_T_MAX
    >> (GMP_NAIL_BITS + nalloc * GMP_NUMB_BITS - mant_bits);

  for (rep = 0; rep < 200; rep++)
    {
      /* random exp_min to exp_max, inclusive */
      exp = exp_min + (long) gmp_urandomm_ui (rands, exp_max - exp_min + 1);

      /* mant_bits worth of random at np */
      if (rep & 1)
        mpn_randomb (np, rands, nalloc);
      else
        mpn_rrandom (np, rands,nalloc);
      nsize = nalloc;
      np[nsize-1] &= nhigh_mask;
      MPN_NORMALIZE (np, nsize);
      if (nsize == 0)
        continue;

      sign = (mp_size_t) gmp_urandomb_ui (rands, 1L) - 1;

      /* want = {np,nsize}, converting one bit at a time */
      want = 0.0;
      for (i = 0, d = 1.0; i < mant_bits; i++, d *= 2.0)
        if (np[i/GMP_NUMB_BITS] & (CNST_LIMB(1) << (i%GMP_NUMB_BITS)))
          want += d;
      if (sign < 0)
        want = -want;

      /* want = want * 2^exp */
      for (i = 0; i < exp; i++)
        want *= 2.0;
      for (i = 0; i > exp; i--)
        want *= 0.5;

      got = mpn_get_d (np, nsize, sign, exp);

      if (got != want)
        {
          printf    ("mpn_get_d wrong on random data\n");
          printf    ("   sign     %ld\n", (long) sign);
          mpn_trace ("   n        ", np, nsize);
          printf    ("   nsize    %ld\n", (long) nsize);
          printf    ("   exp      %ld\n", exp);
          d_trace   ("   want     ", want);
          d_trace   ("   got      ", got);
          abort();
        }
    }

  free (np);
  gmp_randclear(rands);
}
Beispiel #13
0
size_t
mpz_inp_raw (mpz_ptr x, FILE *fp)
{
  unsigned char  csize_bytes[4];
  mp_size_t      csize, abs_xsize, i;
  size_t         abs_csize;
  char           *cp;
  mp_ptr         xp, sp, ep;
  mp_limb_t      slimb, elimb;

  if (fp == 0)
    fp = stdin;

  /* 4 bytes for size */
  if (fread (csize_bytes, sizeof (csize_bytes), 1, fp) != 1)
    return 0;

  csize =
    (  (mp_size_t) csize_bytes[0] << 24)
    + ((mp_size_t) csize_bytes[1] << 16)
    + ((mp_size_t) csize_bytes[2] << 8)
    + ((mp_size_t) csize_bytes[3]);

  /* Sign extend if necessary.
     Could write "csize -= ((csize & 0x80000000L) << 1)", but that tickles a
     bug in gcc 3.0 for powerpc64 on AIX.  */
  if (sizeof (csize) > 4 && csize & 0x80000000L)
    csize -= 0x80000000L << 1;

  abs_csize = ABS (csize);

  /* round up to a multiple of limbs */
  abs_xsize = BITS_TO_LIMBS (abs_csize*8);

  if (abs_xsize != 0)
    {
      xp = MPZ_NEWALLOC (x, abs_xsize);

      /* Get limb boundaries right in the read, for the benefit of the
	 non-nails case.  */
      xp[0] = 0;
      cp = (char *) (xp + abs_xsize) - abs_csize;
      if (fread (cp, abs_csize, 1, fp) != 1)
	return 0;

      if (GMP_NAIL_BITS == 0)
	{
	  /* Reverse limbs to least significant first, and byte swap.  If
	     abs_xsize is odd then on the last iteration elimb and slimb are
	     the same.  It doesn't seem extra code to handle that case
	     separately, to save an NTOH.  */
	  sp = xp;
	  ep = xp + abs_xsize-1;
	  for (i = 0; i < (abs_xsize+1)/2; i++)
	    {
	      NTOH_LIMB_FETCH (elimb, ep);
	      NTOH_LIMB_FETCH (slimb, sp);
	      *sp++ = elimb;
	      *ep-- = slimb;
	    }
	}
      else
	{
	  /* It ought to be possible to do the transformation in-place, but
	     for now it's easier to use an extra temporary area.  */
	  mp_limb_t  byte, limb;
	  int	     bits;
	  mp_size_t  tpos;
	  mp_ptr     tp;
	  TMP_DECL;

	  TMP_MARK;
	  tp = TMP_ALLOC_LIMBS (abs_xsize);
	  limb = 0;
	  bits = 0;
	  tpos = 0;
	  for (i = abs_csize-1; i >= 0; i--)
	    {
	      byte = (unsigned char) cp[i];
	      limb |= (byte << bits);
	      bits += 8;
	      if (bits >= GMP_NUMB_BITS)
		{
		  ASSERT (tpos < abs_xsize);
		  tp[tpos++] = limb & GMP_NUMB_MASK;
		  bits -= GMP_NUMB_BITS;
		  ASSERT (bits < 8);
		  limb = byte >> (8 - bits);
		}
	    }
	  if (bits != 0)
	    {
	      ASSERT (tpos < abs_xsize);
	      tp[tpos++] = limb;
	    }
	  ASSERT (tpos == abs_xsize);

	  MPN_COPY (xp, tp, abs_xsize);
	  TMP_FREE;
	}