Beispiel #1
0
void
cfb_encrypt(const void *ctx, nettle_cipher_func *f,
	    size_t block_size, uint8_t *iv,
	    size_t length, uint8_t *dst,
	    const uint8_t *src)
{
  uint8_t *p;
  TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);

  TMP_ALLOC(buffer, block_size);

  if (src != dst)
    {
      for (p = iv; length >= block_size; p = dst, dst += block_size, src += block_size, length -= block_size)
	{
	  f(ctx, block_size, dst, p);
	  memxor(dst, src, block_size);
	}
    }
  else
    {
      for (p = iv; length >= block_size; p = dst, dst += block_size, src += block_size, length -= block_size)
	{
	  f(ctx, block_size, buffer, p);
	  memxor(dst, buffer, block_size);
	}
    }

  if (p != iv)
    memcpy(iv, p, block_size);

  if (length)
    {
      f(ctx, block_size, buffer, iv);
      memxor3(dst, buffer, src, length);
      /* We do not care about updating IV here. This is the last call in
       * message sequence and one has to set IV afterwards anyway */
    }
}
Beispiel #2
0
int
pkcs1_decrypt (unsigned key_size,
	       const mpz_t m,
	       unsigned *length, uint8_t *message)
{
  TMP_DECL(em, uint8_t, NETTLE_MAX_BIGNUM_SIZE);
  uint8_t *terminator;
  unsigned padding;
  unsigned message_length;

  TMP_ALLOC(em, key_size);
  nettle_mpz_get_str_256(key_size, em, m);

  /* Check format */
  if (em[0] || em[1] != 2)
    return 0;

  terminator = memchr(em + 2, 0, key_size - 2);

  if (!terminator)
    return 0;
  
  padding = terminator - (em + 2);
  if (padding < 8)
    return 0;

  message_length = key_size - 3 - padding;

  if (*length < message_length)
    return 0;
  
  memcpy(message, terminator + 1, message_length);
  *length = message_length;

  return 1;
}
Beispiel #3
0
/* s <- 1 + r/1! + r^2/2! + ... + r^l/l! while MPFR_EXP(r^l/l!)+MPFR_EXPR(r)>-q
   using Brent/Kung method with O(sqrt(l)) multiplications.
   Return l.
   Uses m multiplications of full size and 2l/m of decreasing size,
   i.e. a total equivalent to about m+l/m full multiplications,
   i.e. 2*sqrt(l) for m=sqrt(l).
   Version using mpz. ss must have at least (sizer+1) limbs.
   The error is bounded by (l^2+4*l) ulps where l is the return value.
*/
static unsigned long
mpfr_exp2_aux2 (mpz_t s, mpfr_srcptr r, mp_prec_t q, mp_exp_t *exps)
{
  mp_exp_t expr, *expR, expt;
  mp_size_t sizer;
  mp_prec_t ql;
  unsigned long l, m, i;
  mpz_t t, *R, rr, tmp;
  TMP_DECL(marker);

  /* estimate value of l */
  MPFR_ASSERTD (MPFR_GET_EXP (r) < 0);
  l = q / (- MPFR_GET_EXP (r));
  m = __gmpfr_isqrt (l);
  /* we access R[2], thus we need m >= 2 */
  if (m < 2)
    m = 2;

  TMP_MARK(marker);
  R = (mpz_t*) TMP_ALLOC((m+1)*sizeof(mpz_t));          /* R[i] is r^i */
  expR = (mp_exp_t*) TMP_ALLOC((m+1)*sizeof(mp_exp_t)); /* exponent for R[i] */
  sizer = 1 + (MPFR_PREC(r)-1)/BITS_PER_MP_LIMB;
  mpz_init(tmp);
  MY_INIT_MPZ(rr, sizer+2);
  MY_INIT_MPZ(t, 2*sizer);            /* double size for products */
  mpz_set_ui(s, 0); 
  *exps = 1-q;                        /* 1 ulp = 2^(1-q) */
  for (i = 0 ; i <= m ; i++)
    MY_INIT_MPZ(R[i], sizer+2);
  expR[1] = mpfr_get_z_exp(R[1], r); /* exact operation: no error */
  expR[1] = mpz_normalize2(R[1], R[1], expR[1], 1-q); /* error <= 1 ulp */
  mpz_mul(t, R[1], R[1]); /* err(t) <= 2 ulps */
  mpz_div_2exp(R[2], t, q-1); /* err(R[2]) <= 3 ulps */
  expR[2] = 1-q;
  for (i = 3 ; i <= m ; i++)
    {
      mpz_mul(t, R[i-1], R[1]); /* err(t) <= 2*i-2 */
      mpz_div_2exp(R[i], t, q-1); /* err(R[i]) <= 2*i-1 ulps */
      expR[i] = 1-q;
    }
  mpz_set_ui (R[0], 1);
  mpz_mul_2exp (R[0], R[0], q-1);
  expR[0] = 1-q; /* R[0]=1 */
  mpz_set_ui (rr, 1);
  expr = 0; /* rr contains r^l/l! */
  /* by induction: err(rr) <= 2*l ulps */

  l = 0;
  ql = q; /* precision used for current giant step */
  do
    {
      /* all R[i] must have exponent 1-ql */
      if (l != 0)
        for (i = 0 ; i < m ; i++)
	  expR[i] = mpz_normalize2 (R[i], R[i], expR[i], 1-ql);
      /* the absolute error on R[i]*rr is still 2*i-1 ulps */
      expt = mpz_normalize2 (t, R[m-1], expR[m-1], 1-ql);
      /* err(t) <= 2*m-1 ulps */
      /* computes t = 1 + r/(l+1) + ... + r^(m-1)*l!/(l+m-1)!
         using Horner's scheme */
      for (i = m-1 ; i-- != 0 ; )
        {
          mpz_div_ui(t, t, l+i+1); /* err(t) += 1 ulp */
          mpz_add(t, t, R[i]);
        }
      /* now err(t) <= (3m-2) ulps */

      /* now multiplies t by r^l/l! and adds to s */
      mpz_mul(t, t, rr);
      expt += expr;
      expt = mpz_normalize2(t, t, expt, *exps);
      /* err(t) <= (3m-1) + err_rr(l) <= (3m-2) + 2*l */
      MPFR_ASSERTD (expt == *exps);
      mpz_add(s, s, t); /* no error here */

      /* updates rr, the multiplication of the factors l+i could be done
         using binary splitting too, but it is not sure it would save much */
      mpz_mul(t, rr, R[m]); /* err(t) <= err(rr) + 2m-1 */
      expr += expR[m];
      mpz_set_ui (tmp, 1);
      for (i = 1 ; i <= m ; i++)
	mpz_mul_ui (tmp, tmp, l + i);
      mpz_fdiv_q(t, t, tmp); /* err(t) <= err(rr) + 2m */
      expr += mpz_normalize(rr, t, ql); /* err_rr(l+1) <= err_rr(l) + 2m+1 */
      ql = q - *exps - mpz_sizeinbase(s, 2) + expr + mpz_sizeinbase(rr, 2);
      l += m;
    }
  while ((size_t) expr+mpz_sizeinbase(rr, 2) > (size_t)((int)-q));

  TMP_FREE(marker);
  mpz_clear(tmp);
  return l;
}
Beispiel #4
0
void
mpz_tdiv_r (mpz_ptr rem, mpz_srcptr num, mpz_srcptr den)
{
  mp_size_t ql;
  mp_size_t ns, ds, nl, dl;
  mp_ptr np, dp, qp, rp;
  TMP_DECL;

  ns = SIZ (num);
  ds = SIZ (den);
  nl = ABS (ns);
  dl = ABS (ds);
  ql = nl - dl + 1;

  if (dl == 0)
    DIVIDE_BY_ZERO;

  MPZ_REALLOC (rem, dl);

  if (ql <= 0)
    {
      if (num != rem)
	{
	  mp_ptr np, rp;
	  np = PTR (num);
	  rp = PTR (rem);
	  MPN_COPY (rp, np, nl);
	  SIZ (rem) = SIZ (num);
	}
      return;
    }

  TMP_MARK;
  qp = (mp_ptr) TMP_ALLOC (ql * BYTES_PER_MP_LIMB);
  rp = PTR (rem);
  np = PTR (num);
  dp = PTR (den);

  /* FIXME: We should think about how to handle the temporary allocation.
     Perhaps mpn_tdiv_qr should handle it, since it anyway often needs to
     allocate temp space.  */

  /* Copy denominator to temporary space if it overlaps with the remainder.  */
  if (dp == rp)
    {
      mp_ptr tp;
      tp = (mp_ptr) TMP_ALLOC (dl * BYTES_PER_MP_LIMB);
      MPN_COPY (tp, dp, dl);
      dp = tp;
    }
  /* Copy numerator to temporary space if it overlaps with the remainder.  */
  if (np == rp)
    {
      mp_ptr tp;
      tp = (mp_ptr) TMP_ALLOC (nl * BYTES_PER_MP_LIMB);
      MPN_COPY (tp, np, nl);
      np = tp;
    }

  mpn_tdiv_qr (qp, rp, 0L, np, nl, dp, dl);

  MPN_NORMALIZE (rp, dl);

  SIZ (rem) = ns >= 0 ? dl : -dl;
  TMP_FREE;
}
Beispiel #5
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 #6
0
void
mpz_gcdext (mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_srcptr a, mpz_srcptr b)
{
  mp_size_t asize, bsize, usize, vsize;
  mp_srcptr ap, bp;
  mp_ptr up, vp;
  mp_size_t gsize, ssize, tmp_ssize;
  mp_ptr gp, sp, tmp_gp, tmp_sp;
  mpz_srcptr u, v;
  mpz_ptr ss, tt;
  __mpz_struct stmp, gtmp;
  TMP_DECL;

  TMP_MARK;

  /* mpn_gcdext requires that U >= V.  Therefore, we often have to swap U and
     V.  This in turn leads to a lot of complications.  The computed cofactor
     will be the wrong one, so we have to fix that up at the end.  */

  asize = ABS (SIZ (a));
  bsize = ABS (SIZ (b));
  ap = PTR (a);
  bp = PTR (b);
  if (asize > bsize || (asize == bsize && mpn_cmp (ap, bp, asize) > 0))
    {
      usize = asize;
      vsize = bsize;
      up = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB);
      vp = (mp_ptr) TMP_ALLOC ((vsize + 1) * BYTES_PER_MP_LIMB);
      MPN_COPY (up, ap, usize);
      MPN_COPY (vp, bp, vsize);
      u = a;
      v = b;
      ss = s;
      tt = t;
    }
  else
    {
      usize = bsize;
      vsize = asize;
      up = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB);
      vp = (mp_ptr) TMP_ALLOC ((vsize + 1) * BYTES_PER_MP_LIMB);
      MPN_COPY (up, bp, usize);
      MPN_COPY (vp, ap, vsize);
      u = b;
      v = a;
      ss = t;
      tt = s;
    }

  tmp_gp = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB);
  tmp_sp = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB);

  if (vsize == 0)
    {
      tmp_sp[0] = 1;
      tmp_ssize = 1;
      MPN_COPY (tmp_gp, up, usize);
      gsize = usize;
    }
  else
    gsize = mpn_gcdext (tmp_gp, tmp_sp, &tmp_ssize, up, usize, vp, vsize);
  ssize = ABS (tmp_ssize);

  PTR (&gtmp) = tmp_gp;
  SIZ (&gtmp) = gsize;

  PTR (&stmp) = tmp_sp;
  SIZ (&stmp) = (tmp_ssize ^ SIZ (u)) >= 0 ? ssize : -ssize;

  if (tt != NULL)
    {
      if (SIZ (v) == 0)
	SIZ (tt) = 0;
      else
	{
	  mpz_t x;
	  MPZ_TMP_INIT (x, ssize + usize + 1);
	  mpz_mul (x, &stmp, u);
	  mpz_sub (x, &gtmp, x);
	  mpz_tdiv_q (tt, x, v);
	}
    }

  if (ss != NULL)
    {
      if (ALLOC (ss) < ssize)
	_mpz_realloc (ss, ssize);
      sp = PTR (ss);
      MPN_COPY (sp, tmp_sp, ssize);
      SIZ (ss) = SIZ (&stmp);
    }

  if (ALLOC (g) < gsize)
    _mpz_realloc (g, gsize);
  gp = PTR (g);
  MPN_COPY (gp, tmp_gp, gsize);
  SIZ (g) = gsize;

  TMP_FREE;
}
Beispiel #7
0
void
mout (const MINT *x)
{
  mp_ptr xp;
  mp_srcptr x_ptr;
  mp_size_t x_size;
  unsigned char *str;
  size_t str_size;
  int i;
  TMP_DECL (marker);

  x_size = x->_mp_size;
  if (x_size == 0)
    {
      fputc ('0', stdout);
      fputc ('\n', stdout);
      return;
    }
  if (x_size < 0)
    {
      fputc ('-', stdout);
      x_size = -x_size;
    }

  TMP_MARK (marker);
  x_ptr = x->_mp_d;
  MPN_SIZEINBASE (str_size, x_ptr, x_size, 10);
  str_size += 2;
  str = (unsigned char *) TMP_ALLOC (str_size);

  /* mpn_get_str clobbers its argument */
  xp = TMP_ALLOC_LIMBS (x_size);
  MPN_COPY (xp, x_ptr, x_size);

  str_size = mpn_get_str (str, 10, xp, x_size);

  /* mpn_get_str might make a leading zero, skip it.  */
  str_size -= (*str == 0);
  str += (*str == 0);
  ASSERT (*str != 0);

  /* Translate to printable chars.  */
  for (i = 0; i < str_size; i++)
    str[i] = "0123456789"[str[i]];
  str[str_size] = 0;

  str_size = strlen ((char *) str);
  if (str_size % 10 != 0)
    {
      fwrite (str, 1, str_size % 10, stdout);
      str += str_size % 10;
      str_size -= str_size % 10;
      if (str_size != 0)
	fputc (' ', stdout);
    }
  for (i = 0; i < str_size; i += 10)
    {
      fwrite (str, 1, 10, stdout);
      str += 10;
      if (i + 10 < str_size)
	fputc (' ', stdout);
    }
  fputc ('\n', stdout);
  TMP_FREE (marker);
}
Beispiel #8
0
int
sexp_iterator_assoc(struct sexp_iterator *iterator,
		    unsigned nkeys,
		    const uint8_t * const *keys,
		    struct sexp_iterator *values)
{
  TMP_DECL(found, int, NETTLE_MAX_SEXP_ASSOC);
  unsigned nfound;
  unsigned i;

