| Index: gcc/gmp/tests/refmpn.c
|
| diff --git a/gcc/gmp/tests/refmpn.c b/gcc/gmp/tests/refmpn.c
|
| deleted file mode 100644
|
| index 6af830b11078bafb89c497e556b9b4c9803777dd..0000000000000000000000000000000000000000
|
| --- a/gcc/gmp/tests/refmpn.c
|
| +++ /dev/null
|
| @@ -1,2004 +0,0 @@
|
| -/* Reference mpn functions, designed to be simple, portable and independent
|
| - of the normal gmp code. Speed isn't a consideration.
|
| -
|
| -Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
| -2007, 2008 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 3 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. If not, see http://www.gnu.org/licenses/. */
|
| -
|
| -
|
| -/* Most routines have assertions representing what the mpn routines are
|
| - supposed to accept. Many of these reference routines do sensible things
|
| - outside these ranges (eg. for size==0), but the assertions are present to
|
| - pick up bad parameters passed here that are about to be passed the same
|
| - to a real mpn routine being compared. */
|
| -
|
| -/* always do assertion checking */
|
| -#define WANT_ASSERT 1
|
| -
|
| -#include <stdio.h> /* for NULL */
|
| -#include <stdlib.h> /* for malloc */
|
| -
|
| -#include "gmp.h"
|
| -#include "gmp-impl.h"
|
| -#include "longlong.h"
|
| -
|
| -#include "tests.h"
|
| -
|
| -
|
| -
|
| -/* Return non-zero if regions {xp,xsize} and {yp,ysize} overlap, with sizes
|
| - in bytes. */
|
| -int
|
| -byte_overlap_p (const void *v_xp, mp_size_t xsize,
|
| - const void *v_yp, mp_size_t ysize)
|
| -{
|
| - const char *xp = v_xp;
|
| - const char *yp = v_yp;
|
| -
|
| - ASSERT (xsize >= 0);
|
| - ASSERT (ysize >= 0);
|
| -
|
| - /* no wraparounds */
|
| - ASSERT (xp+xsize >= xp);
|
| - ASSERT (yp+ysize >= yp);
|
| -
|
| - if (xp + xsize <= yp)
|
| - return 0;
|
| -
|
| - if (yp + ysize <= xp)
|
| - return 0;
|
| -
|
| - return 1;
|
| -}
|
| -
|
| -/* Return non-zero if limb regions {xp,xsize} and {yp,ysize} overlap. */
|
| -int
|
| -refmpn_overlap_p (mp_srcptr xp, mp_size_t xsize, mp_srcptr yp, mp_size_t ysize)
|
| -{
|
| - return byte_overlap_p (xp, xsize * BYTES_PER_MP_LIMB,
|
| - yp, ysize * BYTES_PER_MP_LIMB);
|
| -}
|
| -
|
| -/* Check overlap for a routine defined to work low to high. */
|
| -int
|
| -refmpn_overlap_low_to_high_p (mp_srcptr dst, mp_srcptr src, mp_size_t size)
|
| -{
|
| - return (dst <= src || ! refmpn_overlap_p (dst, size, src, size));
|
| -}
|
| -
|
| -/* Check overlap for a routine defined to work high to low. */
|
| -int
|
| -refmpn_overlap_high_to_low_p (mp_srcptr dst, mp_srcptr src, mp_size_t size)
|
| -{
|
| - return (dst >= src || ! refmpn_overlap_p (dst, size, src, size));
|
| -}
|
| -
|
| -/* Check overlap for a standard routine requiring equal or separate. */
|
| -int
|
| -refmpn_overlap_fullonly_p (mp_srcptr dst, mp_srcptr src, mp_size_t size)
|
| -{
|
| - return (dst == src || ! refmpn_overlap_p (dst, size, src, size));
|
| -}
|
| -int
|
| -refmpn_overlap_fullonly_two_p (mp_srcptr dst, mp_srcptr src1, mp_srcptr src2,
|
| - mp_size_t size)
|
| -{
|
| - return (refmpn_overlap_fullonly_p (dst, src1, size)
|
| - && refmpn_overlap_fullonly_p (dst, src2, size));
|
| -}
|
| -
|
| -
|
| -mp_ptr
|
| -refmpn_malloc_limbs (mp_size_t size)
|
| -{
|
| - mp_ptr p;
|
| - ASSERT (size >= 0);
|
| - if (size == 0)
|
| - size = 1;
|
| - p = (mp_ptr) malloc ((size_t) (size * BYTES_PER_MP_LIMB));
|
| - ASSERT (p != NULL);
|
| - return p;
|
| -}
|
| -
|
| -/* Free limbs allocated by refmpn_malloc_limbs. NOTE: Can't free
|
| - * memory allocated by refmpn_malloc_limbs_aligned. */
|
| -void
|
| -refmpn_free_limbs (mp_ptr p)
|
| -{
|
| - free (p);
|
| -}
|
| -
|
| -mp_ptr
|
| -refmpn_memdup_limbs (mp_srcptr ptr, mp_size_t size)
|
| -{
|
| - mp_ptr p;
|
| - p = refmpn_malloc_limbs (size);
|
| - refmpn_copyi (p, ptr, size);
|
| - return p;
|
| -}
|
| -
|
| -/* malloc n limbs on a multiple of m bytes boundary */
|
| -mp_ptr
|
| -refmpn_malloc_limbs_aligned (mp_size_t n, size_t m)
|
| -{
|
| - return (mp_ptr) align_pointer (refmpn_malloc_limbs (n + m-1), m);
|
| -}
|
| -
|
| -
|
| -void
|
| -refmpn_fill (mp_ptr ptr, mp_size_t size, mp_limb_t value)
|
| -{
|
| - mp_size_t i;
|
| - ASSERT (size >= 0);
|
| - for (i = 0; i < size; i++)
|
| - ptr[i] = value;
|
| -}
|
| -
|
| -void
|
| -refmpn_zero (mp_ptr ptr, mp_size_t size)
|
| -{
|
| - refmpn_fill (ptr, size, CNST_LIMB(0));
|
| -}
|
| -
|
| -void
|
| -refmpn_zero_extend (mp_ptr ptr, mp_size_t oldsize, mp_size_t newsize)
|
| -{
|
| - ASSERT (newsize >= oldsize);
|
| - refmpn_zero (ptr+oldsize, newsize-oldsize);
|
| -}
|
| -
|
| -int
|
| -refmpn_zero_p (mp_srcptr ptr, mp_size_t size)
|
| -{
|
| - mp_size_t i;
|
| - for (i = 0; i < size; i++)
|
| - if (ptr[i] != 0)
|
| - return 0;
|
| - return 1;
|
| -}
|
| -
|
| -mp_size_t
|
| -refmpn_normalize (mp_srcptr ptr, mp_size_t size)
|
| -{
|
| - ASSERT (size >= 0);
|
| - while (size > 0 && ptr[size-1] == 0)
|
| - size--;
|
| - return size;
|
| -}
|
| -
|
| -/* the highest one bit in x */
|
| -mp_limb_t
|
| -refmpn_msbone (mp_limb_t x)
|
| -{
|
| - mp_limb_t n = (mp_limb_t) 1 << (BITS_PER_MP_LIMB-1);
|
| -
|
| - while (n != 0)
|
| - {
|
| - if (x & n)
|
| - break;
|
| - n >>= 1;
|
| - }
|
| - return n;
|
| -}
|
| -
|
| -/* a mask of the highest one bit plus and all bits below */
|
| -mp_limb_t
|
| -refmpn_msbone_mask (mp_limb_t x)
|
| -{
|
| - if (x == 0)
|
| - return 0;
|
| -
|
| - return (refmpn_msbone (x) << 1) - 1;
|
| -}
|
| -
|
| -/* How many digits in the given base will fit in a limb.
|
| - Notice that the product b is allowed to be equal to the limit
|
| - 2^GMP_NUMB_BITS, this ensures the result for base==2 will be
|
| - GMP_NUMB_BITS (and similarly other powers of 2). */
|
| -int
|
| -refmpn_chars_per_limb (int base)
|
| -{
|
| - mp_limb_t limit[2], b[2];
|
| - int chars_per_limb;
|
| -
|
| - ASSERT (base >= 2);
|
| -
|
| - limit[0] = 0; /* limit = 2^GMP_NUMB_BITS */
|
| - limit[1] = 1;
|
| - b[0] = 1; /* b = 1 */
|
| - b[1] = 0;
|
| -
|
| - chars_per_limb = 0;
|
| - for (;;)
|
| - {
|
| - if (refmpn_mul_1 (b, b, (mp_size_t) 2, (mp_limb_t) base))
|
| - break;
|
| - if (refmpn_cmp (b, limit, (mp_size_t) 2) > 0)
|
| - break;
|
| - chars_per_limb++;
|
| - }
|
| - return chars_per_limb;
|
| -}
|
| -
|
| -/* The biggest value base**n which fits in GMP_NUMB_BITS. */
|
| -mp_limb_t
|
| -refmpn_big_base (int base)
|
| -{
|
| - int chars_per_limb = refmpn_chars_per_limb (base);
|
| - int i;
|
| - mp_limb_t bb;
|
| -
|
| - ASSERT (base >= 2);
|
| - bb = 1;
|
| - for (i = 0; i < chars_per_limb; i++)
|
| - bb *= base;
|
| - return bb;
|
| -}
|
| -
|
| -
|
| -void
|
| -refmpn_setbit (mp_ptr ptr, unsigned long bit)
|
| -{
|
| - ptr[bit/GMP_NUMB_BITS] |= CNST_LIMB(1) << (bit%GMP_NUMB_BITS);
|
| -}
|
| -
|
| -void
|
| -refmpn_clrbit (mp_ptr ptr, unsigned long bit)
|
| -{
|
| - ptr[bit/GMP_NUMB_BITS] &= ~ (CNST_LIMB(1) << (bit%GMP_NUMB_BITS));
|
| -}
|
| -
|
| -#define REFMPN_TSTBIT(ptr,bit) \
|
| - (((ptr)[(bit)/GMP_NUMB_BITS] & (CNST_LIMB(1) << ((bit)%GMP_NUMB_BITS))) != 0)
|
| -
|
| -int
|
| -refmpn_tstbit (mp_srcptr ptr, unsigned long bit)
|
| -{
|
| - return REFMPN_TSTBIT (ptr, bit);
|
| -}
|
| -
|
| -unsigned long
|
| -refmpn_scan0 (mp_srcptr ptr, unsigned long bit)
|
| -{
|
| - while (REFMPN_TSTBIT (ptr, bit) != 0)
|
| - bit++;
|
| - return bit;
|
| -}
|
| -
|
| -unsigned long
|
| -refmpn_scan1 (mp_srcptr ptr, unsigned long bit)
|
| -{
|
| - while (REFMPN_TSTBIT (ptr, bit) == 0)
|
| - bit++;
|
| - return bit;
|
| -}
|
| -
|
| -void
|
| -refmpn_copy (mp_ptr rp, mp_srcptr sp, mp_size_t size)
|
| -{
|
| - ASSERT (refmpn_overlap_fullonly_p (rp, sp, size));
|
| - refmpn_copyi (rp, sp, size);
|
| -}
|
| -
|
| -void
|
| -refmpn_copyi (mp_ptr rp, mp_srcptr sp, mp_size_t size)
|
| -{
|
| - mp_size_t i;
|
| -
|
| - ASSERT (refmpn_overlap_low_to_high_p (rp, sp, size));
|
| - ASSERT (size >= 0);
|
| -
|
| - for (i = 0; i < size; i++)
|
| - rp[i] = sp[i];
|
| -}
|
| -
|
| -void
|
| -refmpn_copyd (mp_ptr rp, mp_srcptr sp, mp_size_t size)
|
| -{
|
| - mp_size_t i;
|
| -
|
| - ASSERT (refmpn_overlap_high_to_low_p (rp, sp, size));
|
| - ASSERT (size >= 0);
|
| -
|
| - for (i = size-1; i >= 0; i--)
|
| - rp[i] = sp[i];
|
| -}
|
| -
|
| -/* Copy {xp,xsize} to {wp,wsize}. If x is shorter, then pad w with low
|
| - zeros to wsize. If x is longer, then copy just the high wsize limbs. */
|
| -void
|
| -refmpn_copy_extend (mp_ptr wp, mp_size_t wsize, mp_srcptr xp, mp_size_t xsize)
|
| -{
|
| - ASSERT (wsize >= 0);
|
| - ASSERT (xsize >= 0);
|
| -
|
| - /* high part of x if x bigger than w */
|
| - if (xsize > wsize)
|
| - {
|
| - xp += xsize - wsize;
|
| - xsize = wsize;
|
| - }
|
| -
|
| - refmpn_copy (wp + wsize-xsize, xp, xsize);
|
| - refmpn_zero (wp, wsize-xsize);
|
| -}
|
| -
|
| -void
|
| -refmpn_com_n (mp_ptr rp, mp_srcptr sp, mp_size_t size)
|
| -{
|
| - mp_size_t i;
|
| -
|
| - ASSERT (refmpn_overlap_fullonly_p (rp, sp, size));
|
| - ASSERT (size >= 1);
|
| - ASSERT_MPN (sp, size);
|
| -
|
| - for (i = 0; i < size; i++)
|
| - rp[i] = sp[i] ^ GMP_NUMB_MASK;
|
| -}
|
| -
|
| -
|
| -int
|
| -refmpn_cmp (mp_srcptr xp, mp_srcptr yp, mp_size_t size)
|
| -{
|
| - mp_size_t i;
|
| -
|
| - ASSERT (size >= 1);
|
| - ASSERT_MPN (xp, size);
|
| - ASSERT_MPN (yp, size);
|
| -
|
| - for (i = size-1; i >= 0; i--)
|
| - {
|
| - if (xp[i] > yp[i]) return 1;
|
| - if (xp[i] < yp[i]) return -1;
|
| - }
|
| - return 0;
|
| -}
|
| -
|
| -int
|
| -refmpn_cmp_allowzero (mp_srcptr xp, mp_srcptr yp, mp_size_t size)
|
| -{
|
| - if (size == 0)
|
| - return 0;
|
| - else
|
| - return refmpn_cmp (xp, yp, size);
|
| -}
|
| -
|
| -int
|
| -refmpn_cmp_twosizes (mp_srcptr xp, mp_size_t xsize,
|
| - mp_srcptr yp, mp_size_t ysize)
|
| -{
|
| - int opp, cmp;
|
| -
|
| - ASSERT_MPN (xp, xsize);
|
| - ASSERT_MPN (yp, ysize);
|
| -
|
| - opp = (xsize < ysize);
|
| - if (opp)
|
| - MPN_SRCPTR_SWAP (xp,xsize, yp,ysize);
|
| -
|
| - if (! refmpn_zero_p (xp+ysize, xsize-ysize))
|
| - cmp = 1;
|
| - else
|
| - cmp = refmpn_cmp (xp, yp, ysize);
|
| -
|
| - return (opp ? -cmp : cmp);
|
| -}
|
| -
|
| -int
|
| -refmpn_equal_anynail (mp_srcptr xp, mp_srcptr yp, mp_size_t size)
|
| -{
|
| - mp_size_t i;
|
| - ASSERT (size >= 0);
|
| -
|
| - for (i = 0; i < size; i++)
|
| - if (xp[i] != yp[i])
|
| - return 0;
|
| - return 1;
|
| -}
|
| -
|
| -
|
| -#define LOGOPS(operation) \
|
| - { \
|
| - mp_size_t i; \
|
| - \
|
| - ASSERT (refmpn_overlap_fullonly_two_p (rp, s1p, s2p, size)); \
|
| - ASSERT (size >= 1); \
|
| - ASSERT_MPN (s1p, size); \
|
| - ASSERT_MPN (s2p, size); \
|
| - \
|
| - for (i = 0; i < size; i++) \
|
| - rp[i] = operation; \
|
| - }
|
| -
|
| -void
|
| -refmpn_and_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
|
| -{
|
| - LOGOPS (s1p[i] & s2p[i]);
|
| -}
|
| -void
|
| -refmpn_andn_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
|
| -{
|
| - LOGOPS (s1p[i] & ~s2p[i]);
|
| -}
|
| -void
|
| -refmpn_nand_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
|
| -{
|
| - LOGOPS ((s1p[i] & s2p[i]) ^ GMP_NUMB_MASK);
|
| -}
|
| -void
|
| -refmpn_ior_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
|
| -{
|
| - LOGOPS (s1p[i] | s2p[i]);
|
| -}
|
| -void
|
| -refmpn_iorn_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
|
| -{
|
| - LOGOPS (s1p[i] | (s2p[i] ^ GMP_NUMB_MASK));
|
| -}
|
| -void
|
| -refmpn_nior_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
|
| -{
|
| - LOGOPS ((s1p[i] | s2p[i]) ^ GMP_NUMB_MASK);
|
| -}
|
| -void
|
| -refmpn_xor_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
|
| -{
|
| - LOGOPS (s1p[i] ^ s2p[i]);
|
| -}
|
| -void
|
| -refmpn_xnor_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
|
| -{
|
| - LOGOPS ((s1p[i] ^ s2p[i]) ^ GMP_NUMB_MASK);
|
| -}
|
| -
|
| -
|
| -/* set *dh,*dl to mh:ml - sh:sl, in full limbs */
|
| -void
|
| -refmpn_sub_ddmmss (mp_limb_t *dh, mp_limb_t *dl,
|
| - mp_limb_t mh, mp_limb_t ml, mp_limb_t sh, mp_limb_t sl)
|
| -{
|
| - *dl = ml - sl;
|
| - *dh = mh - sh - (ml < sl);
|
| -}
|
| -
|
| -
|
| -/* set *w to x+y, return 0 or 1 carry */
|
| -mp_limb_t
|
| -ref_addc_limb (mp_limb_t *w, mp_limb_t x, mp_limb_t y)
|
| -{
|
| - mp_limb_t sum, cy;
|
| -
|
| - ASSERT_LIMB (x);
|
| - ASSERT_LIMB (y);
|
| -
|
| - sum = x + y;
|
| -#if GMP_NAIL_BITS == 0
|
| - *w = sum;
|
| - cy = (sum < x);
|
| -#else
|
| - *w = sum & GMP_NUMB_MASK;
|
| - cy = (sum >> GMP_NUMB_BITS);
|
| -#endif
|
| - return cy;
|
| -}
|
| -
|
| -/* set *w to x-y, return 0 or 1 borrow */
|
| -mp_limb_t
|
| -ref_subc_limb (mp_limb_t *w, mp_limb_t x, mp_limb_t y)
|
| -{
|
| - mp_limb_t diff, cy;
|
| -
|
| - ASSERT_LIMB (x);
|
| - ASSERT_LIMB (y);
|
| -
|
| - diff = x - y;
|
| -#if GMP_NAIL_BITS == 0
|
| - *w = diff;
|
| - cy = (diff > x);
|
| -#else
|
| - *w = diff & GMP_NUMB_MASK;
|
| - cy = (diff >> GMP_NUMB_BITS) & 1;
|
| -#endif
|
| - return cy;
|
| -}
|
| -
|
| -/* set *w to x+y+c (where c is 0 or 1), return 0 or 1 carry */
|
| -mp_limb_t
|
| -adc (mp_limb_t *w, mp_limb_t x, mp_limb_t y, mp_limb_t c)
|
| -{
|
| - mp_limb_t r;
|
| -
|
| - ASSERT_LIMB (x);
|
| - ASSERT_LIMB (y);
|
| - ASSERT (c == 0 || c == 1);
|
| -
|
| - r = ref_addc_limb (w, x, y);
|
| - return r + ref_addc_limb (w, *w, c);
|
| -}
|
| -
|
| -/* set *w to x-y-c (where c is 0 or 1), return 0 or 1 borrow */
|
| -mp_limb_t
|
| -sbb (mp_limb_t *w, mp_limb_t x, mp_limb_t y, mp_limb_t c)
|
| -{
|
| - mp_limb_t r;
|
| -
|
| - ASSERT_LIMB (x);
|
| - ASSERT_LIMB (y);
|
| - ASSERT (c == 0 || c == 1);
|
| -
|
| - r = ref_subc_limb (w, x, y);
|
| - return r + ref_subc_limb (w, *w, c);
|
| -}
|
| -
|
| -
|
| -#define AORS_1(operation) \
|
| - { \
|
| - mp_limb_t i; \
|
| - \
|
| - ASSERT (refmpn_overlap_fullonly_p (rp, sp, size)); \
|
| - ASSERT (size >= 1); \
|
| - ASSERT_MPN (sp, size); \
|
| - ASSERT_LIMB (n); \
|
| - \
|
| - for (i = 0; i < size; i++) \
|
| - n = operation (&rp[i], sp[i], n); \
|
| - return n; \
|
| - }
|
| -
|
| -mp_limb_t
|
| -refmpn_add_1 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_limb_t n)
|
| -{
|
| - AORS_1 (ref_addc_limb);
|
| -}
|
| -mp_limb_t
|
| -refmpn_sub_1 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_limb_t n)
|
| -{
|
| - AORS_1 (ref_subc_limb);
|
| -}
|
| -
|
| -#define AORS_NC(operation) \
|
| - { \
|
| - mp_size_t i; \
|
| - \
|
| - ASSERT (refmpn_overlap_fullonly_two_p (rp, s1p, s2p, size)); \
|
| - ASSERT (carry == 0 || carry == 1); \
|
| - ASSERT (size >= 1); \
|
| - ASSERT_MPN (s1p, size); \
|
| - ASSERT_MPN (s2p, size); \
|
| - \
|
| - for (i = 0; i < size; i++) \
|
| - carry = operation (&rp[i], s1p[i], s2p[i], carry); \
|
| - return carry; \
|
| - }
|
| -
|
| -mp_limb_t
|
| -refmpn_add_nc (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size,
|
| - mp_limb_t carry)
|
| -{
|
| - AORS_NC (adc);
|
| -}
|
| -mp_limb_t
|
| -refmpn_sub_nc (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size,
|
| - mp_limb_t carry)
|
| -{
|
| - AORS_NC (sbb);
|
| -}
|
| -
|
| -
|
| -mp_limb_t
|
| -refmpn_add_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
|
| -{
|
| - return refmpn_add_nc (rp, s1p, s2p, size, CNST_LIMB(0));
|
| -}
|
| -mp_limb_t
|
| -refmpn_sub_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
|
| -{
|
| - return refmpn_sub_nc (rp, s1p, s2p, size, CNST_LIMB(0));
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_addlsh1_n (mp_ptr rp, mp_srcptr up, mp_srcptr vp, mp_size_t n)
|
| -{
|
| - mp_limb_t cy;
|
| - mp_ptr tp;
|
| -
|
| - ASSERT (refmpn_overlap_fullonly_two_p (rp, up, vp, n));
|
| - ASSERT (n >= 1);
|
| - ASSERT_MPN (up, n);
|
| - ASSERT_MPN (vp, n);
|
| -
|
| - tp = refmpn_malloc_limbs (n);
|
| - cy = refmpn_lshift (tp, vp, n, 1);
|
| - cy += refmpn_add_n (rp, up, tp, n);
|
| - free (tp);
|
| - return cy;
|
| -}
|
| -mp_limb_t
|
| -refmpn_sublsh1_n (mp_ptr rp, mp_srcptr up, mp_srcptr vp, mp_size_t n)
|
| -{
|
| - mp_limb_t cy;
|
| - mp_ptr tp;
|
| -
|
| - ASSERT (refmpn_overlap_fullonly_two_p (rp, up, vp, n));
|
| - ASSERT (n >= 1);
|
| - ASSERT_MPN (up, n);
|
| - ASSERT_MPN (vp, n);
|
| -
|
| - tp = refmpn_malloc_limbs (n);
|
| - cy = mpn_lshift (tp, vp, n, 1);
|
| - cy += mpn_sub_n (rp, up, tp, n);
|
| - free (tp);
|
| - return cy;
|
| -}
|
| -mp_limb_t
|
| -refmpn_rsh1add_n (mp_ptr rp, mp_srcptr up, mp_srcptr vp, mp_size_t n)
|
| -{
|
| - mp_limb_t cya, cys;
|
| -
|
| - ASSERT (refmpn_overlap_fullonly_two_p (rp, up, vp, n));
|
| - ASSERT (n >= 1);
|
| - ASSERT_MPN (up, n);
|
| - ASSERT_MPN (vp, n);
|
| -
|
| - cya = mpn_add_n (rp, up, vp, n);
|
| - cys = mpn_rshift (rp, rp, n, 1) >> (GMP_NUMB_BITS - 1);
|
| - rp[n - 1] |= cya << (GMP_NUMB_BITS - 1);
|
| - return cys;
|
| -}
|
| -mp_limb_t
|
| -refmpn_rsh1sub_n (mp_ptr rp, mp_srcptr up, mp_srcptr vp, mp_size_t n)
|
| -{
|
| - mp_limb_t cya, cys;
|
| -
|
| - ASSERT (refmpn_overlap_fullonly_two_p (rp, up, vp, n));
|
| - ASSERT (n >= 1);
|
| - ASSERT_MPN (up, n);
|
| - ASSERT_MPN (vp, n);
|
| -
|
| - cya = mpn_sub_n (rp, up, vp, n);
|
| - cys = mpn_rshift (rp, rp, n, 1) >> (GMP_NUMB_BITS - 1);
|
| - rp[n - 1] |= cya << (GMP_NUMB_BITS - 1);
|
| - return cys;
|
| -}
|
| -
|
| -/* Twos complement, return borrow. */
|
| -mp_limb_t
|
| -refmpn_neg_n (mp_ptr dst, mp_srcptr src, mp_size_t size)
|
| -{
|
| - mp_ptr zeros;
|
| - mp_limb_t ret;
|
| -
|
| - ASSERT (size >= 1);
|
| -
|
| - zeros = refmpn_malloc_limbs (size);
|
| - refmpn_fill (zeros, size, CNST_LIMB(0));
|
| - ret = refmpn_sub_n (dst, zeros, src, size);
|
| - free (zeros);
|
| - return ret;
|
| -}
|
| -
|
| -
|
| -#define AORS(aors_n, aors_1) \
|
| - { \
|
| - mp_limb_t c; \
|
| - ASSERT (s1size >= s2size); \
|
| - ASSERT (s2size >= 1); \
|
| - c = aors_n (rp, s1p, s2p, s2size); \
|
| - if (s1size-s2size != 0) \
|
| - c = aors_1 (rp+s2size, s1p+s2size, s1size-s2size, c); \
|
| - return c; \
|
| - }
|
| -mp_limb_t
|
| -refmpn_add (mp_ptr rp,
|
| - mp_srcptr s1p, mp_size_t s1size,
|
| - mp_srcptr s2p, mp_size_t s2size)
|
| -{
|
| - AORS (refmpn_add_n, refmpn_add_1);
|
| -}
|
| -mp_limb_t
|
| -refmpn_sub (mp_ptr rp,
|
| - mp_srcptr s1p, mp_size_t s1size,
|
| - mp_srcptr s2p, mp_size_t s2size)
|
| -{
|
| - AORS (refmpn_sub_n, refmpn_sub_1);
|
| -}
|
| -
|
| -
|
| -#define SHIFTHIGH(x) ((x) << BITS_PER_MP_LIMB/2)
|
| -#define SHIFTLOW(x) ((x) >> BITS_PER_MP_LIMB/2)
|
| -
|
| -#define LOWMASK (((mp_limb_t) 1 << BITS_PER_MP_LIMB/2)-1)
|
| -#define HIGHMASK SHIFTHIGH(LOWMASK)
|
| -
|
| -#define LOWPART(x) ((x) & LOWMASK)
|
| -#define HIGHPART(x) SHIFTLOW((x) & HIGHMASK)
|
| -
|
| -/* Set return:*lo to x*y, using full limbs not nails. */
|
| -mp_limb_t
|
| -refmpn_umul_ppmm (mp_limb_t *lo, mp_limb_t x, mp_limb_t y)
|
| -{
|
| - mp_limb_t hi, s;
|
| -
|
| - *lo = LOWPART(x) * LOWPART(y);
|
| - hi = HIGHPART(x) * HIGHPART(y);
|
| -
|
| - s = LOWPART(x) * HIGHPART(y);
|
| - hi += HIGHPART(s);
|
| - s = SHIFTHIGH(LOWPART(s));
|
| - *lo += s;
|
| - hi += (*lo < s);
|
| -
|
| - s = HIGHPART(x) * LOWPART(y);
|
| - hi += HIGHPART(s);
|
| - s = SHIFTHIGH(LOWPART(s));
|
| - *lo += s;
|
| - hi += (*lo < s);
|
| -
|
| - return hi;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_umul_ppmm_r (mp_limb_t x, mp_limb_t y, mp_limb_t *lo)
|
| -{
|
| - return refmpn_umul_ppmm (lo, x, y);
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_mul_1c (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_limb_t multiplier,
|
| - mp_limb_t carry)
|
| -{
|
| - mp_size_t i;
|
| - mp_limb_t hi, lo;
|
| -
|
| - ASSERT (refmpn_overlap_low_to_high_p (rp, sp, size));
|
| - ASSERT (size >= 1);
|
| - ASSERT_MPN (sp, size);
|
| - ASSERT_LIMB (multiplier);
|
| - ASSERT_LIMB (carry);
|
| -
|
| - multiplier <<= GMP_NAIL_BITS;
|
| - for (i = 0; i < size; i++)
|
| - {
|
| - hi = refmpn_umul_ppmm (&lo, sp[i], multiplier);
|
| - lo >>= GMP_NAIL_BITS;
|
| - ASSERT_NOCARRY (ref_addc_limb (&hi, hi, ref_addc_limb (&lo, lo, carry)));
|
| - rp[i] = lo;
|
| - carry = hi;
|
| - }
|
| - return carry;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_mul_1 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_limb_t multiplier)
|
| -{
|
| - return refmpn_mul_1c (rp, sp, size, multiplier, CNST_LIMB(0));
|
| -}
|
| -
|
| -
|
| -mp_limb_t
|
| -refmpn_mul_N (mp_ptr dst, mp_srcptr src, mp_size_t size,
|
| - mp_srcptr mult, mp_size_t msize)
|
| -{
|
| - mp_ptr src_copy;
|
| - mp_limb_t ret;
|
| - mp_size_t i;
|
| -
|
| - ASSERT (refmpn_overlap_fullonly_p (dst, src, size));
|
| - ASSERT (! refmpn_overlap_p (dst, size+msize-1, mult, msize));
|
| - ASSERT (size >= msize);
|
| - ASSERT_MPN (mult, msize);
|
| -
|
| - /* in case dst==src */
|
| - src_copy = refmpn_malloc_limbs (size);
|
| - refmpn_copyi (src_copy, src, size);
|
| - src = src_copy;
|
| -
|
| - dst[size] = refmpn_mul_1 (dst, src, size, mult[0]);
|
| - for (i = 1; i < msize-1; i++)
|
| - dst[size+i] = refmpn_addmul_1 (dst+i, src, size, mult[i]);
|
| - ret = refmpn_addmul_1 (dst+i, src, size, mult[i]);
|
| -
|
| - free (src_copy);
|
| - return ret;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_mul_2 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_srcptr mult)
|
| -{
|
| - return refmpn_mul_N (rp, sp, size, mult, (mp_size_t) 2);
|
| -}
|
| -mp_limb_t
|
| -refmpn_mul_3 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_srcptr mult)
|
| -{
|
| - return refmpn_mul_N (rp, sp, size, mult, (mp_size_t) 3);
|
| -}
|
| -mp_limb_t
|
| -refmpn_mul_4 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_srcptr mult)
|
| -{
|
| - return refmpn_mul_N (rp, sp, size, mult, (mp_size_t) 4);
|
| -}
|
| -
|
| -#define AORSMUL_1C(operation_n) \
|
| - { \
|
| - mp_ptr p; \
|
| - mp_limb_t ret; \
|
| - \
|
| - ASSERT (refmpn_overlap_fullonly_p (rp, sp, size)); \
|
| - \
|
| - p = refmpn_malloc_limbs (size); \
|
| - ret = refmpn_mul_1c (p, sp, size, multiplier, carry); \
|
| - ret += operation_n (rp, rp, p, size); \
|
| - \
|
| - free (p); \
|
| - return ret; \
|
| - }
|
| -
|
| -mp_limb_t
|
| -refmpn_addmul_1c (mp_ptr rp, mp_srcptr sp, mp_size_t size,
|
| - mp_limb_t multiplier, mp_limb_t carry)
|
| -{
|
| - AORSMUL_1C (refmpn_add_n);
|
| -}
|
| -mp_limb_t
|
| -refmpn_submul_1c (mp_ptr rp, mp_srcptr sp, mp_size_t size,
|
| - mp_limb_t multiplier, mp_limb_t carry)
|
| -{
|
| - AORSMUL_1C (refmpn_sub_n);
|
| -}
|
| -
|
| -
|
| -mp_limb_t
|
| -refmpn_addmul_1 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_limb_t multiplier)
|
| -{
|
| - return refmpn_addmul_1c (rp, sp, size, multiplier, CNST_LIMB(0));
|
| -}
|
| -mp_limb_t
|
| -refmpn_submul_1 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_limb_t multiplier)
|
| -{
|
| - return refmpn_submul_1c (rp, sp, size, multiplier, CNST_LIMB(0));
|
| -}
|
| -
|
| -
|
| -mp_limb_t
|
| -refmpn_addmul_N (mp_ptr dst, mp_srcptr src, mp_size_t size,
|
| - mp_srcptr mult, mp_size_t msize)
|
| -{
|
| - mp_ptr src_copy;
|
| - mp_limb_t ret;
|
| - mp_size_t i;
|
| -
|
| - ASSERT (dst == src || ! refmpn_overlap_p (dst, size+msize-1, src, size));
|
| - ASSERT (! refmpn_overlap_p (dst, size+msize-1, mult, msize));
|
| - ASSERT (size >= msize);
|
| - ASSERT_MPN (mult, msize);
|
| -
|
| - /* in case dst==src */
|
| - src_copy = refmpn_malloc_limbs (size);
|
| - refmpn_copyi (src_copy, src, size);
|
| - src = src_copy;
|
| -
|
| - for (i = 0; i < msize-1; i++)
|
| - dst[size+i] = refmpn_addmul_1 (dst+i, src, size, mult[i]);
|
| - ret = refmpn_addmul_1 (dst+i, src, size, mult[i]);
|
| -
|
| - free (src_copy);
|
| - return ret;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_addmul_2 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_srcptr mult)
|
| -{
|
| - return refmpn_addmul_N (rp, sp, size, mult, (mp_size_t) 2);
|
| -}
|
| -mp_limb_t
|
| -refmpn_addmul_3 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_srcptr mult)
|
| -{
|
| - return refmpn_addmul_N (rp, sp, size, mult, (mp_size_t) 3);
|
| -}
|
| -mp_limb_t
|
| -refmpn_addmul_4 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_srcptr mult)
|
| -{
|
| - return refmpn_addmul_N (rp, sp, size, mult, (mp_size_t) 4);
|
| -}
|
| -mp_limb_t
|
| -refmpn_addmul_5 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_srcptr mult)
|
| -{
|
| - return refmpn_addmul_N (rp, sp, size, mult, (mp_size_t) 5);
|
| -}
|
| -mp_limb_t
|
| -refmpn_addmul_6 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_srcptr mult)
|
| -{
|
| - return refmpn_addmul_N (rp, sp, size, mult, (mp_size_t) 6);
|
| -}
|
| -mp_limb_t
|
| -refmpn_addmul_7 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_srcptr mult)
|
| -{
|
| - return refmpn_addmul_N (rp, sp, size, mult, (mp_size_t) 7);
|
| -}
|
| -mp_limb_t
|
| -refmpn_addmul_8 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_srcptr mult)
|
| -{
|
| - return refmpn_addmul_N (rp, sp, size, mult, (mp_size_t) 8);
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_addsub_nc (mp_ptr r1p, mp_ptr r2p,
|
| - mp_srcptr s1p, mp_srcptr s2p, mp_size_t size,
|
| - mp_limb_t carry)
|
| -{
|
| - mp_ptr p;
|
| - mp_limb_t acy, scy;
|
| -
|
| - /* Destinations can't overlap. */
|
| - ASSERT (! refmpn_overlap_p (r1p, size, r2p, size));
|
| - ASSERT (refmpn_overlap_fullonly_two_p (r1p, s1p, s2p, size));
|
| - ASSERT (refmpn_overlap_fullonly_two_p (r2p, s1p, s2p, size));
|
| - ASSERT (size >= 1);
|
| -
|
| - /* in case r1p==s1p or r1p==s2p */
|
| - p = refmpn_malloc_limbs (size);
|
| -
|
| - acy = refmpn_add_nc (p, s1p, s2p, size, carry >> 1);
|
| - scy = refmpn_sub_nc (r2p, s1p, s2p, size, carry & 1);
|
| - refmpn_copyi (r1p, p, size);
|
| -
|
| - free (p);
|
| - return 2 * acy + scy;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_addsub_n (mp_ptr r1p, mp_ptr r2p,
|
| - mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
|
| -{
|
| - return refmpn_addsub_nc (r1p, r2p, s1p, s2p, size, CNST_LIMB(0));
|
| -}
|
| -
|
| -
|
| -/* Right shift hi,lo and return the low limb of the result.
|
| - Note a shift by BITS_PER_MP_LIMB isn't assumed to work (doesn't on x86). */
|
| -mp_limb_t
|
| -rshift_make (mp_limb_t hi, mp_limb_t lo, unsigned shift)
|
| -{
|
| - ASSERT (shift < GMP_NUMB_BITS);
|
| - if (shift == 0)
|
| - return lo;
|
| - else
|
| - return ((hi << (GMP_NUMB_BITS-shift)) | (lo >> shift)) & GMP_NUMB_MASK;
|
| -}
|
| -
|
| -/* Left shift hi,lo and return the high limb of the result.
|
| - Note a shift by BITS_PER_MP_LIMB isn't assumed to work (doesn't on x86). */
|
| -mp_limb_t
|
| -lshift_make (mp_limb_t hi, mp_limb_t lo, unsigned shift)
|
| -{
|
| - ASSERT (shift < GMP_NUMB_BITS);
|
| - if (shift == 0)
|
| - return hi;
|
| - else
|
| - return ((hi << shift) | (lo >> (GMP_NUMB_BITS-shift))) & GMP_NUMB_MASK;
|
| -}
|
| -
|
| -
|
| -mp_limb_t
|
| -refmpn_rshift (mp_ptr rp, mp_srcptr sp, mp_size_t size, unsigned shift)
|
| -{
|
| - mp_limb_t ret;
|
| - mp_size_t i;
|
| -
|
| - ASSERT (refmpn_overlap_low_to_high_p (rp, sp, size));
|
| - ASSERT (size >= 1);
|
| - ASSERT (shift >= 1 && shift < GMP_NUMB_BITS);
|
| - ASSERT_MPN (sp, size);
|
| -
|
| - ret = rshift_make (sp[0], CNST_LIMB(0), shift);
|
| -
|
| - for (i = 0; i < size-1; i++)
|
| - rp[i] = rshift_make (sp[i+1], sp[i], shift);
|
| -
|
| - rp[i] = rshift_make (CNST_LIMB(0), sp[i], shift);
|
| - return ret;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_lshift (mp_ptr rp, mp_srcptr sp, mp_size_t size, unsigned shift)
|
| -{
|
| - mp_limb_t ret;
|
| - mp_size_t i;
|
| -
|
| - ASSERT (refmpn_overlap_high_to_low_p (rp, sp, size));
|
| - ASSERT (size >= 1);
|
| - ASSERT (shift >= 1 && shift < GMP_NUMB_BITS);
|
| - ASSERT_MPN (sp, size);
|
| -
|
| - ret = lshift_make (CNST_LIMB(0), sp[size-1], shift);
|
| -
|
| - for (i = size-2; i >= 0; i--)
|
| - rp[i+1] = lshift_make (sp[i+1], sp[i], shift);
|
| -
|
| - rp[i+1] = lshift_make (sp[i+1], CNST_LIMB(0), shift);
|
| - return ret;
|
| -}
|
| -
|
| -
|
| -/* accepting shift==0 and doing a plain copyi or copyd in that case */
|
| -mp_limb_t
|
| -refmpn_rshift_or_copy (mp_ptr rp, mp_srcptr sp, mp_size_t size, unsigned shift)
|
| -{
|
| - if (shift == 0)
|
| - {
|
| - refmpn_copyi (rp, sp, size);
|
| - return 0;
|
| - }
|
| - else
|
| - {
|
| - return refmpn_rshift (rp, sp, size, shift);
|
| - }
|
| -}
|
| -mp_limb_t
|
| -refmpn_lshift_or_copy (mp_ptr rp, mp_srcptr sp, mp_size_t size, unsigned shift)
|
| -{
|
| - if (shift == 0)
|
| - {
|
| - refmpn_copyd (rp, sp, size);
|
| - return 0;
|
| - }
|
| - else
|
| - {
|
| - return refmpn_lshift (rp, sp, size, shift);
|
| - }
|
| -}
|
| -
|
| -/* accepting size==0 too */
|
| -mp_limb_t
|
| -refmpn_rshift_or_copy_any (mp_ptr rp, mp_srcptr sp, mp_size_t size,
|
| - unsigned shift)
|
| -{
|
| - return (size == 0 ? 0 : refmpn_rshift_or_copy (rp, sp, size, shift));
|
| -}
|
| -mp_limb_t
|
| -refmpn_lshift_or_copy_any (mp_ptr rp, mp_srcptr sp, mp_size_t size,
|
| - unsigned shift)
|
| -{
|
| - return (size == 0 ? 0 : refmpn_lshift_or_copy (rp, sp, size, shift));
|
| -}
|
| -
|
| -/* Divide h,l by d, return quotient, store remainder to *rp.
|
| - Operates on full limbs, not nails.
|
| - Must have h < d.
|
| - __udiv_qrnnd_c isn't simple, and it's a bit slow, but it works. */
|
| -mp_limb_t
|
| -refmpn_udiv_qrnnd (mp_limb_t *rp, mp_limb_t h, mp_limb_t l, mp_limb_t d)
|
| -{
|
| - mp_limb_t q, r;
|
| - int n;
|
| -
|
| - ASSERT (d != 0);
|
| - ASSERT (h < d);
|
| -
|
| -#if 0
|
| - udiv_qrnnd (q, r, h, l, d);
|
| - *rp = r;
|
| - return q;
|
| -#endif
|
| -
|
| - n = refmpn_count_leading_zeros (d);
|
| - d <<= n;
|
| -
|
| - if (n != 0)
|
| - {
|
| - h = (h << n) | (l >> (GMP_LIMB_BITS - n));
|
| - l <<= n;
|
| - }
|
| -
|
| - __udiv_qrnnd_c (q, r, h, l, d);
|
| - r >>= n;
|
| - *rp = r;
|
| - return q;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_udiv_qrnnd_r (mp_limb_t h, mp_limb_t l, mp_limb_t d, mp_limb_t *rp)
|
| -{
|
| - return refmpn_udiv_qrnnd (rp, h, l, d);
|
| -}
|
| -
|
| -/* This little subroutine avoids some bad code generation from i386 gcc 3.0
|
| - -fPIC -O2 -fomit-frame-pointer (%ebp being used uninitialized). */
|
| -static mp_limb_t
|
| -refmpn_divmod_1c_workaround (mp_ptr rp, mp_srcptr sp, mp_size_t size,
|
| - mp_limb_t divisor, mp_limb_t carry)
|
| -{
|
| - mp_size_t i;
|
| - mp_limb_t rem[1];
|
| - for (i = size-1; i >= 0; i--)
|
| - {
|
| - rp[i] = refmpn_udiv_qrnnd (rem, carry,
|
| - sp[i] << GMP_NAIL_BITS,
|
| - divisor << GMP_NAIL_BITS);
|
| - carry = *rem >> GMP_NAIL_BITS;
|
| - }
|
| - return carry;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_divmod_1c (mp_ptr rp, mp_srcptr sp, mp_size_t size,
|
| - mp_limb_t divisor, mp_limb_t carry)
|
| -{
|
| - mp_ptr sp_orig;
|
| - mp_ptr prod;
|
| - mp_limb_t carry_orig;
|
| -
|
| - ASSERT (refmpn_overlap_fullonly_p (rp, sp, size));
|
| - ASSERT (size >= 0);
|
| - ASSERT (carry < divisor);
|
| - ASSERT_MPN (sp, size);
|
| - ASSERT_LIMB (divisor);
|
| - ASSERT_LIMB (carry);
|
| -
|
| - if (size == 0)
|
| - return carry;
|
| -
|
| - sp_orig = refmpn_memdup_limbs (sp, size);
|
| - prod = refmpn_malloc_limbs (size);
|
| - carry_orig = carry;
|
| -
|
| - carry = refmpn_divmod_1c_workaround (rp, sp, size, divisor, carry);
|
| -
|
| - /* check by multiplying back */
|
| -#if 0
|
| - printf ("size=%ld divisor=0x%lX carry=0x%lX remainder=0x%lX\n",
|
| - size, divisor, carry_orig, carry);
|
| - mpn_trace("s",sp_copy,size);
|
| - mpn_trace("r",rp,size);
|
| - printf ("mul_1c %lX\n", refmpn_mul_1c (prod, rp, size, divisor, carry));
|
| - mpn_trace("p",prod,size);
|
| -#endif
|
| - ASSERT (refmpn_mul_1c (prod, rp, size, divisor, carry) == carry_orig);
|
| - ASSERT (refmpn_cmp (prod, sp_orig, size) == 0);
|
| - free (sp_orig);
|
| - free (prod);
|
| -
|
| - return carry;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_divmod_1 (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_limb_t divisor)
|
| -{
|
| - return refmpn_divmod_1c (rp, sp, size, divisor, CNST_LIMB(0));
|
| -}
|
| -
|
| -
|
| -mp_limb_t
|
| -refmpn_mod_1c (mp_srcptr sp, mp_size_t size, mp_limb_t divisor,
|
| - mp_limb_t carry)
|
| -{
|
| - mp_ptr p = refmpn_malloc_limbs (size);
|
| - carry = refmpn_divmod_1c (p, sp, size, divisor, carry);
|
| - free (p);
|
| - return carry;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_mod_1 (mp_srcptr sp, mp_size_t size, mp_limb_t divisor)
|
| -{
|
| - return refmpn_mod_1c (sp, size, divisor, CNST_LIMB(0));
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_preinv_mod_1 (mp_srcptr sp, mp_size_t size, mp_limb_t divisor,
|
| - mp_limb_t inverse)
|
| -{
|
| - ASSERT (divisor & GMP_NUMB_HIGHBIT);
|
| - ASSERT (inverse == refmpn_invert_limb (divisor));
|
| - return refmpn_mod_1 (sp, size, divisor);
|
| -}
|
| -
|
| -/* This implementation will be rather slow, but has the advantage of being
|
| - in a different style than the libgmp versions. */
|
| -mp_limb_t
|
| -refmpn_mod_34lsub1 (mp_srcptr p, mp_size_t n)
|
| -{
|
| - ASSERT ((GMP_NUMB_BITS % 4) == 0);
|
| - return mpn_mod_1 (p, n, (CNST_LIMB(1) << (3 * GMP_NUMB_BITS / 4)) - 1);
|
| -}
|
| -
|
| -
|
| -mp_limb_t
|
| -refmpn_divrem_1c (mp_ptr rp, mp_size_t xsize,
|
| - mp_srcptr sp, mp_size_t size, mp_limb_t divisor,
|
| - mp_limb_t carry)
|
| -{
|
| - mp_ptr z;
|
| -
|
| - z = refmpn_malloc_limbs (xsize);
|
| - refmpn_fill (z, xsize, CNST_LIMB(0));
|
| -
|
| - carry = refmpn_divmod_1c (rp+xsize, sp, size, divisor, carry);
|
| - carry = refmpn_divmod_1c (rp, z, xsize, divisor, carry);
|
| -
|
| - free (z);
|
| - return carry;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_divrem_1 (mp_ptr rp, mp_size_t xsize,
|
| - mp_srcptr sp, mp_size_t size, mp_limb_t divisor)
|
| -{
|
| - return refmpn_divrem_1c (rp, xsize, sp, size, divisor, CNST_LIMB(0));
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_preinv_divrem_1 (mp_ptr rp, mp_size_t xsize,
|
| - mp_srcptr sp, mp_size_t size,
|
| - mp_limb_t divisor, mp_limb_t inverse, unsigned shift)
|
| -{
|
| - ASSERT (size >= 0);
|
| - ASSERT (shift == refmpn_count_leading_zeros (divisor));
|
| - ASSERT (inverse == refmpn_invert_limb (divisor << shift));
|
| -
|
| - return refmpn_divrem_1 (rp, xsize, sp, size, divisor);
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_divrem_2 (mp_ptr qp, mp_size_t qxn,
|
| - mp_ptr np, mp_size_t nn,
|
| - mp_srcptr dp)
|
| -{
|
| - mp_ptr tp;
|
| - mp_limb_t qh;
|
| -
|
| - tp = refmpn_malloc_limbs (nn + qxn);
|
| - refmpn_zero (tp, qxn);
|
| - refmpn_copyi (tp + qxn, np, nn);
|
| - qh = refmpn_sb_divrem_mn (qp, tp, nn + qxn, dp, 2);
|
| - refmpn_copyi (np, tp, 2);
|
| - free (tp);
|
| - return qh;
|
| -}
|
| -
|
| -/* Inverse is floor((b*(b-d)-1) / d), per division by invariant integers
|
| - paper, figure 8.1 m', where b=2^BITS_PER_MP_LIMB. Note that -d-1 < d
|
| - since d has the high bit set. */
|
| -
|
| -mp_limb_t
|
| -refmpn_invert_limb (mp_limb_t d)
|
| -{
|
| - mp_limb_t r;
|
| - ASSERT (d & GMP_LIMB_HIGHBIT);
|
| - return refmpn_udiv_qrnnd (&r, -d-1, MP_LIMB_T_MAX, d);
|
| -}
|
| -
|
| -
|
| -/* The aim is to produce a dst quotient and return a remainder c, satisfying
|
| - c*b^n + src-i == 3*dst, where i is the incoming carry.
|
| -
|
| - Some value c==0, c==1 or c==2 will satisfy, so just try each.
|
| -
|
| - If GMP_NUMB_BITS is even then 2^GMP_NUMB_BITS==1mod3 and a non-zero
|
| - remainder from the first division attempt determines the correct
|
| - remainder (3-c), but don't bother with that, since we can't guarantee
|
| - anything about GMP_NUMB_BITS when using nails.
|
| -
|
| - If the initial src-i produces a borrow then refmpn_sub_1 leaves a twos
|
| - complement negative, ie. b^n+a-i, and the calculation produces c1
|
| - satisfying c1*b^n + b^n+src-i == 3*dst, from which clearly c=c1+1. This
|
| - means it's enough to just add any borrow back at the end.
|
| -
|
| - A borrow only occurs when a==0 or a==1, and, by the same reasoning as in
|
| - mpn/generic/diveby3.c, the c1 that results in those cases will only be 0
|
| - or 1 respectively, so with 1 added the final return value is still in the
|
| - prescribed range 0 to 2. */
|
| -
|
| -mp_limb_t
|
| -refmpn_divexact_by3c (mp_ptr rp, mp_srcptr sp, mp_size_t size, mp_limb_t carry)
|
| -{
|
| - mp_ptr spcopy;
|
| - mp_limb_t c, cs;
|
| -
|
| - ASSERT (refmpn_overlap_fullonly_p (rp, sp, size));
|
| - ASSERT (size >= 1);
|
| - ASSERT (carry <= 2);
|
| - ASSERT_MPN (sp, size);
|
| -
|
| - spcopy = refmpn_malloc_limbs (size);
|
| - cs = refmpn_sub_1 (spcopy, sp, size, carry);
|
| -
|
| - for (c = 0; c <= 2; c++)
|
| - if (refmpn_divmod_1c (rp, spcopy, size, CNST_LIMB(3), c) == 0)
|
| - goto done;
|
| - ASSERT_FAIL (no value of c satisfies);
|
| -
|
| - done:
|
| - c += cs;
|
| - ASSERT (c <= 2);
|
| -
|
| - free (spcopy);
|
| - return c;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_divexact_by3 (mp_ptr rp, mp_srcptr sp, mp_size_t size)
|
| -{
|
| - return refmpn_divexact_by3c (rp, sp, size, CNST_LIMB(0));
|
| -}
|
| -
|
| -
|
| -/* The same as mpn/generic/mul_basecase.c, but using refmpn functions. */
|
| -void
|
| -refmpn_mul_basecase (mp_ptr prodp,
|
| - mp_srcptr up, mp_size_t usize,
|
| - mp_srcptr vp, mp_size_t vsize)
|
| -{
|
| - mp_size_t i;
|
| -
|
| - ASSERT (! refmpn_overlap_p (prodp, usize+vsize, up, usize));
|
| - ASSERT (! refmpn_overlap_p (prodp, usize+vsize, vp, vsize));
|
| - ASSERT (usize >= vsize);
|
| - ASSERT (vsize >= 1);
|
| - ASSERT_MPN (up, usize);
|
| - ASSERT_MPN (vp, vsize);
|
| -
|
| - prodp[usize] = refmpn_mul_1 (prodp, up, usize, vp[0]);
|
| - for (i = 1; i < vsize; i++)
|
| - prodp[usize+i] = refmpn_addmul_1 (prodp+i, up, usize, vp[i]);
|
| -}
|
| -
|
| -void
|
| -refmpn_mul_n (mp_ptr prodp, mp_srcptr up, mp_srcptr vp, mp_size_t size)
|
| -{
|
| - refmpn_mul_basecase (prodp, up, size, vp, size);
|
| -}
|
| -
|
| -void
|
| -refmpn_sqr (mp_ptr dst, mp_srcptr src, mp_size_t size)
|
| -{
|
| - refmpn_mul_basecase (dst, src, size, src, size);
|
| -}
|
| -
|
| -/* Allowing usize<vsize, usize==0 or vsize==0. */
|
| -void
|
| -refmpn_mul_any (mp_ptr prodp,
|
| - mp_srcptr up, mp_size_t usize,
|
| - mp_srcptr vp, mp_size_t vsize)
|
| -{
|
| - ASSERT (! refmpn_overlap_p (prodp, usize+vsize, up, usize));
|
| - ASSERT (! refmpn_overlap_p (prodp, usize+vsize, vp, vsize));
|
| - ASSERT (usize >= 0);
|
| - ASSERT (vsize >= 0);
|
| - ASSERT_MPN (up, usize);
|
| - ASSERT_MPN (vp, vsize);
|
| -
|
| - if (usize == 0)
|
| - {
|
| - refmpn_fill (prodp, vsize, CNST_LIMB(0));
|
| - return;
|
| - }
|
| -
|
| - if (vsize == 0)
|
| - {
|
| - refmpn_fill (prodp, usize, CNST_LIMB(0));
|
| - return;
|
| - }
|
| -
|
| - if (usize >= vsize)
|
| - refmpn_mul_basecase (prodp, up, usize, vp, vsize);
|
| - else
|
| - refmpn_mul_basecase (prodp, vp, vsize, up, usize);
|
| -}
|
| -
|
| -
|
| -mp_limb_t
|
| -refmpn_gcd_1 (mp_srcptr xp, mp_size_t xsize, mp_limb_t y)
|
| -{
|
| - mp_limb_t x;
|
| - int twos;
|
| -
|
| - ASSERT (y != 0);
|
| - ASSERT (! refmpn_zero_p (xp, xsize));
|
| - ASSERT_MPN (xp, xsize);
|
| - ASSERT_LIMB (y);
|
| -
|
| - x = refmpn_mod_1 (xp, xsize, y);
|
| - if (x == 0)
|
| - return y;
|
| -
|
| - twos = 0;
|
| - while ((x & 1) == 0 && (y & 1) == 0)
|
| - {
|
| - x >>= 1;
|
| - y >>= 1;
|
| - twos++;
|
| - }
|
| -
|
| - for (;;)
|
| - {
|
| - while ((x & 1) == 0) x >>= 1;
|
| - while ((y & 1) == 0) y >>= 1;
|
| -
|
| - if (x < y)
|
| - MP_LIMB_T_SWAP (x, y);
|
| -
|
| - x -= y;
|
| - if (x == 0)
|
| - break;
|
| - }
|
| -
|
| - return y << twos;
|
| -}
|
| -
|
| -
|
| -/* Based on the full limb x, not nails. */
|
| -unsigned
|
| -refmpn_count_leading_zeros (mp_limb_t x)
|
| -{
|
| - unsigned n = 0;
|
| -
|
| - ASSERT (x != 0);
|
| -
|
| - while ((x & GMP_LIMB_HIGHBIT) == 0)
|
| - {
|
| - x <<= 1;
|
| - n++;
|
| - }
|
| - return n;
|
| -}
|
| -
|
| -/* Full limbs allowed, not limited to nails. */
|
| -unsigned
|
| -refmpn_count_trailing_zeros (mp_limb_t x)
|
| -{
|
| - unsigned n = 0;
|
| -
|
| - ASSERT (x != 0);
|
| - ASSERT_LIMB (x);
|
| -
|
| - while ((x & 1) == 0)
|
| - {
|
| - x >>= 1;
|
| - n++;
|
| - }
|
| - return n;
|
| -}
|
| -
|
| -/* Strip factors of two (low zero bits) from {p,size} by right shifting.
|
| - The return value is the number of twos stripped. */
|
| -mp_size_t
|
| -refmpn_strip_twos (mp_ptr p, mp_size_t size)
|
| -{
|
| - mp_size_t limbs;
|
| - unsigned shift;
|
| -
|
| - ASSERT (size >= 1);
|
| - ASSERT (! refmpn_zero_p (p, size));
|
| - ASSERT_MPN (p, size);
|
| -
|
| - for (limbs = 0; p[0] == 0; limbs++)
|
| - {
|
| - refmpn_copyi (p, p+1, size-1);
|
| - p[size-1] = 0;
|
| - }
|
| -
|
| - shift = refmpn_count_trailing_zeros (p[0]);
|
| - if (shift)
|
| - refmpn_rshift (p, p, size, shift);
|
| -
|
| - return limbs*GMP_NUMB_BITS + shift;
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_gcd (mp_ptr gp, mp_ptr xp, mp_size_t xsize, mp_ptr yp, mp_size_t ysize)
|
| -{
|
| - int cmp;
|
| -
|
| - ASSERT (ysize >= 1);
|
| - ASSERT (xsize >= ysize);
|
| - ASSERT ((xp[0] & 1) != 0);
|
| - ASSERT ((yp[0] & 1) != 0);
|
| - /* ASSERT (xp[xsize-1] != 0); */ /* don't think x needs to be odd */
|
| - ASSERT (yp[ysize-1] != 0);
|
| - ASSERT (refmpn_overlap_fullonly_p (gp, xp, xsize));
|
| - ASSERT (refmpn_overlap_fullonly_p (gp, yp, ysize));
|
| - ASSERT (! refmpn_overlap_p (xp, xsize, yp, ysize));
|
| - if (xsize == ysize)
|
| - ASSERT (refmpn_msbone (xp[xsize-1]) >= refmpn_msbone (yp[ysize-1]));
|
| - ASSERT_MPN (xp, xsize);
|
| - ASSERT_MPN (yp, ysize);
|
| -
|
| - refmpn_strip_twos (xp, xsize);
|
| - MPN_NORMALIZE (xp, xsize);
|
| - MPN_NORMALIZE (yp, ysize);
|
| -
|
| - for (;;)
|
| - {
|
| - cmp = refmpn_cmp_twosizes (xp, xsize, yp, ysize);
|
| - if (cmp == 0)
|
| - break;
|
| - if (cmp < 0)
|
| - MPN_PTR_SWAP (xp,xsize, yp,ysize);
|
| -
|
| - ASSERT_NOCARRY (refmpn_sub (xp, xp, xsize, yp, ysize));
|
| -
|
| - refmpn_strip_twos (xp, xsize);
|
| - MPN_NORMALIZE (xp, xsize);
|
| - }
|
| -
|
| - refmpn_copyi (gp, xp, xsize);
|
| - return xsize;
|
| -}
|
| -
|
| -unsigned long
|
| -ref_popc_limb (mp_limb_t src)
|
| -{
|
| - unsigned long count;
|
| - int i;
|
| -
|
| - count = 0;
|
| - for (i = 0; i < GMP_LIMB_BITS; i++)
|
| - {
|
| - count += (src & 1);
|
| - src >>= 1;
|
| - }
|
| - return count;
|
| -}
|
| -
|
| -unsigned long
|
| -refmpn_popcount (mp_srcptr sp, mp_size_t size)
|
| -{
|
| - unsigned long count = 0;
|
| - mp_size_t i;
|
| -
|
| - ASSERT (size >= 0);
|
| - ASSERT_MPN (sp, size);
|
| -
|
| - for (i = 0; i < size; i++)
|
| - count += ref_popc_limb (sp[i]);
|
| - return count;
|
| -}
|
| -
|
| -unsigned long
|
| -refmpn_hamdist (mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
|
| -{
|
| - mp_ptr d;
|
| - unsigned long count;
|
| -
|
| - ASSERT (size >= 0);
|
| - ASSERT_MPN (s1p, size);
|
| - ASSERT_MPN (s2p, size);
|
| -
|
| - if (size == 0)
|
| - return 0;
|
| -
|
| - d = refmpn_malloc_limbs (size);
|
| - refmpn_xor_n (d, s1p, s2p, size);
|
| - count = refmpn_popcount (d, size);
|
| - free (d);
|
| - return count;
|
| -}
|
| -
|
| -
|
| -/* set r to a%d */
|
| -void
|
| -refmpn_mod2 (mp_limb_t r[2], const mp_limb_t a[2], const mp_limb_t d[2])
|
| -{
|
| - mp_limb_t D[2];
|
| - int n;
|
| -
|
| - ASSERT (! refmpn_overlap_p (r, (mp_size_t) 2, d, (mp_size_t) 2));
|
| - ASSERT_MPN (a, 2);
|
| - ASSERT_MPN (d, 2);
|
| -
|
| - D[1] = d[1], D[0] = d[0];
|
| - r[1] = a[1], r[0] = a[0];
|
| - n = 0;
|
| -
|
| - for (;;)
|
| - {
|
| - if (D[1] & GMP_NUMB_HIGHBIT)
|
| - break;
|
| - if (refmpn_cmp (r, D, (mp_size_t) 2) <= 0)
|
| - break;
|
| - refmpn_lshift (D, D, (mp_size_t) 2, 1);
|
| - n++;
|
| - ASSERT (n <= GMP_NUMB_BITS);
|
| - }
|
| -
|
| - while (n >= 0)
|
| - {
|
| - if (refmpn_cmp (r, D, (mp_size_t) 2) >= 0)
|
| - ASSERT_NOCARRY (refmpn_sub_n (r, r, D, (mp_size_t) 2));
|
| - refmpn_rshift (D, D, (mp_size_t) 2, 1);
|
| - n--;
|
| - }
|
| -
|
| - ASSERT (refmpn_cmp (r, d, (mp_size_t) 2) < 0);
|
| -}
|
| -
|
| -
|
| -
|
| -/* Similar to mpn/generic/sb_divrem_mn.c, but somewhat simplified, in
|
| - particular the trial quotient is allowed to be 2 too big. */
|
| -mp_limb_t
|
| -refmpn_sb_divrem_mn (mp_ptr qp,
|
| - mp_ptr np, mp_size_t nsize,
|
| - mp_srcptr dp, mp_size_t dsize)
|
| -{
|
| - mp_limb_t retval = 0;
|
| - mp_size_t i;
|
| - mp_limb_t d1 = dp[dsize-1];
|
| - mp_ptr np_orig = refmpn_memdup_limbs (np, nsize);
|
| -
|
| - ASSERT (nsize >= dsize);
|
| - /* ASSERT (dsize > 2); */
|
| - ASSERT (dsize >= 2);
|
| - ASSERT (dp[dsize-1] & GMP_NUMB_HIGHBIT);
|
| - ASSERT (! refmpn_overlap_p (qp, nsize-dsize, np, nsize) || qp+dsize >= np);
|
| - ASSERT_MPN (np, nsize);
|
| - ASSERT_MPN (dp, dsize);
|
| -
|
| - i = nsize-dsize;
|
| - if (refmpn_cmp (np+i, dp, dsize) >= 0)
|
| - {
|
| - ASSERT_NOCARRY (refmpn_sub_n (np+i, np+i, dp, dsize));
|
| - retval = 1;
|
| - }
|
| -
|
| - for (i--; i >= 0; i--)
|
| - {
|
| - mp_limb_t n0 = np[i+dsize];
|
| - mp_limb_t n1 = np[i+dsize-1];
|
| - mp_limb_t q, dummy_r;
|
| -
|
| - ASSERT (n0 <= d1);
|
| - if (n0 == d1)
|
| - q = GMP_NUMB_MAX;
|
| - else
|
| - q = refmpn_udiv_qrnnd (&dummy_r, n0, n1 << GMP_NAIL_BITS,
|
| - d1 << GMP_NAIL_BITS);
|
| -
|
| - n0 -= refmpn_submul_1 (np+i, dp, dsize, q);
|
| - ASSERT (n0 == 0 || n0 == MP_LIMB_T_MAX);
|
| - if (n0)
|
| - {
|
| - q--;
|
| - if (! refmpn_add_n (np+i, np+i, dp, dsize))
|
| - {
|
| - q--;
|
| - ASSERT_CARRY (refmpn_add_n (np+i, np+i, dp, dsize));
|
| - }
|
| - }
|
| - np[i+dsize] = 0;
|
| -
|
| - qp[i] = q;
|
| - }
|
| -
|
| - /* remainder < divisor */
|
| -#if 0 /* ASSERT triggers gcc 4.2.1 bug */
|
| - ASSERT (refmpn_cmp (np, dp, dsize) < 0);
|
| -#endif
|
| -
|
| - /* multiply back to original */
|
| - {
|
| - mp_ptr mp = refmpn_malloc_limbs (nsize);
|
| -
|
| - refmpn_mul_any (mp, qp, nsize-dsize, dp, dsize);
|
| - if (retval)
|
| - ASSERT_NOCARRY (refmpn_add_n (mp+nsize-dsize,mp+nsize-dsize, dp, dsize));
|
| - ASSERT_NOCARRY (refmpn_add (mp, mp, nsize, np, dsize));
|
| - ASSERT (refmpn_cmp (mp, np_orig, nsize) == 0);
|
| -
|
| - free (mp);
|
| - }
|
| -
|
| - free (np_orig);
|
| - return retval;
|
| -}
|
| -
|
| -/* Similar to mpn/generic/sb_divrem_mn.c, but somewhat simplified, in
|
| - particular the trial quotient is allowed to be 2 too big. */
|
| -void
|
| -refmpn_tdiv_qr (mp_ptr qp, mp_ptr rp, mp_size_t qxn,
|
| - mp_ptr np, mp_size_t nsize,
|
| - mp_srcptr dp, mp_size_t dsize)
|
| -{
|
| - ASSERT (qxn == 0);
|
| - ASSERT_MPN (np, nsize);
|
| - ASSERT_MPN (dp, dsize);
|
| - ASSERT (dsize > 0);
|
| - ASSERT (dp[dsize-1] != 0);
|
| -
|
| - if (dsize == 1)
|
| - {
|
| - rp[0] = refmpn_divmod_1 (qp, np, nsize, dp[0]);
|
| - return;
|
| - }
|
| - else
|
| - {
|
| - mp_ptr n2p = refmpn_malloc_limbs (nsize+1);
|
| - mp_ptr d2p = refmpn_malloc_limbs (dsize);
|
| - int norm = refmpn_count_leading_zeros (dp[dsize-1]) - GMP_NAIL_BITS;
|
| -
|
| - n2p[nsize] = refmpn_lshift_or_copy (n2p, np, nsize, norm);
|
| - ASSERT_NOCARRY (refmpn_lshift_or_copy (d2p, dp, dsize, norm));
|
| -
|
| - refmpn_sb_divrem_mn (qp, n2p, nsize+1, d2p, dsize);
|
| - refmpn_rshift_or_copy (rp, n2p, dsize, norm);
|
| -
|
| - /* ASSERT (refmpn_zero_p (tp+dsize, nsize-dsize)); */
|
| - free (n2p);
|
| - free (d2p);
|
| - }
|
| -}
|
| -
|
| -void
|
| -refmpn_redc_1 (mp_ptr rp, mp_ptr up, mp_srcptr mp, mp_size_t n, mp_limb_t invm)
|
| -{
|
| - mp_size_t j;
|
| - mp_limb_t cy;
|
| -
|
| - ASSERT_MPN (up, 2*n);
|
| - /* ASSERT about directed overlap rp, up */
|
| - /* ASSERT about overlap rp, mp */
|
| - /* ASSERT about overlap up, mp */
|
| -
|
| - for (j = n - 1; j >= 0; j--)
|
| - {
|
| - up[0] = mpn_addmul_1 (up, mp, n, (up[0] * invm) & GMP_NUMB_MASK);
|
| - up++;
|
| - }
|
| - cy = mpn_add_n (rp, up, up - n, n);
|
| - if (cy != 0)
|
| - mpn_sub_n (rp, rp, mp, n);
|
| -}
|
| -
|
| -size_t
|
| -refmpn_get_str (unsigned char *dst, int base, mp_ptr src, mp_size_t size)
|
| -{
|
| - unsigned char *d;
|
| - size_t dsize;
|
| -
|
| - ASSERT (size >= 0);
|
| - ASSERT (base >= 2);
|
| - ASSERT (base < numberof (__mp_bases));
|
| - ASSERT (size == 0 || src[size-1] != 0);
|
| - ASSERT_MPN (src, size);
|
| -
|
| - MPN_SIZEINBASE (dsize, src, size, base);
|
| - ASSERT (dsize >= 1);
|
| - ASSERT (! byte_overlap_p (dst, (mp_size_t) dsize, src, size * BYTES_PER_MP_LIMB));
|
| -
|
| - if (size == 0)
|
| - {
|
| - dst[0] = 0;
|
| - return 1;
|
| - }
|
| -
|
| - /* don't clobber input for power of 2 bases */
|
| - if (POW2_P (base))
|
| - src = refmpn_memdup_limbs (src, size);
|
| -
|
| - d = dst + dsize;
|
| - do
|
| - {
|
| - d--;
|
| - ASSERT (d >= dst);
|
| - *d = refmpn_divrem_1 (src, (mp_size_t) 0, src, size, (mp_limb_t) base);
|
| - size -= (src[size-1] == 0);
|
| - }
|
| - while (size != 0);
|
| -
|
| - /* Move result back and decrement dsize if we didn't generate
|
| - the maximum possible digits. */
|
| - if (d != dst)
|
| - {
|
| - size_t i;
|
| - dsize -= d - dst;
|
| - for (i = 0; i < dsize; i++)
|
| - dst[i] = d[i];
|
| - }
|
| -
|
| - if (POW2_P (base))
|
| - free (src);
|
| -
|
| - return dsize;
|
| -}
|
| -
|
| -
|
| -mp_limb_t
|
| -ref_bswap_limb (mp_limb_t src)
|
| -{
|
| - mp_limb_t dst;
|
| - int i;
|
| -
|
| - dst = 0;
|
| - for (i = 0; i < BYTES_PER_MP_LIMB; i++)
|
| - {
|
| - dst = (dst << 8) + (src & 0xFF);
|
| - src >>= 8;
|
| - }
|
| - return dst;
|
| -}
|
| -
|
| -
|
| -/* These random functions are mostly for transitional purposes while adding
|
| - nail support, since they're independent of the normal mpn routines. They
|
| - can probably be removed when those normal routines are reliable, though
|
| - perhaps something independent would still be useful at times. */
|
| -
|
| -#if BITS_PER_MP_LIMB == 32
|
| -#define RAND_A CNST_LIMB(0x29CF535)
|
| -#endif
|
| -#if BITS_PER_MP_LIMB == 64
|
| -#define RAND_A CNST_LIMB(0xBAECD515DAF0B49D)
|
| -#endif
|
| -
|
| -mp_limb_t refmpn_random_seed;
|
| -
|
| -mp_limb_t
|
| -refmpn_random_half (void)
|
| -{
|
| - refmpn_random_seed = refmpn_random_seed * RAND_A + 1;
|
| - return (refmpn_random_seed >> BITS_PER_MP_LIMB/2);
|
| -}
|
| -
|
| -mp_limb_t
|
| -refmpn_random_limb (void)
|
| -{
|
| - return ((refmpn_random_half () << (BITS_PER_MP_LIMB/2))
|
| - | refmpn_random_half ()) & GMP_NUMB_MASK;
|
| -}
|
| -
|
| -void
|
| -refmpn_random (mp_ptr ptr, mp_size_t size)
|
| -{
|
| - mp_size_t i;
|
| - if (GMP_NAIL_BITS == 0)
|
| - {
|
| - mpn_random (ptr, size);
|
| - return;
|
| - }
|
| -
|
| - for (i = 0; i < size; i++)
|
| - ptr[i] = refmpn_random_limb ();
|
| -}
|
| -
|
| -void
|
| -refmpn_random2 (mp_ptr ptr, mp_size_t size)
|
| -{
|
| - mp_size_t i;
|
| - mp_limb_t bit, mask, limb;
|
| - int run;
|
| -
|
| - if (GMP_NAIL_BITS == 0)
|
| - {
|
| - mpn_random2 (ptr, size);
|
| - return;
|
| - }
|
| -
|
| -#define RUN_MODULUS 32
|
| -
|
| - /* start with ones at a random pos in the high limb */
|
| - bit = CNST_LIMB(1) << (refmpn_random_half () % GMP_NUMB_BITS);
|
| - mask = 0;
|
| - run = 0;
|
| -
|
| - for (i = size-1; i >= 0; i--)
|
| - {
|
| - limb = 0;
|
| - do
|
| - {
|
| - if (run == 0)
|
| - {
|
| - run = (refmpn_random_half () % RUN_MODULUS) + 1;
|
| - mask = ~mask;
|
| - }
|
| -
|
| - limb |= (bit & mask);
|
| - bit >>= 1;
|
| - run--;
|
| - }
|
| - while (bit != 0);
|
| -
|
| - ptr[i] = limb;
|
| - bit = GMP_NUMB_HIGHBIT;
|
| - }
|
| -}
|
| -
|
| -/* This is a simple bitwise algorithm working high to low across "s" and
|
| - testing each time whether setting the bit would make s^2 exceed n. */
|
| -mp_size_t
|
| -refmpn_sqrtrem (mp_ptr sp, mp_ptr rp, mp_srcptr np, mp_size_t nsize)
|
| -{
|
| - mp_ptr tp, dp;
|
| - mp_size_t ssize, talloc, tsize, dsize, ret, ilimbs;
|
| - unsigned ibit;
|
| - long i;
|
| - mp_limb_t c;
|
| -
|
| - ASSERT (nsize >= 0);
|
| -
|
| - /* If n==0, then s=0 and r=0. */
|
| - if (nsize == 0)
|
| - return 0;
|
| -
|
| - ASSERT (np[nsize - 1] != 0);
|
| - ASSERT (rp == NULL || MPN_SAME_OR_SEPARATE_P (np, rp, nsize));
|
| - ASSERT (rp == NULL || ! MPN_OVERLAP_P (sp, (nsize + 1) / 2, rp, nsize));
|
| - ASSERT (! MPN_OVERLAP_P (sp, (nsize + 1) / 2, np, nsize));
|
| -
|
| - /* root */
|
| - ssize = (nsize+1)/2;
|
| - refmpn_zero (sp, ssize);
|
| -
|
| - /* the remainder so far */
|
| - dp = refmpn_memdup_limbs (np, nsize);
|
| - dsize = nsize;
|
| -
|
| - /* temporary */
|
| - talloc = 2*ssize + 1;
|
| - tp = refmpn_malloc_limbs (talloc);
|
| -
|
| - for (i = GMP_NUMB_BITS * ssize - 1; i >= 0; i--)
|
| - {
|
| - /* t = 2*s*2^i + 2^(2*i), being the amount s^2 will increase by if 2^i
|
| - is added to it */
|
| -
|
| - ilimbs = (i+1) / GMP_NUMB_BITS;
|
| - ibit = (i+1) % GMP_NUMB_BITS;
|
| - refmpn_zero (tp, ilimbs);
|
| - c = refmpn_lshift_or_copy (tp+ilimbs, sp, ssize, ibit);
|
| - tsize = ilimbs + ssize;
|
| - tp[tsize] = c;
|
| - tsize += (c != 0);
|
| -
|
| - ilimbs = (2*i) / GMP_NUMB_BITS;
|
| - ibit = (2*i) % GMP_NUMB_BITS;
|
| - if (ilimbs + 1 > tsize)
|
| - {
|
| - refmpn_zero_extend (tp, tsize, ilimbs + 1);
|
| - tsize = ilimbs + 1;
|
| - }
|
| - c = refmpn_add_1 (tp+ilimbs, tp+ilimbs, tsize-ilimbs,
|
| - CNST_LIMB(1) << ibit);
|
| - ASSERT (tsize < talloc);
|
| - tp[tsize] = c;
|
| - tsize += (c != 0);
|
| -
|
| - if (refmpn_cmp_twosizes (dp, dsize, tp, tsize) >= 0)
|
| - {
|
| - /* set this bit in s and subtract from the remainder */
|
| - refmpn_setbit (sp, i);
|
| -
|
| - ASSERT_NOCARRY (refmpn_sub_n (dp, dp, tp, dsize));
|
| - dsize = refmpn_normalize (dp, dsize);
|
| - }
|
| - }
|
| -
|
| - if (rp == NULL)
|
| - {
|
| - ret = ! refmpn_zero_p (dp, dsize);
|
| - }
|
| - else
|
| - {
|
| - ASSERT (dsize == 0 || dp[dsize-1] != 0);
|
| - refmpn_copy (rp, dp, dsize);
|
| - ret = dsize;
|
| - }
|
| -
|
| - free (dp);
|
| - free (tp);
|
| - return ret;
|
| -}
|
|
|