  TMP_ALLOC(found, nkeys);
  for (i = 0; i<nkeys; i++)
    found[i] = 0;

  nfound = 0;
  
  for (;;)
    {
      switch (iterator->type)
	{
	case SEXP_LIST:

	  /* FIXME: Use sexp_iterator_check_type? Problem is to
	   * distinguish syntax errors from unkown keys (which we want
	   * to just ignore). */
	  if (!sexp_iterator_enter_list(iterator))
	    return 0;
	  
	  if (iterator->type == SEXP_ATOM
	      && !iterator->display)
	    {
	      /* Compare to the given keys */
	      for (i = 0; i<nkeys; i++)
		{
		  /* NOTE: The strlen could be put outside of the
		   * loop */
		  if (strlen(keys[i]) == iterator->atom_length
		      && !memcmp(keys[i], iterator->atom,
				 iterator->atom_length))
		    {
		      if (found[i])
			/* We don't allow duplicates */
			return 0;

		      /* Advance to point to value */
		      if (!sexp_iterator_next(iterator))
			return 0;

		      found[i] = 1;
		      nfound++;
		      
		      /* Record this position. */
		      values[i] = *iterator;
		      
		      break;
		    }
		}
	    }
	  if (!sexp_iterator_exit_list(iterator))
	    return 0;
	  break;
	case SEXP_ATOM:
	  /* Just ignore */
	  if (!sexp_iterator_next(iterator))
	    return 0;
	  break;
	  
	case SEXP_END:
	  return sexp_iterator_exit_list(iterator)
	    && (nfound == nkeys);

	default:
	  abort();
	}
    }
}
void time_div_divconquer(void)
{
   nn_t a, a2, b, q1, q2;
   len_t size;
   word_t inv;
   long count, i;
   clock_t t;

   TMP_INIT;

   for (size = 370; size < 1000; size = (long) ceil(size*1.1))
   {
      TMP_START;
      
      a = TMP_ALLOC(2*size - 1);
      a2 = TMP_ALLOC(2*size - 1);
      b = TMP_ALLOC(size);
      q1 = TMP_ALLOC(size);
      q2 = TMP_ALLOC(size);
               
      printf("size = %ld: ", size);

      t = clock();
      for (i = 0; i < 10; i++)
      {
         randoms_of_len(size, ANY, state, &b, NULL);
         b[size - 1] |= (1UL<<(WORD_BITS - 1));
         randoms_of_len(2*size - 1, ANY, state, &a, NULL);
         inv = precompute_inverse2(b[size - 1], b[size - 2]);
         
         for (count = 0; count < ITER/10; count++)
         {
            nn_copy(a2, a, 2*size - 1);
            nn_divrem_classical_preinv_c(q1, a2, 2*size - 1, b, size, inv, 0);
         }
      }
      t = clock() - t;

      printf("classical = %gs, ", ((double) t)/CLOCKS_PER_SEC/ITER);

      t = clock();
      for (i = 0; i < 10; i++)
      {
         randoms_of_len(size, ANY, state, &b, NULL);
         b[size - 1] |= (1UL<<(WORD_BITS - 1));
         randoms_of_len(2*size - 1, ANY, state, &a, NULL);
         inv = precompute_inverse2(b[size - 1], b[size - 2]);
         
         for (count = 0; count < ITER/10; count++)
         {
            nn_copy(a2, a, 2*size - 1);
            nn_div_divconquer_preinv_c(q2, a2, 2*size - 1, b, size, inv, 0);
         }
      }
      t = clock() - t;

      printf("divconquer = %gs\n", ((double) t)/CLOCKS_PER_SEC/ITER);
     
      TMP_END;
   }
}
Beispiel #10
0
size_t
mpz_out_str (FILE *stream, int base, mpz_srcptr x)
{
  mp_ptr xp;
  mp_size_t x_size = SIZ (x);
  unsigned char *str;
  size_t str_size;
  size_t i;
  size_t written;
  const char *num_to_text;
  TMP_DECL;

  if (stream == 0)
    stream = stdout;

  if (base >= 0)
    {
      num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz";
      if (base <= 1)
	base = 10;
      else if (base > 36)
	{
	  num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
	  if (base > 62)
	    return 0;
	}
    }
  else
    {
      base = -base;
      if (base <= 1)
	base = 10;
      else if (base > 36)
	return 0;
      num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    }

  written = 0;

  if (x_size < 0)
    {
      fputc ('-', stream);
      x_size = -x_size;
      written = 1;
    }

  TMP_MARK;

  DIGITS_IN_BASE_PER_LIMB (str_size, x_size, base);
  str_size += 3;
  str = (unsigned char *) TMP_ALLOC (str_size);

  xp = PTR (x);
  if (! POW2_P (base))
    {
      xp = TMP_ALLOC_LIMBS (x_size | 1);  /* |1 in case x_size==0 */
      MPN_COPY (xp, PTR (x), x_size);
    }

  str_size = mpn_get_str (str, base, xp, x_size);

  /* Convert result to printable chars.  */
  for (i = 0; i < str_size; i++)
    str[i] = num_to_text[str[i]];
  str[str_size] = 0;

  {
    size_t fwret;
    fwret = fwrite ((char *) str, 1, str_size, stream);
    written += fwret;
  }

  TMP_FREE;
  return ferror (stream) ? 0 : written;
}
Beispiel #11
0
/* mpz_tdiv_qr(quot,rem,dividend,divisor) -- Set QUOT to DIVIDEND/DIVISOR,
   and REM to DIVIDEND mod DIVISOR.

Copyright 1991, 1993, 1994, 2000, 2001, 2005 Free Software Foundation, Inc.

This file is part of the GNU MP Library.

The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at your
option) any later version.

The GNU MP Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
License for more details.

You should have received a copy of the GNU Lesser General Public License
along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */

#include "gmp.h"
#include "gmp-impl.h"
#include "longlong.h"
#ifdef BERKELEY_MP
#include "mp.h"
#endif

void
#ifndef BERKELEY_MP
mpz_tdiv_qr (mpz_ptr quot, mpz_ptr rem, mpz_srcptr num, mpz_srcptr den)
#else /* BERKELEY_MP */
mdiv (mpz_srcptr num, mpz_srcptr den, mpz_ptr quot, mpz_ptr rem)
#endif /* BERKELEY_MP */
{
  mp_size_t ql;
  mp_size_t ns, ds, nl, dl;
  mp_ptr np, dp, qp, rp;
  TMP_DECL;

  ns = SIZ (num);
  ds = SIZ (den);
  nl = ABS (ns);
  dl = ABS (ds);
  ql = nl - dl + 1;

  if (dl == 0)
    DIVIDE_BY_ZERO;

  MPZ_REALLOC (rem, dl);

  if (ql <= 0)
    {
      if (num != rem)
	{
	  mp_ptr np, rp;
	  np = PTR (num);
	  rp = PTR (rem);
	  MPN_COPY (rp, np, nl);
	  SIZ (rem) = SIZ (num);
	}
      /* This needs to follow the assignment to rem, in case the
	 numerator and quotient are the same.  */
      SIZ (quot) = 0;
      return;
    }

  MPZ_REALLOC (quot, ql);

  TMP_MARK;
  qp = PTR (quot);
  rp = PTR (rem);
  np = PTR (num);
  dp = PTR (den);

  /* FIXME: We should think about how to handle the temporary allocation.
     Perhaps mpn_tdiv_qr should handle it, since it anyway often needs to
     allocate temp space.  */

  /* Copy denominator to temporary space if it overlaps with the quotient
     or remainder.  */
  if (dp == rp || dp == qp)
    {
      mp_ptr tp;
      tp = (mp_ptr) TMP_ALLOC (dl * BYTES_PER_MP_LIMB);
      MPN_COPY (tp, dp, dl);
      dp = tp;
    }
  /* Copy numerator to temporary space if it overlaps with the quotient or
     remainder.  */
  if (np == rp || np == qp)
    {
      mp_ptr tp;
      tp = (mp_ptr) TMP_ALLOC (nl * BYTES_PER_MP_LIMB);
      MPN_COPY (tp, np, nl);
      np = tp;
    }

  mpn_tdiv_qr (qp, rp, 0L, np, nl, dp, dl);

  ql -=  qp[ql - 1] == 0;
  MPN_NORMALIZE (rp, dl);

  SIZ (quot) = (ns ^ ds) >= 0 ? ql : -ql;
  SIZ (rem) = ns >= 0 ? dl : -dl;
  TMP_FREE;
}
Beispiel #12
0
mp_limb_t
mpn_divrem (mp_ptr qp, mp_size_t qxn,
	    mp_ptr np, mp_size_t nn,
	    mp_srcptr dp, mp_size_t dn)
{
  ASSERT (qxn >= 0);
  ASSERT (nn >= dn);
  ASSERT (dn >= 1);
  ASSERT (dp[dn-1] & GMP_NUMB_HIGHBIT);
  ASSERT (! MPN_OVERLAP_P (np, nn, dp, dn));
  ASSERT (! MPN_OVERLAP_P (qp, nn-dn+qxn, np, nn) || qp==np+dn+qxn);
  ASSERT (! MPN_OVERLAP_P (qp, nn-dn+qxn, dp, dn));
  ASSERT_MPN (np, nn);
  ASSERT_MPN (dp, dn);

  if (dn == 1)
    {
      mp_limb_t ret;
      mp_ptr q2p;
      mp_size_t qn;
      TMP_DECL;

      TMP_MARK;
      q2p = (mp_ptr) TMP_ALLOC ((nn + qxn) * BYTES_PER_MP_LIMB);

      np[0] = mpn_divrem_1 (q2p, qxn, np, nn, dp[0]);
      qn = nn + qxn - 1;
      MPN_COPY (qp, q2p, qn);
      ret = q2p[qn];

      TMP_FREE;
      return ret;
    }
  else if (dn == 2)
    {
      return mpn_divrem_2 (qp, qxn, np, nn, dp);
    }
  else
    {
      mp_ptr rp, q2p;
      mp_limb_t qhl;
      mp_size_t qn;
      TMP_DECL;

      TMP_MARK;
      if (UNLIKELY (qxn != 0))
	{
	  mp_ptr n2p;
	  n2p = (mp_ptr) TMP_ALLOC ((nn + qxn) * BYTES_PER_MP_LIMB);
	  MPN_ZERO (n2p, qxn);
	  MPN_COPY (n2p + qxn, np, nn);
	  q2p = (mp_ptr) TMP_ALLOC ((nn - dn + qxn + 1) * BYTES_PER_MP_LIMB);
	  rp = (mp_ptr) TMP_ALLOC (dn * BYTES_PER_MP_LIMB);
	  mpn_tdiv_qr (q2p, rp, 0L, n2p, nn + qxn, dp, dn);
	  MPN_COPY (np, rp, dn);
	  qn = nn - dn + qxn;
	  MPN_COPY (qp, q2p, qn);
	  qhl = q2p[qn];
	}
      else
	{
	  q2p = (mp_ptr) TMP_ALLOC ((nn - dn + 1) * BYTES_PER_MP_LIMB);
	  rp = (mp_ptr) TMP_ALLOC (dn * BYTES_PER_MP_LIMB);
	  mpn_tdiv_qr (q2p, rp, 0L, np, nn, dp, dn);
	  MPN_COPY (np, rp, dn);	/* overwrite np area with remainder */
	  qn = nn - dn;
	  MPN_COPY (qp, q2p, qn);
	  qhl = q2p[qn];
	}
      TMP_FREE;
      return qhl;
    }
}
Beispiel #13
0
void
mpf_add (mpf_ptr r, mpf_srcptr u, mpf_srcptr v)
{
  mp_srcptr up, vp;
  mp_ptr rp, tp;
  mp_size_t usize, vsize, rsize;
  mp_size_t prec;
  mp_exp_t uexp;
  mp_size_t ediff;
  mp_limb_t cy;
  int negate;
  TMP_DECL (marker);

  usize = u->_mp_size;
  vsize = v->_mp_size;

  /* Handle special cases that don't work in generic code below.  */
  if (usize == 0)
    {
    set_r_v_maybe:
      if (r != v)
        mpf_set (r, v);
      return;
    }
  if (vsize == 0)
    {
      v = u;
      goto set_r_v_maybe;
    }

  /* If signs of U and V are different, perform subtraction.  */
  if ((usize ^ vsize) < 0)
    {
      __mpf_struct v_negated;
      v_negated._mp_size = -vsize;
      v_negated._mp_exp = v->_mp_exp;
      v_negated._mp_d = v->_mp_d;
      mpf_sub (r, u, &v_negated);
      return;
    }

  TMP_MARK (marker);

  /* Signs are now known to be the same.  */
  negate = usize < 0;

  /* Make U be the operand with the largest exponent.  */
  if (u->_mp_exp < v->_mp_exp)
    {
      mpf_srcptr t;
      t = u; u = v; v = t;
      usize = u->_mp_size;
      vsize = v->_mp_size;
    }

  usize = ABS (usize);
  vsize = ABS (vsize);
  up = u->_mp_d;
  vp = v->_mp_d;
  rp = r->_mp_d;
  prec = r->_mp_prec;
  uexp = u->_mp_exp;
  ediff = u->_mp_exp - v->_mp_exp;

  /* If U extends beyond PREC, ignore the part that does.  */
  if (usize > prec)
    {
      up += usize - prec;
      usize = prec;
    }

  /* If V extends beyond PREC, ignore the part that does.
     Note that this may make vsize negative.  */
  if (vsize + ediff > prec)
    {
      vp += vsize + ediff - prec;
      vsize = prec - ediff;
    }

#if 0
  /* Locate the least significant non-zero limb in (the needed parts
     of) U and V, to simplify the code below.  */
  while (up[0] == 0)
    up++, usize--;
  while (vp[0] == 0)
    vp++, vsize--;
#endif

  /* Allocate temp space for the result.  Allocate
     just vsize + ediff later???  */
  tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);

  if (ediff >= prec)
    {
      /* V completely cancelled.  */
      if (rp != up)
	MPN_COPY_INCR (rp, up, usize);
      rsize = usize;
    }
  else
    {
      /* uuuu     |  uuuu     |  uuuu     |  uuuu     |  uuuu    */
      /* vvvvvvv  |  vv       |    vvvvv  |    v      |       vv */

      if (usize > ediff)
	{
	  /* U and V partially overlaps.  */
	  if (vsize + ediff <= usize)
	    {
	      /* uuuu     */
	      /*   v      */
	      mp_size_t size;
	      size = usize - ediff - vsize;
	      MPN_COPY (tp, up, size);
	      cy = mpn_add (tp + size, up + size, usize - size, vp, vsize);
	      rsize = usize;
	    }
	  else
	    {
	      /* uuuu     */
	      /*   vvvvv  */
	      mp_size_t size;
	      size = vsize + ediff - usize;
	      MPN_COPY (tp, vp, size);
	      cy = mpn_add (tp + size, up, usize, vp + size, usize - ediff);
	      rsize = vsize + ediff;
	    }
	}
      else
	{
	  /* uuuu     */
	  /*      vv  */
	  mp_size_t size;
	  size = vsize + ediff - usize;
	  MPN_COPY (tp, vp, vsize);
	  MPN_ZERO (tp + vsize, ediff - usize);
	  MPN_COPY (tp + size, up, usize);
	  cy = 0;
	  rsize = size + usize;
	}

      MPN_COPY (rp, tp, rsize);
      rp[rsize] = cy;
      rsize += cy;
      uexp += cy;
    }

  r->_mp_size = negate ? -rsize : rsize;
  r->_mp_exp = uexp;
  TMP_FREE (marker);
}
Beispiel #14
0
void
mpz_sqrtrem (mpz_ptr root, mpz_ptr rem, mpz_srcptr op)
{
  mp_size_t op_size, root_size, rem_size;
  mp_ptr root_ptr, op_ptr;
  mp_ptr free_me = NULL;
  mp_size_t free_me_size;
  TMP_DECL;

  TMP_MARK;
  op_size = op->_mp_size;
  if (op_size <= 0)
    {
      if (op_size < 0)
        SQRT_OF_NEGATIVE;
      SIZ(root) = 0;
      SIZ(rem) = 0;
      return;
    }

  if (rem->_mp_alloc < op_size)
    _mpz_realloc (rem, op_size);

  /* The size of the root is accurate after this simple calculation.  */
  root_size = (op_size + 1) / 2;

  root_ptr = root->_mp_d;
  op_ptr = op->_mp_d;

  if (root->_mp_alloc < root_size)
    {
      if (root_ptr == op_ptr)
	{
	  free_me = root_ptr;
	  free_me_size = root->_mp_alloc;
	}
      else
	(*__gmp_free_func) (root_ptr, root->_mp_alloc * BYTES_PER_MP_LIMB);

      root->_mp_alloc = root_size;
      root_ptr = (mp_ptr) (*__gmp_allocate_func) (root_size * BYTES_PER_MP_LIMB);
      root->_mp_d = root_ptr;
    }
  else
    {
      /* Make OP not overlap with ROOT.  */
      if (root_ptr == op_ptr)
	{
	  /* ROOT and OP are identical.  Allocate temporary space for OP.  */
	  op_ptr = (mp_ptr) TMP_ALLOC (op_size * BYTES_PER_MP_LIMB);
	  /* Copy to the temporary space.  Hack: Avoid temporary variable
	     by using ROOT_PTR.  */
	  MPN_COPY (op_ptr, root_ptr, op_size);
	}
    }

  rem_size = mpn_sqrtrem (root_ptr, rem->_mp_d, op_ptr, op_size);

  root->_mp_size = root_size;

  /* Write remainder size last, to enable us to define this function to
     give only the square root remainder, if the user calls if with
     ROOT == REM.  */
  rem->_mp_size = rem_size;

  if (free_me != NULL)
    (*__gmp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB);
  TMP_FREE;
}
Beispiel #15
0
void
nmod_poly_divrem_basecase(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A,
                          const nmod_poly_t B)
{
    const slong lenA = A->length, lenB = B->length;
    mp_ptr Q_coeffs, R_coeffs, W;
    nmod_poly_t t1, t2;
    TMP_INIT;

    if (lenB == 0)
    {
        flint_printf("Exception (nmod_poly_divrem). Division by zero.\n");
        abort();
    }

    if (lenA < lenB)
    {
        nmod_poly_set(R, A);
        nmod_poly_zero(Q);
        return;
    }

    if (Q == A || Q == B)
    {
        nmod_poly_init2_preinv(t1, B->mod.n, B->mod.ninv, lenA - lenB + 1);
        Q_coeffs = t1->coeffs;
    }
    else
    {
        nmod_poly_fit_length(Q, lenA - lenB + 1);
        Q_coeffs = Q->coeffs;
    }

    if (R == A || R == B)
    {
        nmod_poly_init2_preinv(t2, B->mod.n, B->mod.ninv, lenB - 1);
        R_coeffs = t2->coeffs;
    }
    else
    {
        nmod_poly_fit_length(R, lenB - 1);
        R_coeffs = R->coeffs;
    }

    TMP_START;
    W = TMP_ALLOC(NMOD_DIVREM_BC_ITCH(lenA, lenB, A->mod)*sizeof(mp_limb_t));
    
    _nmod_poly_divrem_basecase(Q_coeffs, R_coeffs, W, A->coeffs, lenA,
                               B->coeffs, lenB, B->mod);

    if (Q == A || Q == B)
    {
        nmod_poly_swap(Q, t1);
        nmod_poly_clear(t1);
    }
    if (R == A || R == B)
    {
        nmod_poly_swap(R, t2);
        nmod_poly_clear(t2);
    }
    Q->length = lenA - lenB + 1;
    R->length = lenB - 1;

    TMP_END;
    _nmod_poly_normalise(R);
}
Beispiel #16
0
void
cbc_decrypt(void *ctx, nettle_crypt_func *f,
	    unsigned block_size, uint8_t *iv,
	    unsigned length, uint8_t *dst,
	    const uint8_t *src)
{
  assert(!(length % block_size));

  if (!length)
    return;

  if (src != dst)
    {
      /* Decrypt in ECB mode */
      f(ctx, length, dst, src);

      /* XOR the cryptotext, shifted one block */
      memxor(dst, iv, block_size);
      memxor(dst + block_size, src, length - block_size);
      memcpy(iv, src + length - block_size, block_size);
    }

  else
    {
      /* For in-place CBC, we decrypt into a temporary buffer of size
       * at most CBC_BUFFER_LIMIT, and process that amount of data at
       * a time. */
      
      /* NOTE: We assume that block_size <= CBC_BUFFER_LIMIT, and we
	 depend on memxor3 working from the end of the area, allowing
	 certain overlapping operands. */ 

      TMP_DECL(buffer, uint8_t, CBC_BUFFER_LIMIT);
      TMP_DECL(initial_iv, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);

      unsigned buffer_size;

      if (length <= CBC_BUFFER_LIMIT)
	buffer_size = length;
      else
	buffer_size
	  = CBC_BUFFER_LIMIT - (CBC_BUFFER_LIMIT % block_size);

      TMP_ALLOC(buffer, buffer_size);
      TMP_ALLOC(initial_iv, block_size);

      for ( ; length > buffer_size;
	    length -= buffer_size, src += buffer_size, dst += buffer_size)
	{
	  f(ctx, buffer_size, buffer, src);
	  memcpy(initial_iv, iv, block_size);
	  memcpy(iv, src + buffer_size - block_size, block_size);
	  memxor3(dst + block_size, buffer + block_size, src,
		  buffer_size - block_size);
	  memxor3(dst, buffer, initial_iv, block_size);
	}

      f(ctx, length, buffer, src);
      memcpy(initial_iv, iv, block_size);
      /* Copies last block */
      memcpy(iv, src + length - block_size, block_size);
      /* Writes all but first block, reads all but last block. */
      memxor3(dst + block_size, buffer + block_size, src,
	      length - block_size);
      /* Writes first block. */
      memxor3(dst, buffer, initial_iv, block_size);
    }
}
/* NOTE: The mpz_nextprime in current GMP is unoptimized. */
void
nettle_next_prime(mpz_t p, mpz_t n, unsigned count, unsigned prime_limit,
		  void *progress_ctx, nettle_progress_func progress)
{
  mpz_t tmp;
  TMP_DECL(moduli, unsigned, NUMBER_OF_PRIMES);
  
  unsigned difference;

  if (prime_limit > NUMBER_OF_PRIMES)
    prime_limit = NUMBER_OF_PRIMES;
  
  /* First handle tiny numbers */
  if (mpz_cmp_ui(n, 2) <= 0)
    {
      mpz_set_ui(p, 2);
      return;
    }
  mpz_set(p, n);
  mpz_setbit(p, 0);

  if (mpz_cmp_ui(p, 8) < 0)
    return;

  mpz_init(tmp);

  if (mpz_cmp_ui(p, primes[prime_limit-1]) <= 0)
    /* Use only 3, 5 and 7 */
    /* FIXME: Could do binary search in the table. */
    prime_limit = 3;
  
  /* Compute residues modulo small odd primes */
  /* FIXME: Could be sped up by collecting limb-sized products of the
     primes, to reduce the calls to mpz_fdiv_ui */

  /* FIXME: Could also handle the first few primes separately; compute
     the residue mod 15015 = 3 * 7 * 11 * 13, and tabulate the steps
     between the 5760 odd numbers in this interval that have no factor
     in common with 15015.
   */
  TMP_ALLOC(moduli, prime_limit);
  {
    unsigned i;
    for (i = 0; i < prime_limit; i++)
      moduli[i] = mpz_fdiv_ui(p, primes[i]);
  }
  
  for (difference = 0; ; difference += 2)
    {
      int composite = 0;
      unsigned i;
      
      if (difference >= UINT_MAX - 10)
	{ /* Should not happen, at least not very often... */
	  mpz_add_ui(p, p, difference);
	  difference = 0;
	}

      /* First check residues */
      for (i = 0; i < prime_limit; i++)
	{
	  if (moduli[i] == 0)
	    composite = 1;

	  moduli[i] += 2;
	  if (UNLIKELY(moduli[i] >= primes[i]))
	    moduli[i] -= primes[i];
	}
      if (composite)
	continue;
      
      mpz_add_ui(p, p, difference);
      difference = 0;

      if (progress)
	progress(progress_ctx, '.');

      /* Miller-Rabin test */
      if (PRIME_P(p, count))
	break;

#if 0
      if (progress)
	progress(progress_ctx, '*');
#endif
    }
  mpz_clear(tmp);
}
Beispiel #18
0
void time_mulmid_kara(void)
{
   nn_t a, b, r1, r2;
   len_t size;
   long count;
   clock_t t;

   TMP_INIT;

   for (size = 2; size < 4000; size = (long) ceil(size*1.1))
   {
      TMP_START;
      
      a = TMP_ALLOC(2*size);
      b = TMP_ALLOC(size);
      r1 = TMP_ALLOC(size + 3);
      r2 = TMP_ALLOC(3*size);
      
      randoms_of_len(2*size, ANY, state, &a, NULL);
      randoms_of_len(size, ANY, state, &b, NULL);
      
      printf("size = %ld: ", size);

      if (size < 100)
      {
         t = clock();
         for (count = 0; count < ITER; count++)
            nn_mulmid_classical(r1 + size + 1, r1, a, 2*size, b, size);
         t = clock() - t;

         printf("mulmid_classical = %gs, ", ((double) t)/CLOCKS_PER_SEC/ITER);
      }

      t = clock();
      for (count = 0; count < ITER; count++)
         nn_mulmid_kara(r1 + size + 1, r2, a, 2*size, b, size);
      t = clock() - t;

      printf("mulmid_kara = %gs\n", ((double) t)/CLOCKS_PER_SEC/ITER);
     
      printf("size = %ld: ", size);

      if (size < 100)
      {
         t = clock();
         for (count = 0; count < ITER; count++)
            nn_mul_classical(r2, a, 2*size, b, size);
         t = clock() - t;
      
         printf("mul_classical = %gs, ", ((double) t)/CLOCKS_PER_SEC/ITER);
      }

      t = clock();
      for (count = 0; count < ITER; count++)
         nn_mul(r2, a, 2*size, b, size);
      t = clock() - t;

      printf("mul = %gs, ", ((double) t)/CLOCKS_PER_SEC/ITER);
     
      t = clock();
      for (count = 0; count < ITER; count++)
         nn_mullow(r2 + 2*size, r2, a, 2*size, b, size);
      t = clock() - t;

      printf("mullow = %gs\n", ((double) t)/CLOCKS_PER_SEC/ITER);
     
      TMP_END;
   }
}
Beispiel #19
0
void
mpf_sub (mpf_ptr r, mpf_srcptr u, mpf_srcptr v)
{
  mp_srcptr up, vp;
  mp_ptr rp, tp;
  mp_size_t usize, vsize, rsize;
  mp_size_t prec;
  mp_exp_t exp;
  mp_size_t ediff;
  int negate;
  TMP_DECL;

  usize = u->_mp_size;
  vsize = v->_mp_size;

  /* Handle special cases that don't work in generic code below.  */
  if (usize == 0)
    {
      mpf_neg (r, v);
      return;
    }
  if (vsize == 0)
    {
      if (r != u)
        mpf_set (r, u);
      return;
    }

  /* If signs of U and V are different, perform addition.  */
  if ((usize ^ vsize) < 0)
    {
      __mpf_struct v_negated;
      v_negated._mp_size = -vsize;
      v_negated._mp_exp = v->_mp_exp;
      v_negated._mp_d = v->_mp_d;
      mpf_add (r, u, &v_negated);
      return;
    }

  TMP_MARK;

  /* Signs are now known to be the same.  */
  negate = usize < 0;

  /* Make U be the operand with the largest exponent.  */
  if (u->_mp_exp < v->_mp_exp)
    {
      mpf_srcptr t;
      t = u; u = v; v = t;
      negate ^= 1;
      usize = u->_mp_size;
      vsize = v->_mp_size;
    }

  usize = ABS (usize);
  vsize = ABS (vsize);
  up = u->_mp_d;
  vp = v->_mp_d;
  rp = r->_mp_d;
  prec = r->_mp_prec + 1;
  exp = u->_mp_exp;
  ediff = u->_mp_exp - v->_mp_exp;

  /* If ediff is 0 or 1, we might have a situation where the operands are
     extremely close.  We need to scan the operands from the most significant
     end ignore the initial parts that are equal.  */
  if (ediff <= 1)
    {
      if (ediff == 0)
	{
	  /* Skip leading limbs in U and V that are equal.  */
	  if (up[usize - 1] == vp[vsize - 1])
	    {
	      /* This loop normally exits immediately.  Optimize for that.  */
	      do
		{
		  usize--;
		  vsize--;
		  exp--;

		  if (usize == 0)
		    {
                      /* u cancels high limbs of v, result is rest of v */
		      negate ^= 1;
                    cancellation:
                      /* strip high zeros before truncating to prec */
                      while (vsize != 0 && vp[vsize - 1] == 0)
                        {
                          vsize--;
                          exp--;
                        }
		      if (vsize > prec)
			{
			  vp += vsize - prec;
			  vsize = prec;
			}
                      MPN_COPY_INCR (rp, vp, vsize);
                      rsize = vsize;
                      goto done;
		    }
		  if (vsize == 0)
		    {
                      vp = up;
                      vsize = usize;
                      goto cancellation;
		    }
		}
	      while (up[usize - 1] == vp[vsize - 1]);
	    }

	  if (up[usize - 1] < vp[vsize - 1])
	    {
	      /* For simplicity, swap U and V.  Note that since the loop above
		 wouldn't have exited unless up[usize - 1] and vp[vsize - 1]
		 were non-equal, this if-statement catches all cases where U
		 is smaller than V.  */
	      MPN_SRCPTR_SWAP (up,usize, vp,vsize);
	      negate ^= 1;
	      /* negating ediff not necessary since it is 0.  */
	    }

	  /* Check for
	     x+1 00000000 ...
	      x  ffffffff ... */
	  if (up[usize - 1] != vp[vsize - 1] + 1)
	    goto general_case;
	  usize--;
	  vsize--;
	  exp--;
	}
      else /* ediff == 1 */
	{
	  /* Check for
	     1 00000000 ...
	     0 ffffffff ... */

	  if (up[usize - 1] != 1 || vp[vsize - 1] != GMP_NUMB_MAX
	      || (usize >= 2 && up[usize - 2] != 0))
	    goto general_case;

	  usize--;
	  exp--;
	}

      /* Skip sequences of 00000000/ffffffff */
      while (vsize != 0 && usize != 0 && up[usize - 1] == 0
	     && vp[vsize - 1] == GMP_NUMB_MAX)
	{
	  usize--;
	  vsize--;
	  exp--;
	}

      if (usize == 0)
	{
	  while (vsize != 0 && vp[vsize - 1] == GMP_NUMB_MAX)
	    {
	      vsize--;
	      exp--;
	    }
	}

      if (usize > prec - 1)
	{
	  up += usize - (prec - 1);
	  usize = prec - 1;
	}
      if (vsize > prec - 1)
	{
	  vp += vsize - (prec - 1);
	  vsize = prec - 1;
	}

      tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);
      {
	mp_limb_t cy_limb;
	if (vsize == 0)
	  {
	    mp_size_t size, i;
	    size = usize;
	    for (i = 0; i < size; i++)
	      tp[i] = up[i];
	    tp[size] = 1;
	    rsize = size + 1;
	    exp++;
	    goto normalize;
	  }
	if (usize == 0)
	  {
	    mp_size_t size, i;
	    size = vsize;
	    for (i = 0; i < size; i++)
	      tp[i] = ~vp[i] & GMP_NUMB_MASK;
	    cy_limb = 1 - mpn_add_1 (tp, tp, vsize, (mp_limb_t) 1);
	    rsize = vsize;
	    if (cy_limb == 0)
	      {
		tp[rsize] = 1;
		rsize++;
		exp++;
	      }
	    goto normalize;
	  }
	if (usize >= vsize)
	  {
	    /* uuuu     */
	    /* vv       */
	    mp_size_t size;
	    size = usize - vsize;
	    MPN_COPY (tp, up, size);
	    cy_limb = mpn_sub_n (tp + size, up + size, vp, vsize);
	    rsize = usize;
	  }
	else /* (usize < vsize) */
	  {
	    /* uuuu     */
	    /* vvvvvvv  */
	    mp_size_t size, i;
	    size = vsize - usize;
	    for (i = 0; i < size; i++)
	      tp[i] = ~vp[i] & GMP_NUMB_MASK;
	    cy_limb = mpn_sub_n (tp + size, up, vp + size, usize);
	    cy_limb+= mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
	    cy_limb-= mpn_add_1 (tp, tp, vsize, (mp_limb_t) 1);
	    rsize = vsize;
	  }
	if (cy_limb == 0)
	  {
	    tp[rsize] = 1;
	    rsize++;
	    exp++;
	  }
	goto normalize;
      }
    }

general_case:
  /* If U extends beyond PREC, ignore the part that does.  */
  if (usize > prec)
    {
      up += usize - prec;
      usize = prec;
    }

  /* If V extends beyond PREC, ignore the part that does.
     Note that this may make vsize negative.  */
  if (vsize + ediff > prec)
    {
      vp += vsize + ediff - prec;
      vsize = prec - ediff;
    }

  /* Allocate temp space for the result.  Allocate
     just vsize + ediff later???  */
  tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);

  if (ediff >= prec)
    {
      /* V completely cancelled.  */
      if (tp != up)
	MPN_COPY (rp, up, usize);
      rsize = usize;
    }
  else
    {
      /* Locate the least significant non-zero limb in (the needed
	 parts of) U and V, to simplify the code below.  */
      for (;;)
	{
	  if (vsize == 0)
	    {
	      MPN_COPY (rp, up, usize);
	      rsize = usize;
	      goto done;
	    }
	  if (vp[0] != 0)
	    break;
	  vp++, vsize--;
	}
      for (;;)
	{
	  if (usize == 0)
	    {
	      MPN_COPY (rp, vp, vsize);
	      rsize = vsize;
	      negate ^= 1;
	      goto done;
	    }
	  if (up[0] != 0)
	    break;
	  up++, usize--;
	}

      /* uuuu     |  uuuu     |  uuuu     |  uuuu     |  uuuu    */
      /* vvvvvvv  |  vv       |    vvvvv  |    v      |       vv */

      if (usize > ediff)
	{
	  /* U and V partially overlaps.  */
	  if (ediff == 0)
	    {
	      /* Have to compare the leading limbs of u and v
		 to determine whether to compute u - v or v - u.  */
	      if (usize >= vsize)
		{
		  /* uuuu     */
		  /* vv       */
		  mp_size_t size;
		  size = usize - vsize;
		  MPN_COPY (tp, up, size);
		  mpn_sub_n (tp + size, up + size, vp, vsize);
		  rsize = usize;
		}
	      else /* (usize < vsize) */
		{
		  /* uuuu     */
		  /* vvvvvvv  */
		  mp_size_t size, i;
		  size = vsize - usize;
		  tp[0] = -vp[0] & GMP_NUMB_MASK;
		  for (i = 1; i < size; i++)
		    tp[i] = ~vp[i] & GMP_NUMB_MASK;
		  mpn_sub_n (tp + size, up, vp + size, usize);
		  mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
		  rsize = vsize;
		}
	    }
	  else
	    {
	      if (vsize + ediff <= usize)
		{
		  /* uuuu     */
		  /*   v      */
		  mp_size_t size;
		  size = usize - ediff - vsize;
		  MPN_COPY (tp, up, size);
		  mpn_sub (tp + size, up + size, usize - size, vp, vsize);
		  rsize = usize;
		}
	      else
		{
		  /* uuuu     */
		  /*   vvvvv  */
		  mp_size_t size, i;
		  size = vsize + ediff - usize;
		  tp[0] = -vp[0] & GMP_NUMB_MASK;
		  for (i = 1; i < size; i++)
		    tp[i] = ~vp[i] & GMP_NUMB_MASK;
		  mpn_sub (tp + size, up, usize, vp + size, usize - ediff);
		  mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
		  rsize = vsize + ediff;
		}
	    }
	}
      else
	{
	  /* uuuu     */
	  /*      vv  */
	  mp_size_t size, i;
	  size = vsize + ediff - usize;
	  tp[0] = -vp[0] & GMP_NUMB_MASK;
	  for (i = 1; i < vsize; i++)
	    tp[i] = ~vp[i] & GMP_NUMB_MASK;
	  for (i = vsize; i < size; i++)
	    tp[i] = GMP_NUMB_MAX;
	  mpn_sub_1 (tp + size, up, usize, (mp_limb_t) 1);
	  rsize = size + usize;
	}

    normalize:
      /* Full normalize.  Optimize later.  */
      while (rsize != 0 && tp[rsize - 1] == 0)
	{
	  rsize--;
	  exp--;
	}
      MPN_COPY (rp, tp, rsize);
    }

 done:
  r->_mp_size = negate ? -rsize : rsize;
  if (rsize == 0)
    exp = 0;
  r->_mp_exp = exp;
  TMP_FREE;
}
Beispiel #20
0
void
_gmp_rand (mp_ptr rp, gmp_randstate_t rstate, unsigned long int nbits)
{
  mp_size_t rn;			/* Size of R.  */

  rn = (nbits + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;

  switch (rstate->_mp_alg)
    {
    case GMP_RAND_ALG_LC:
      {
	unsigned long int rbitpos;
	int chunk_nbits;
	mp_ptr tp;
	mp_size_t tn;
	TMP_DECL (lcmark);

	TMP_MARK (lcmark);

	chunk_nbits = rstate->_mp_algdata._mp_lc->_mp_m2exp / 2;
	tn = (chunk_nbits + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;

	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 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 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 = (last_nbits + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;
	    lc (tp, rstate);
	    if (rbitpos % GMP_NUMB_BITS != 0)
	      {
		mp_limb_t savelimb, rcy;
		/* Target of 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]
		&= ~ ((~(mp_limb_t) 0) << nbits % GMP_NUMB_BITS);
	  }

	TMP_FREE (lcmark);
	break;
      }

    default:
      ASSERT (0);
      break;
    }
}
Beispiel #21
0
size_t
mpf_out_str (FILE *stream, int base, size_t n_digits, mpf_srcptr op)
{
    char *str;
    mp_exp_t exp;
    size_t written;
    TMP_DECL;

    TMP_MARK;

    if (base == 0)
        base = 10;
    if (n_digits == 0)
        MPF_SIGNIFICANT_DIGITS (n_digits, base, op->_mp_prec);

    if (stream == 0)
        stream = stdout;

    /* Consider these changes:
       * Don't allocate memory here for huge n_digits; pass NULL to mpf_get_str.
       * Make mpf_get_str allocate extra space when passed NULL, to avoid
         allocating two huge string buffers.
       * Implement more/other allocation reductions tricks.  */

    str = (char *) TMP_ALLOC (n_digits + 2); /* extra for minus sign and \0 */

    mpf_get_str (str, &exp, base, n_digits, op);
    n_digits = strlen (str);

    written = 0;

    /* Write sign */
    if (str[0] == '-')
    {
        str++;
        fputc ('-', stream);
        written = 1;
        n_digits--;
    }

    {
        const char  *point = GMP_DECIMAL_POINT;
        size_t      pointlen = strlen (point);
        putc ('0', stream);
        fwrite (point, 1, pointlen, stream);
        written += pointlen + 1;
    }

    /* Write mantissa */
    {
        size_t fwret;
        fwret = fwrite (str, 1, n_digits, stream);
        written += fwret;
    }

    /* Write exponent */
    {
        int fpret;
        fpret = fprintf (stream, (base <= 10 ? "e%ld" : "@%ld"), exp);
        written += fpret;
    }

    TMP_FREE;
    return ferror (stream) ? 0 : written;
}
Beispiel #22
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;
  mp_limb_t c;
  TMP_DECL (mark);

  m2exp = rstate->_mp_algdata._mp_lc->_mp_m2exp;

  /* The code below assumes the mod part is a power of two.  Make sure
     that is the case.  */
  ASSERT_ALWAYS (m2exp != 0);

  c = (mp_limb_t) rstate->_mp_algdata._mp_lc->_mp_c;

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

  if (seedn == 0)
    {
      /* Seed is 0.  Result is C % M.  Assume table is sensibly stored,
       with C smaller than M*/
      *rp = c;

      *seedp = c;
      SIZ (rstate->_mp_seed) = 1;
      return m2exp;
    }

  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;
  tp = (mp_ptr) TMP_ALLOC (ta * BYTES_PER_MP_LIMB);

  /* t = a * seed */
  if (seedn >= an)
    mpn_mul (tp, seedp, seedn, ap, an);
  else
    mpn_mul (tp, ap, an, seedp, seedn);
  tn = an + seedn;

  /* 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;

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

  {
    /* Discard the lower m2exp/2 bits of result.  */
    unsigned long int bits = m2exp / 2;
    mp_size_t 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 (mark);

  /* Return number of valid bits in the result.  */
  return (m2exp + 1) / 2;
}
Beispiel #23
0
int
mpfr_div (mpfr_ptr q, mpfr_srcptr u, mpfr_srcptr v, mp_rnd_t rnd_mode)
{
  mp_srcptr up, vp, bp;
  mp_size_t usize, vsize;

  mp_ptr ap, qp, rp;
  mp_size_t asize, bsize, qsize, rsize;
  mp_exp_t qexp;

  mp_size_t err, k;
  mp_limb_t tonearest;
  int inex, sh, can_round = 0, sign_quotient;
  unsigned int cc = 0, rw;

  TMP_DECL (marker);


  /**************************************************************************
   *                                                                        *
   *              This part of the code deals with special cases            *
   *                                                                        *
   **************************************************************************/

  if (MPFR_ARE_SINGULAR(u,v))
    {
      if (MPFR_IS_NAN(u) || MPFR_IS_NAN(v))
	{
	  MPFR_SET_NAN(q);
	  MPFR_RET_NAN;
	}
      sign_quotient = MPFR_MULT_SIGN( MPFR_SIGN(u) , MPFR_SIGN(v) );
      MPFR_SET_SIGN(q, sign_quotient);
      if (MPFR_IS_INF(u))
	{
	  if (MPFR_IS_INF(v))
	    {
	      MPFR_SET_NAN(q);
	      MPFR_RET_NAN;
	    }
	  else
	    {
	      MPFR_SET_INF(q);
	      MPFR_RET(0);
	    }
	}
      else if (MPFR_IS_INF(v))
	{
	  MPFR_SET_ZERO(q);
	  MPFR_RET(0);
	}
      else if (MPFR_IS_ZERO(v))
	{
	  if (MPFR_IS_ZERO(u))
	    {
	      MPFR_SET_NAN(q);
	      MPFR_RET_NAN;
	    }
	  else
	    {
	      MPFR_SET_INF(q);
	      MPFR_RET(0);
	    }
	}
      else
	{
	  MPFR_ASSERTD(MPFR_IS_ZERO(u));
	  MPFR_SET_ZERO(q);
	  MPFR_RET(0);
	}
    }
  MPFR_CLEAR_FLAGS(q);

  /**************************************************************************
   *                                                                        *
   *              End of the part concerning special values.                *
   *                                                                        *
   **************************************************************************/

  sign_quotient = MPFR_MULT_SIGN( MPFR_SIGN(u) , MPFR_SIGN(v) );
  up = MPFR_MANT(u);
  vp = MPFR_MANT(v);
  MPFR_SET_SIGN(q, sign_quotient);

  TMP_MARK (marker);
  usize = MPFR_LIMB_SIZE(u);
  vsize = MPFR_LIMB_SIZE(v);

  /**************************************************************************
   *                                                                        *
   *   First try to use only part of u, v. If this is not sufficient,       *
   *   use the full u and v, to avoid long computations eg. in the case     *
   *   u = v.                                                               *
   *                                                                        *
   **************************************************************************/

  /* The dividend is a, length asize. The divisor is b, length bsize. */

  qsize = (MPFR_PREC(q) + 3) / BITS_PER_MP_LIMB + 1;

  /* in case PREC(q)=PREC(v), then vsize=qsize with probability 1-4/b
     where b is the number of bits per limb */
  if (MPFR_LIKELY(vsize <= qsize))
    {
      bsize = vsize;
      bp = vp;
    }
  else /* qsize < vsize: take only the qsize high limbs of the divisor */
    {
      bsize = qsize;
      bp = (mp_srcptr) vp + (vsize - qsize);
    }

  /* we have {bp, bsize} * (1 + errb) = (true divisor)
     with 0 <= errb < 2^(-qsize*BITS_PER_MP_LIMB+1) */

  asize = bsize + qsize;
  ap = (mp_ptr) TMP_ALLOC (asize * BYTES_PER_MP_LIMB);
  /* if all arguments have same precision, then asize will be about 2*usize */
  if (MPFR_LIKELY(asize > usize))
    {
      /* copy u into the high limbs of {ap, asize}, and pad with zeroes */
      /* FIXME: could we copy only the qsize high limbs of the dividend? */
      MPN_COPY (ap + asize - usize, up, usize);
      MPN_ZERO (ap, asize - usize);
    }
  else /* truncate the high asize limbs of u into {ap, asize} */
    MPN_COPY (ap, up + usize - asize, asize);

  /* we have {ap, asize} = (true dividend) * (1 - erra)
     with 0 <= erra < 2^(-asize*BITS_PER_MP_LIMB).
     This {ap, asize} / {bp, bsize} =
     (true dividend) / (true divisor) * (1 - erra) (1 + errb) */

  /* Allocate limbs for quotient and remainder. */
  qp = (mp_ptr) TMP_ALLOC ((qsize + 1) * BYTES_PER_MP_LIMB);
  rp = (mp_ptr) TMP_ALLOC (bsize * BYTES_PER_MP_LIMB);
  rsize = bsize;

  mpn_tdiv_qr (qp, rp, 0, ap, asize, bp, bsize);
  sh = - (int) qp[qsize];
  /* since u and v are normalized, sh is 0 or -1 */

  /* we have {qp, qsize + 1} = {ap, asize} / {bp, bsize} (1 - errq)
     with 0 <= errq < 2^(-qsize*BITS_PER_MP_LIMB+1+sh)
     thus {qp, qsize + 1} =
     (true dividend) / (true divisor) * (1 - erra) (1 + errb) (1 - errq).
     
     In fact, since the truncated dividend and {rp, bsize} do not overlap,
     we have: {qp, qsize + 1} =
     (true dividend) / (true divisor) * (1 - erra') (1 + errb)
     where 0 <= erra' < 2^(-qsize*BITS_PER_MP_LIMB+sh) */

  /* Estimate number of correct bits. */

  err = qsize * BITS_PER_MP_LIMB;

  /* We want to check if rounding is possible, but without normalizing
     because we might have to divide again if rounding is impossible, or
     if the result might be exact. We have however to mimic normalization */

  /*
     To detect asap if the result is inexact, so as to avoid doing the
     division completely, we perform the following check :

     - if rnd_mode != GMP_RNDN, and the result is exact, we are unable
     to round simultaneously to zero and to infinity ;

     - if rnd_mode == GMP_RNDN, and if we can round to zero with one extra
     bit of precision, we can decide rounding. Hence in that case, check
     as in the case of GMP_RNDN, with one extra bit. Note that in the case
     of close to even rounding we shall do the division completely, but
     this is necessary anyway : we need to know whether this is really
     even rounding or not.
  */

  if (MPFR_UNLIKELY(asize < usize || bsize < vsize))
    {
      {
	mp_rnd_t  rnd_mode1, rnd_mode2;
	mp_exp_t  tmp_exp;
	mp_prec_t tmp_prec;

        if (bsize < vsize)
          err -= 2; /* divisor is truncated */
#if 0 /* commented this out since the truncation of the dividend is already
         taken into account in {rp, bsize}, which does not overlap with the
         neglected part of the dividend */
        else if (asize < usize)
          err --;   /* dividend is truncated */
#endif

	if (MPFR_LIKELY(rnd_mode == GMP_RNDN))
	  {
	    rnd_mode1 = GMP_RNDZ;
	    rnd_mode2 = MPFR_IS_POS_SIGN(sign_quotient) ? GMP_RNDU : GMP_RNDD;
	    sh++;
	  }
	else
	  {
	    rnd_mode1 = rnd_mode;
	    switch (rnd_mode)
	      {
	      case GMP_RNDU:
		rnd_mode2 = GMP_RNDD; break;
	      case GMP_RNDD:
		rnd_mode2 = GMP_RNDU; break;
	      default:
		rnd_mode2 = MPFR_IS_POS_SIGN(sign_quotient) ?
		  GMP_RNDU : GMP_RNDD;
		break;
	      }
	  }

	tmp_exp  = err + sh + BITS_PER_MP_LIMB;
	tmp_prec = MPFR_PREC(q) + sh + BITS_PER_MP_LIMB;
	
	can_round =
	  mpfr_can_round_raw (qp, qsize + 1, sign_quotient, tmp_exp,
                              GMP_RNDN, rnd_mode1, tmp_prec)
	  & mpfr_can_round_raw (qp, qsize + 1, sign_quotient, tmp_exp,
                                GMP_RNDN, rnd_mode2, tmp_prec);

        /* restore original value of sh, i.e. sh = - qp[qsize] */
	sh -= (rnd_mode == GMP_RNDN);
      }
Beispiel #24
0
void
mpf_ui_sub (mpf_ptr r, unsigned long int u, mpf_srcptr v)
{
  mp_srcptr up, vp;
  mp_ptr rp, tp;
  mp_size_t usize, vsize, rsize;
  mp_size_t prec;
  mp_exp_t uexp;
  mp_size_t ediff;
  int negate;
  mp_limb_t ulimb;
  TMP_DECL;

  vsize = v->_mp_size;

  /* Handle special cases that don't work in generic code below.  */
  if (u == 0)
    {
      mpf_neg (r, v);
      return;
    }
  if (vsize == 0)
    {
      mpf_set_ui (r, u);
      return;
    }

  /* If signs of U and V are different, perform addition.  */
  if (vsize < 0)
    {
      __mpf_struct v_negated;
      v_negated._mp_size = -vsize;
      v_negated._mp_exp = v->_mp_exp;
      v_negated._mp_d = v->_mp_d;
      mpf_add_ui (r, &v_negated, u);
      return;
    }

  TMP_MARK;

  /* Signs are now known to be the same.  */

  ulimb = u;
  /* Make U be the operand with the largest exponent.  */
  if (1 < v->_mp_exp)
    {
      negate = 1;
      usize = ABS (vsize);
      vsize = 1;
      up = v->_mp_d;
      vp = &ulimb;
      rp = r->_mp_d;
      prec = r->_mp_prec + 1;
      uexp = v->_mp_exp;
      ediff = uexp - 1;
    }
  else
    {
      negate = 0;
      usize = 1;
      vsize = ABS (vsize);
      up = &ulimb;
      vp = v->_mp_d;
      rp = r->_mp_d;
      prec = r->_mp_prec;
      uexp = 1;
      ediff = 1 - v->_mp_exp;
    }

  /* Ignore leading limbs in U and V that are equal.  Doing
     this helps increase the precision of the result.  */
  if (ediff == 0)
    {
      /* This loop normally exits immediately.  Optimize for that.  */
      for (;;)
	{
	  usize--;
	  vsize--;
	  if (up[usize] != vp[vsize])
	    break;
	  uexp--;
	  if (usize == 0)
	    goto Lu0;
	  if (vsize == 0)
	    goto Lv0;
	}
      usize++;
      vsize++;
      /* Note that either operand (but not both operands) might now have
	 leading zero limbs.  It matters only that U is unnormalized if
	 vsize is now zero, and vice versa.  And it is only in that case
	 that we have to adjust uexp.  */
      if (vsize == 0)
      Lv0:
	while (usize != 0 && up[usize - 1] == 0)
	  usize--, uexp--;
      if (usize == 0)
      Lu0:
	while (vsize != 0 && vp[vsize - 1] == 0)
	  vsize--, uexp--;
    }

  /* If U extends beyond PREC, ignore the part that does.  */
  if (usize > prec)
    {
      up += usize - prec;
      usize = prec;
    }

  /* If V extends beyond PREC, ignore the part that does.
     Note that this may make vsize negative.  */
  if (vsize + ediff > prec)
    {
      vp += vsize + ediff - prec;
      vsize = prec - ediff;
    }

  /* Allocate temp space for the result.  Allocate
     just vsize + ediff later???  */
  tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);

  if (ediff >= prec)
    {
      /* V completely cancelled.  */
      if (tp != up)
	MPN_COPY (rp, up, usize);
      rsize = usize;
    }
  else
    {
      /* Locate the least significant non-zero limb in (the needed
	 parts of) U and V, to simplify the code below.  */
      for (;;)
	{
	  if (vsize == 0)
	    {
	      MPN_COPY (rp, up, usize);
	      rsize = usize;
	      goto done;
	    }
	  if (vp[0] != 0)
	    break;
	  vp++, vsize--;
	}
      for (;;)
	{
	  if (usize == 0)
	    {
	      MPN_COPY (rp, vp, vsize);
	      rsize = vsize;
	      negate ^= 1;
	      goto done;
	    }
	  if (up[0] != 0)
	    break;
	  up++, usize--;
	}

      /* uuuu     |  uuuu     |  uuuu     |  uuuu     |  uuuu    */
      /* vvvvvvv  |  vv       |    vvvvv  |    v      |       vv */

      if (usize > ediff)
	{
	  /* U and V partially overlaps.  */
	  if (ediff == 0)
	    {
	      /* Have to compare the leading limbs of u and v
		 to determine whether to compute u - v or v - u.  */
	      if (usize > vsize)
		{
		  /* uuuu     */
		  /* vv       */
		  int cmp;
		  cmp = mpn_cmp (up + usize - vsize, vp, vsize);
		  if (cmp >= 0)
		    {
		      mp_size_t size;
		      size = usize - vsize;
		      MPN_COPY (tp, up, size);
		      mpn_sub_n (tp + size, up + size, vp, vsize);
		      rsize = usize;
		    }
		  else
		    {
		      /* vv       */  /* Swap U and V. */
		      /* uuuu     */
		      mp_size_t size, i;
		      size = usize - vsize;
		      tp[0] = -up[0] & GMP_NUMB_MASK;
		      for (i = 1; i < size; i++)
			tp[i] = ~up[i] & GMP_NUMB_MASK;
		      mpn_sub_n (tp + size, vp, up + size, vsize);
		      mpn_sub_1 (tp + size, tp + size, vsize, (mp_limb_t) 1);
		      negate ^= 1;
		      rsize = usize;
		    }
		}
	      else if (usize < vsize)
		{
		  /* uuuu     */
		  /* vvvvvvv  */
		  int cmp;
		  cmp = mpn_cmp (up, vp + vsize - usize, usize);
		  if (cmp > 0)
		    {
		      mp_size_t size, i;
		      size = vsize - usize;
		      tp[0] = -vp[0] & GMP_NUMB_MASK;
		      for (i = 1; i < size; i++)
			tp[i] = ~vp[i] & GMP_NUMB_MASK;
		      mpn_sub_n (tp + size, up, vp + size, usize);
		      mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
		      rsize = vsize;
		    }
		  else
		    {
		      /* vvvvvvv  */  /* Swap U and V. */
		      /* uuuu     */
		      /* This is the only place we can get 0.0.  */
		      mp_size_t size;
		      size = vsize - usize;
		      MPN_COPY (tp, vp, size);
		      mpn_sub_n (tp + size, vp + size, up, usize);
		      negate ^= 1;
		      rsize = vsize;
		    }
		}
	      else
		{
		  /* uuuu     */
		  /* vvvv     */
		  int cmp;
		  cmp = mpn_cmp (up, vp + vsize - usize, usize);
		  if (cmp > 0)
		    {
		      mpn_sub_n (tp, up, vp, usize);
		      rsize = usize;
		    }
		  else
		    {
		      mpn_sub_n (tp, vp, up, usize);
		      negate ^= 1;
		      rsize = usize;
		      /* can give zero */
		    }
		}
	    }
	  else
	    {
	      if (vsize + ediff <= usize)
		{
		  /* uuuu     */
		  /*   v      */
		  mp_size_t size;
		  size = usize - ediff - vsize;
		  MPN_COPY (tp, up, size);
		  mpn_sub (tp + size, up + size, usize - size, vp, vsize);
		  rsize = usize;
		}
	      else
		{
		  /* uuuu     */
		  /*   vvvvv  */
		  mp_size_t size, i;
		  size = vsize + ediff - usize;
		  tp[0] = -vp[0] & GMP_NUMB_MASK;
		  for (i = 1; i < size; i++)
		    tp[i] = ~vp[i] & GMP_NUMB_MASK;
		  mpn_sub (tp + size, up, usize, vp + size, usize - ediff);
		  mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
		  rsize = vsize + ediff;
		}
	    }
	}
      else
	{
	  /* uuuu     */
	  /*      vv  */
	  mp_size_t size, i;
	  size = vsize + ediff - usize;
	  tp[0] = -vp[0] & GMP_NUMB_MASK;
	  for (i = 1; i < vsize; i++)
	    tp[i] = ~vp[i] & GMP_NUMB_MASK;
	  for (i = vsize; i < size; i++)
	    tp[i] = GMP_NUMB_MAX;
	  mpn_sub_1 (tp + size, up, usize, (mp_limb_t) 1);
	  rsize = size + usize;
	}

      /* Full normalize.  Optimize later.  */
      while (rsize != 0 && tp[rsize - 1] == 0)
	{
	  rsize--;
	  uexp--;
	}
      MPN_COPY (rp, tp, rsize);
    }

 done:
  r->_mp_size = negate ? -rsize : rsize;
  r->_mp_exp = uexp;
  TMP_FREE;
}
Beispiel #25
0
size_t
mpz_out_str (FILE *stream, int base, mpz_srcptr x)
{
  mp_ptr xp;
  mp_size_t x_size = x->_mp_size;
  unsigned char *str;
  size_t str_size;
  size_t i;
  size_t written;
  char *num_to_text;
  TMP_DECL;

  if (stream == 0)
    stream = stdout;

  if (base >= 0)
    {
      num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz";
      if (base == 0)
	base = 10;
      else if (base > 36)
	{
	  num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
	  if (base > 62)
	    return 0;
	}
    }
  else
    {
      base = -base;
      num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    }

  if (x_size == 0)
    {
      fputc ('0', stream);
      return ferror (stream) ? 0 : 1;
    }

  written = 0;

  if (x_size < 0)
    {
      fputc ('-', stream);
      x_size = -x_size;
      written = 1;
    }

  TMP_MARK;
  str_size = ((size_t) (x_size * BITS_PER_MP_LIMB
			* __mp_bases[base].chars_per_bit_exactly)) + 3;
  str = (unsigned char *) TMP_ALLOC (str_size);

  /* Move the number to convert into temporary space, since mpn_get_str
     clobbers its argument + needs one extra high limb....  */
  xp = (mp_ptr) TMP_ALLOC ((x_size + 1) * BYTES_PER_MP_LIMB);
  MPN_COPY (xp, x->_mp_d, x_size);

  str_size = mpn_get_str (str, base, xp, x_size);

  /* mpn_get_str might make some leading zeros.  Skip them.  */
  while (*str == 0)
    {
      str_size--;
      str++;
    }

  /* Translate to printable chars.  */
  for (i = 0; i < str_size; i++)
    str[i] = num_to_text[str[i]];
  str[str_size] = 0;

  {
    size_t fwret;
    fwret = fwrite ((char *) str, 1, str_size, stream);
    written += fwret;
  }

  TMP_FREE;
  return ferror (stream) ? 0 : written;
}
Beispiel #26
0
void
cfb_decrypt(const void *ctx, nettle_cipher_func *f,
	    size_t block_size, uint8_t *iv,
	    size_t length, uint8_t *dst,
	    const uint8_t *src)
{
  if (src != dst)
    {
      size_t left = length % block_size;

      length -= left;
      if (length > 0)
	{
	  /* Decrypt in ECB mode */
	  f(ctx, block_size, dst, iv);
	  f(ctx, length - block_size, dst + block_size, src);
	  memcpy(iv, src + length - block_size, block_size);
	  memxor(dst, src, length);
	}

      if (left > 0)
	{
	  TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
	  TMP_ALLOC(buffer, block_size);

	  f(ctx, block_size, buffer, iv);
	  memxor3(dst + length, src + length, buffer, left);
	}
    }
  else
    {
      /* For in-place CFB, we decrypt into a temporary buffer of size
       * at most CFB_BUFFER_LIMIT, and process that amount of data at
       * a time. */

      /* NOTE: We assume that block_size <= CFB_BUFFER_LIMIT */

      TMP_DECL(buffer, uint8_t, CFB_BUFFER_LIMIT);
      TMP_DECL(initial_iv, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);

      size_t buffer_size;
      size_t left;

      buffer_size = CFB_BUFFER_LIMIT - (CFB_BUFFER_LIMIT % block_size);

      TMP_ALLOC(buffer, buffer_size);
      TMP_ALLOC(initial_iv, block_size);

      left = length % block_size;
      length -= left;

      while (length > 0)
	{
	  size_t part = length > buffer_size ? buffer_size : length;

	  /* length is greater that zero and is divided by block_size, so it is
	   * not less than block_size. So does part */

	  f(ctx, block_size, buffer, iv);
	  f(ctx, part - block_size, buffer + block_size, src);
	  memcpy(iv, src + part - block_size, block_size);
	  memxor(dst, buffer, part);

	  length -= part;
	  src += part;
	  dst += part;
	}

      if (left > 0)
	{
	  f(ctx, block_size, buffer, iv);
	  memxor(dst, buffer, left);
	}
    }
}
Beispiel #27
0
int
mpz_set_str (mpz_ptr x, const char *str, int base)
{
  size_t str_size;
  char *s, *begs;
  size_t i;
  mp_size_t xsize;
  int c;
  int negative;
  const unsigned char *digit_value;
  TMP_DECL;

  digit_value = digit_value_tab;
  if (base > 36)
    {
      /* For bases > 36, use the collating sequence
	 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.  */
      digit_value += 208;
      if (base > 62)
	return -1;		/* too large base */
    }

  /* Skip whitespace.  */
  do
    c = (unsigned char) *str++;
  while (isspace (c));

  negative = 0;
  if (c == '-')
    {
      negative = 1;
      c = (unsigned char) *str++;
    }

  if (digit_value[c] >= (base == 0 ? 10 : base))
    return -1;			/* error if no valid digits */

  /* If BASE is 0, try to find out the base by looking at the initial
     characters.  */
  if (base == 0)
    {
      base = 10;
      if (c == '0')
	{
	  base = 8;
	  c = (unsigned char) *str++;
	  if (c == 'x' || c == 'X')
	    {
	      base = 16;
	      c = (unsigned char) *str++;
	    }
	  else if (c == 'b' || c == 'B')
	    {
	      base = 2;
	      c = (unsigned char) *str++;
	    }
	}
    }

  /* Skip leading zeros and white space.  */
  while (c == '0' || isspace (c))
    c = (unsigned char) *str++;
  /* Make sure the string does not become empty, mpn_set_str would fail.  */
  if (c == 0)
    {
      SIZ (x) = 0;
      return 0;
    }

  TMP_MARK;
  str_size = strlen (str - 1);
  s = begs = (char *) TMP_ALLOC (str_size + 1);

  /* Remove spaces from the string and convert the result from ASCII to a
     byte array.  */
  for (i = 0; i < str_size; i++)
    {
      if (!isspace (c))
	{
	  int dig = digit_value[c];
	  if (dig >= base)
	    {
	      TMP_FREE;
	      return -1;
	    }
	  *s++ = dig;
	}
      c = (unsigned char) *str++;
    }

  str_size = s - begs;

  LIMBS_PER_DIGIT_IN_BASE (xsize, str_size, base);
  MPZ_REALLOC (x, xsize);

  /* Convert the byte array in base BASE to our bignum format.  */
  xsize = mpn_set_str (PTR (x), (unsigned char *) begs, str_size, base);
  SIZ (x) = negative ? -xsize : xsize;

  TMP_FREE;
  return 0;
}
Beispiel #28
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 #29
0
/* returns 0 if result exact, non-zero otherwise */
int
mpfr_div_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mp_rnd_t rnd_mode)
{
  long int xn, yn, dif, sh, i;
  mp_limb_t *xp, *yp, *tmp, c, d;
  mp_exp_t exp;
  int inexact, middle = 1;
  TMP_DECL(marker);

  if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(x) ))
    {
      if (MPFR_IS_NAN(x))
	{
	  MPFR_SET_NAN(y);
	  MPFR_RET_NAN;
	}
      else if (MPFR_IS_INF(x))
	{
	  MPFR_SET_INF(y);
	  MPFR_SET_SAME_SIGN(y, x);
	  MPFR_RET(0);
	}
      else
	{
          MPFR_ASSERTD(MPFR_IS_ZERO(x));
	  if (u == 0)/* 0/0 is NaN */
	    {
	      MPFR_SET_NAN(y);
	      MPFR_RET_NAN;
	    }
	  else
	    {
	      MPFR_SET_ZERO(y);
	      MPFR_RET(0);
	    }
	}
    }

  if (MPFR_UNLIKELY(u == 0))
    {
      /* x/0 is Inf */
      MPFR_SET_INF(y);
      MPFR_SET_SAME_SIGN(y, x);
      MPFR_RET(0);
    }

  MPFR_CLEAR_FLAGS(y);

  MPFR_SET_SAME_SIGN(y, x);

  TMP_MARK(marker);
  xn = MPFR_LIMB_SIZE(x);
  yn = MPFR_LIMB_SIZE(y);

  xp = MPFR_MANT(x);
  yp = MPFR_MANT(y);
  exp = MPFR_GET_EXP (x);

  dif = yn + 1 - xn;

  /* we need to store yn+1 = xn + dif limbs of the quotient */
  /* don't use tmp=yp since the mpn_lshift call below requires yp >= tmp+1 */
  tmp = (mp_limb_t*) TMP_ALLOC((yn + 1) * BYTES_PER_MP_LIMB);

  c = (mp_limb_t) u;
  MPFR_ASSERTN(u == c);
  if (dif >= 0)
    c = mpn_divrem_1 (tmp, dif, xp, xn, c); /* used all the dividend */
  else /* dif < 0 i.e. xn > yn, don't use the (-dif) low limbs from x */
    c = mpn_divrem_1 (tmp, 0, xp - dif, yn + 1, c);

  inexact = (c != 0);

  /* First pass in estimating next bit of the quotient, in case of RNDN    *
   * In case we just have the right number of bits (postpone this ?),      *
   * we need to check whether the remainder is more or less than half      *
   * the divisor. The test must be performed with a subtraction, so as     *
   * to prevent carries.                                                   */

  if (rnd_mode == GMP_RNDN)
    {
      if (c < (mp_limb_t) u - c) /* We have u > c */
	middle = -1;
      else if (c > (mp_limb_t) u - c)
	middle = 1;
      else
	middle = 0; /* exactly in the middle */
    }

  /* If we believe that we are right in the middle or exact, we should check
     that we did not neglect any word of x (division large / 1 -> small). */

  for (i=0; ((inexact == 0) || (middle == 0)) && (i < -dif); i++)
    if (xp[i])
      inexact = middle = 1; /* larger than middle */

  /*
     If the high limb of the result is 0 (xp[xn-1] < u), remove it.
     Otherwise, compute the left shift to be performed to normalize.
     In the latter case, we discard some low bits computed. They
     contain information useful for the rounding, hence the updating
     of middle and inexact.
  */

  if (tmp[yn] == 0)
    {
      MPN_COPY(yp, tmp, yn);
      exp -= BITS_PER_MP_LIMB;
      sh = 0;
    }
  else
    {
      count_leading_zeros (sh, tmp[yn]);

      /* shift left to normalize */
      if (sh)
        {
          mp_limb_t w = tmp[0] << sh;

          mpn_lshift (yp, tmp + 1, yn, sh);
          yp[0] += tmp[0] >> (BITS_PER_MP_LIMB - sh);

          if (w > (MPFR_LIMB_ONE << (BITS_PER_MP_LIMB - 1)))
            { middle = 1; }
          else if (w < (MPFR_LIMB_ONE << (BITS_PER_MP_LIMB - 1)))
            { middle = -1; }
          else
            { middle = (c != 0); }

          inexact = inexact || (w != 0);
          exp -= sh;
        }
      else
        { /* this happens only if u == 1 and xp[xn-1] >=
             1<<(BITS_PER_MP_LIMB-1). It might be better to handle the
             u == 1 case seperately ?
          */

          MPN_COPY (yp, tmp + 1, yn);
        }
    }
Beispiel #30
0
/* Compute the first 2^m terms from the hypergeometric series
   with x = p / 2^r */
static int
GENERIC (mpfr_ptr y, mpz_srcptr p, long r, int m)
{
  int n,i,k,j,l;
  int is_p_one = 0;
  mpz_t* P,*S;
#ifdef A
  mpz_t *T;
#endif
  mpz_t* ptoj;
#ifdef R_IS_RATIONAL
  mpz_t* qtoj;
  mpfr_t tmp;
#endif
  int diff, expo;
  int precy = MPFR_PREC(y);
  TMP_DECL(marker);

  TMP_MARK(marker);
  MPFR_CLEAR_FLAGS(y); 
  n = 1 << m;
  P = (mpz_t*) TMP_ALLOC ((m+1) * sizeof(mpz_t));
  S = (mpz_t*) TMP_ALLOC ((m+1) * sizeof(mpz_t));
  ptoj = (mpz_t*) TMP_ALLOC ((m+1) * sizeof(mpz_t)); /* ptoj[i] = mantissa^(2^i) */
#ifdef A
  T = (mpz_t*) TMP_ALLOC ((m+1) * sizeof(mpz_t));
#endif
#ifdef R_IS_RATIONAL
  qtoj = (mpz_t*) TMP_ALLOC ((m+1) * sizeof(mpz_t));
#endif
  for (i=0;i<=m;i++)
    {
      mpz_init (P[i]);
      mpz_init (S[i]);
      mpz_init (ptoj[i]);
#ifdef R_IS_RATIONAL
      mpz_init (qtoj[i]);
#endif
#ifdef A
      mpz_init (T[i]);
#endif
    }
  mpz_set (ptoj[0], p);
#ifdef C
#  if C2 != 1
  mpz_mul_ui(ptoj[0], ptoj[0], C2);
#  endif
#endif
  is_p_one = !mpz_cmp_si(ptoj[0], 1);
#ifdef A
#  ifdef B
  mpz_set_ui(T[0], A1 * B1);
#  else
  mpz_set_ui(T[0], A1);
#  endif
#endif
  if (!is_p_one) 
  for (i=1;i<m;i++) mpz_mul(ptoj[i], ptoj[i-1], ptoj[i-1]);
#ifdef R_IS_RATIONAL
  mpz_set_si(qtoj[0], r);
  for (i=1;i<=m;i++) 
    {
      mpz_mul(qtoj[i], qtoj[i-1], qtoj[i-1]);
    }
#endif

  mpz_set_ui(P[0], 1);
  mpz_set_ui(S[0], 1);
  k = 0;
  for (i=1;(i < n) ;i++) {
    k++;
    
#ifdef A
#  ifdef B 
    mpz_set_ui(T[k], (A1 + A2*i)*(B1+B2*i));
#  else
    mpz_set_ui(T[k], A1 + A2*i);
#  endif
#endif
    
#ifdef C
#  ifdef NO_FACTORIAL
    mpz_set_ui(P[k], (C1 + C2 * (i-1)));
    mpz_set_ui(S[k], 1);
#  else
    mpz_set_ui(P[k], (i+1) * (C1 + C2 * (i-1)));
    mpz_set_ui(S[k], i+1);
#  endif
#else
#  ifdef NO_FACTORIAL
    mpz_set_ui(P[k], 1);
#  else
    mpz_set_ui(P[k], i+1);
#  endif
    mpz_set(S[k], P[k]);
#endif
    j=i+1; l=0; while ((j & 1) == 0) {      
      if (!is_p_one) 
	mpz_mul(S[k], S[k], ptoj[l]);
#ifdef A
#  ifdef B
#    if (A2*B2) != 1
      mpz_mul_ui(P[k], P[k], A2*B2);
#    endif
#  else
#    if A2 != 1 
      mpz_mul_ui(P[k], P[k], A2);
#  endif
#endif
      mpz_mul(S[k], S[k], T[k-1]);
#endif
      mpz_mul(S[k-1], S[k-1], P[k]);
#ifdef R_IS_RATIONAL
      mpz_mul(S[k-1], S[k-1], qtoj[l]);
#else
      mpz_mul_2exp(S[k-1], S[k-1], r*(1<<l));
#endif
      mpz_add(S[k-1], S[k-1], S[k]);
      mpz_mul(P[k-1], P[k-1], P[k]);
#ifdef A
      mpz_mul(T[k-1], T[k-1], T[k]);
#endif
      l++; j>>=1; k--;
    }
  }

  diff = mpz_sizeinbase(S[0],2) - 2*precy;
  expo = diff;
  if (diff >=0)
    {
      mpz_div_2exp(S[0],S[0],diff);
    } else 
      {
	mpz_mul_2exp(S[0],S[0],-diff);
      }
  diff = mpz_sizeinbase(P[0],2) - precy;
  expo -= diff;
  if (diff >=0)
    {
      mpz_div_2exp(P[0],P[0],diff);
    } else
      {
	mpz_mul_2exp(P[0],P[0],-diff);
	}

  mpz_tdiv_q(S[0], S[0], P[0]);
  mpfr_set_z(y, S[0], GMP_RNDD);
  MPFR_SET_EXP (y, MPFR_GET_EXP (y) + expo);

#ifdef R_IS_RATIONAL
  /* exact division */
  mpz_div_ui (qtoj[m], qtoj[m], r);
  mpfr_init2 (tmp, MPFR_PREC(y));
  mpfr_set_z (tmp, qtoj[m] , GMP_RNDD);
  mpfr_div (y, y, tmp, GMP_RNDD);
  mpfr_clear (tmp);
#else
  mpfr_div_2ui(y, y, r*(i-1), GMP_RNDN);
#endif
  for (i=0;i<=m;i++)
    {
      mpz_clear (P[i]);
      mpz_clear (S[i]);
      mpz_clear (ptoj[i]); 
#ifdef R_IS_RATIONAL
      mpz_clear (qtoj[i]);
#endif
#ifdef A
      mpz_clear (T[i]);
#endif
    }
  TMP_FREE(marker);
  return 0;
}