xref: /dflybsd-src/contrib/gmp/dumbmp.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /* dumbmp mini GMP compatible library.
286d7f5d3SJohn Marino 
386d7f5d3SJohn Marino Copyright 2001, 2002, 2004 Free Software Foundation, Inc.
486d7f5d3SJohn Marino 
586d7f5d3SJohn Marino This file is part of the GNU MP Library.
686d7f5d3SJohn Marino 
786d7f5d3SJohn Marino The GNU MP Library is free software; you can redistribute it and/or modify
886d7f5d3SJohn Marino it under the terms of the GNU Lesser General Public License as published by
986d7f5d3SJohn Marino the Free Software Foundation; either version 3 of the License, or (at your
1086d7f5d3SJohn Marino option) any later version.
1186d7f5d3SJohn Marino 
1286d7f5d3SJohn Marino The GNU MP Library is distributed in the hope that it will be useful, but
1386d7f5d3SJohn Marino WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1486d7f5d3SJohn Marino or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
1586d7f5d3SJohn Marino License for more details.
1686d7f5d3SJohn Marino 
1786d7f5d3SJohn Marino You should have received a copy of the GNU Lesser General Public License
1886d7f5d3SJohn Marino along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
1986d7f5d3SJohn Marino 
2086d7f5d3SJohn Marino 
2186d7f5d3SJohn Marino /* The code here implements a subset (a very limited subset) of the main GMP
2286d7f5d3SJohn Marino    functions.  It's designed for use in a few build-time calculations and
2386d7f5d3SJohn Marino    will be slow, but highly portable.
2486d7f5d3SJohn Marino 
2586d7f5d3SJohn Marino    None of the normal GMP configure things are used, nor any of the normal
2686d7f5d3SJohn Marino    gmp.h or gmp-impl.h.  To use this file in a program just #include
2786d7f5d3SJohn Marino    "dumbmp.c".
2886d7f5d3SJohn Marino 
2986d7f5d3SJohn Marino    ANSI function definitions can be used here, since ansi2knr is run if
3086d7f5d3SJohn Marino    necessary.  But other ANSI-isms like "const" should be avoided.
3186d7f5d3SJohn Marino 
3286d7f5d3SJohn Marino    mp_limb_t here is an unsigned long, since that's a sensible type
3386d7f5d3SJohn Marino    everywhere we know of, with 8*sizeof(unsigned long) giving the number of
3486d7f5d3SJohn Marino    bits in the type (that not being true for instance with int or short on
3586d7f5d3SJohn Marino    Cray vector systems.)
3686d7f5d3SJohn Marino 
3786d7f5d3SJohn Marino    Only the low half of each mp_limb_t is used, so as to make carry handling
3886d7f5d3SJohn Marino    and limb multiplies easy.  GMP_LIMB_BITS is the number of bits used.  */
3986d7f5d3SJohn Marino 
4086d7f5d3SJohn Marino #include <stdio.h>
4186d7f5d3SJohn Marino #include <stdlib.h>
4286d7f5d3SJohn Marino #include <string.h>
4386d7f5d3SJohn Marino 
4486d7f5d3SJohn Marino 
4586d7f5d3SJohn Marino typedef unsigned long mp_limb_t;
4686d7f5d3SJohn Marino 
4786d7f5d3SJohn Marino typedef struct {
4886d7f5d3SJohn Marino   int        _mp_alloc;
4986d7f5d3SJohn Marino   int        _mp_size;
5086d7f5d3SJohn Marino   mp_limb_t *_mp_d;
5186d7f5d3SJohn Marino } mpz_t[1];
5286d7f5d3SJohn Marino 
5386d7f5d3SJohn Marino #define GMP_LIMB_BITS  (sizeof (mp_limb_t) * 8 / 2)
5486d7f5d3SJohn Marino 
5586d7f5d3SJohn Marino #define ABS(x)   ((x) >= 0 ? (x) : -(x))
5686d7f5d3SJohn Marino #define MIN(l,o) ((l) < (o) ? (l) : (o))
5786d7f5d3SJohn Marino #define MAX(h,i) ((h) > (i) ? (h) : (i))
5886d7f5d3SJohn Marino 
5986d7f5d3SJohn Marino #define ALLOC(x) ((x)->_mp_alloc)
6086d7f5d3SJohn Marino #define PTR(x)   ((x)->_mp_d)
6186d7f5d3SJohn Marino #define SIZ(x)   ((x)->_mp_size)
6286d7f5d3SJohn Marino #define ABSIZ(x) ABS (SIZ (x))
6386d7f5d3SJohn Marino #define LOMASK   ((1L << GMP_LIMB_BITS) - 1)
6486d7f5d3SJohn Marino #define LO(x)    ((x) & LOMASK)
6586d7f5d3SJohn Marino #define HI(x)    ((x) >> GMP_LIMB_BITS)
6686d7f5d3SJohn Marino 
6786d7f5d3SJohn Marino #define ASSERT(cond)                                    \
6886d7f5d3SJohn Marino   do {                                                  \
6986d7f5d3SJohn Marino     if (! (cond))                                       \
7086d7f5d3SJohn Marino       {                                                 \
7186d7f5d3SJohn Marino         fprintf (stderr, "Assertion failure\n");        \
7286d7f5d3SJohn Marino         abort ();                                       \
7386d7f5d3SJohn Marino       }                                                 \
7486d7f5d3SJohn Marino   } while (0)
7586d7f5d3SJohn Marino 
7686d7f5d3SJohn Marino 
7786d7f5d3SJohn Marino char *
xmalloc(int n)7886d7f5d3SJohn Marino xmalloc (int n)
7986d7f5d3SJohn Marino {
8086d7f5d3SJohn Marino   char  *p;
8186d7f5d3SJohn Marino   p = malloc (n);
8286d7f5d3SJohn Marino   if (p == NULL)
8386d7f5d3SJohn Marino     {
8486d7f5d3SJohn Marino       fprintf (stderr, "Out of memory (alloc %d bytes)\n", n);
8586d7f5d3SJohn Marino       abort ();
8686d7f5d3SJohn Marino     }
8786d7f5d3SJohn Marino   return p;
8886d7f5d3SJohn Marino }
8986d7f5d3SJohn Marino 
9086d7f5d3SJohn Marino mp_limb_t *
xmalloc_limbs(int n)9186d7f5d3SJohn Marino xmalloc_limbs (int n)
9286d7f5d3SJohn Marino {
9386d7f5d3SJohn Marino   return (mp_limb_t *) xmalloc (n * sizeof (mp_limb_t));
9486d7f5d3SJohn Marino }
9586d7f5d3SJohn Marino 
9686d7f5d3SJohn Marino void
mem_copyi(char * dst,char * src,int size)9786d7f5d3SJohn Marino mem_copyi (char *dst, char *src, int size)
9886d7f5d3SJohn Marino {
9986d7f5d3SJohn Marino   int  i;
10086d7f5d3SJohn Marino   for (i = 0; i < size; i++)
10186d7f5d3SJohn Marino     dst[i] = src[i];
10286d7f5d3SJohn Marino }
10386d7f5d3SJohn Marino 
10486d7f5d3SJohn Marino static int
isprime(unsigned long int t)10586d7f5d3SJohn Marino isprime (unsigned long int t)
10686d7f5d3SJohn Marino {
10786d7f5d3SJohn Marino   unsigned long int q, r, d;
10886d7f5d3SJohn Marino 
10986d7f5d3SJohn Marino   if (t < 32)
11086d7f5d3SJohn Marino     return (0xa08a28acUL >> t) & 1;
11186d7f5d3SJohn Marino   if ((t & 1) == 0)
11286d7f5d3SJohn Marino     return 0;
11386d7f5d3SJohn Marino 
11486d7f5d3SJohn Marino   if (t % 3 == 0)
11586d7f5d3SJohn Marino     return 0;
11686d7f5d3SJohn Marino   if (t % 5 == 0)
11786d7f5d3SJohn Marino     return 0;
11886d7f5d3SJohn Marino   if (t % 7 == 0)
11986d7f5d3SJohn Marino     return 0;
12086d7f5d3SJohn Marino 
12186d7f5d3SJohn Marino   for (d = 11;;)
12286d7f5d3SJohn Marino     {
12386d7f5d3SJohn Marino       q = t / d;
12486d7f5d3SJohn Marino       r = t - q * d;
12586d7f5d3SJohn Marino       if (q < d)
12686d7f5d3SJohn Marino 	return 1;
12786d7f5d3SJohn Marino       if (r == 0)
12886d7f5d3SJohn Marino 	break;
12986d7f5d3SJohn Marino       d += 2;
13086d7f5d3SJohn Marino       q = t / d;
13186d7f5d3SJohn Marino       r = t - q * d;
13286d7f5d3SJohn Marino       if (q < d)
13386d7f5d3SJohn Marino 	return 1;
13486d7f5d3SJohn Marino       if (r == 0)
13586d7f5d3SJohn Marino 	break;
13686d7f5d3SJohn Marino       d += 4;
13786d7f5d3SJohn Marino     }
13886d7f5d3SJohn Marino   return 0;
13986d7f5d3SJohn Marino }
14086d7f5d3SJohn Marino 
14186d7f5d3SJohn Marino int
log2_ceil(int n)14286d7f5d3SJohn Marino log2_ceil (int n)
14386d7f5d3SJohn Marino {
14486d7f5d3SJohn Marino   int  e;
14586d7f5d3SJohn Marino   ASSERT (n >= 1);
14686d7f5d3SJohn Marino   for (e = 0; ; e++)
14786d7f5d3SJohn Marino     if ((1 << e) >= n)
14886d7f5d3SJohn Marino       break;
14986d7f5d3SJohn Marino   return e;
15086d7f5d3SJohn Marino }
15186d7f5d3SJohn Marino 
15286d7f5d3SJohn Marino void
mpz_realloc(mpz_t r,int n)15386d7f5d3SJohn Marino mpz_realloc (mpz_t r, int n)
15486d7f5d3SJohn Marino {
15586d7f5d3SJohn Marino   if (n <= ALLOC(r))
15686d7f5d3SJohn Marino     return;
15786d7f5d3SJohn Marino 
15886d7f5d3SJohn Marino   ALLOC(r) = n;
15986d7f5d3SJohn Marino   PTR(r) = (mp_limb_t *) realloc (PTR(r), n * sizeof (mp_limb_t));
16086d7f5d3SJohn Marino   if (PTR(r) == NULL)
16186d7f5d3SJohn Marino     {
16286d7f5d3SJohn Marino       fprintf (stderr, "Out of memory (realloc to %d)\n", n);
16386d7f5d3SJohn Marino       abort ();
16486d7f5d3SJohn Marino     }
16586d7f5d3SJohn Marino }
16686d7f5d3SJohn Marino 
16786d7f5d3SJohn Marino void
mpn_normalize(mp_limb_t * rp,int * rnp)16886d7f5d3SJohn Marino mpn_normalize (mp_limb_t *rp, int *rnp)
16986d7f5d3SJohn Marino {
17086d7f5d3SJohn Marino   int  rn = *rnp;
17186d7f5d3SJohn Marino   while (rn > 0 && rp[rn-1] == 0)
17286d7f5d3SJohn Marino     rn--;
17386d7f5d3SJohn Marino   *rnp = rn;
17486d7f5d3SJohn Marino }
17586d7f5d3SJohn Marino 
17686d7f5d3SJohn Marino void
mpn_copyi(mp_limb_t * dst,mp_limb_t * src,int n)17786d7f5d3SJohn Marino mpn_copyi (mp_limb_t *dst, mp_limb_t *src, int n)
17886d7f5d3SJohn Marino {
17986d7f5d3SJohn Marino   int  i;
18086d7f5d3SJohn Marino   for (i = 0; i < n; i++)
18186d7f5d3SJohn Marino     dst[i] = src[i];
18286d7f5d3SJohn Marino }
18386d7f5d3SJohn Marino 
18486d7f5d3SJohn Marino void
mpn_zero(mp_limb_t * rp,int rn)18586d7f5d3SJohn Marino mpn_zero (mp_limb_t *rp, int rn)
18686d7f5d3SJohn Marino {
18786d7f5d3SJohn Marino   int  i;
18886d7f5d3SJohn Marino   for (i = 0; i < rn; i++)
18986d7f5d3SJohn Marino     rp[i] = 0;
19086d7f5d3SJohn Marino }
19186d7f5d3SJohn Marino 
19286d7f5d3SJohn Marino void
mpz_init(mpz_t r)19386d7f5d3SJohn Marino mpz_init (mpz_t r)
19486d7f5d3SJohn Marino {
19586d7f5d3SJohn Marino   ALLOC(r) = 1;
19686d7f5d3SJohn Marino   PTR(r) = xmalloc_limbs (ALLOC(r));
19786d7f5d3SJohn Marino   PTR(r)[0] = 0;
19886d7f5d3SJohn Marino   SIZ(r) = 0;
19986d7f5d3SJohn Marino }
20086d7f5d3SJohn Marino 
20186d7f5d3SJohn Marino void
mpz_clear(mpz_t r)20286d7f5d3SJohn Marino mpz_clear (mpz_t r)
20386d7f5d3SJohn Marino {
20486d7f5d3SJohn Marino   free (PTR (r));
20586d7f5d3SJohn Marino   ALLOC(r) = -1;
20686d7f5d3SJohn Marino   SIZ (r) = 0xbadcafeL;
20786d7f5d3SJohn Marino   PTR (r) = (mp_limb_t *) 0xdeadbeefL;
20886d7f5d3SJohn Marino }
20986d7f5d3SJohn Marino 
21086d7f5d3SJohn Marino int
mpz_sgn(mpz_t a)21186d7f5d3SJohn Marino mpz_sgn (mpz_t a)
21286d7f5d3SJohn Marino {
21386d7f5d3SJohn Marino   return (SIZ(a) > 0 ? 1 : SIZ(a) == 0 ? 0 : -1);
21486d7f5d3SJohn Marino }
21586d7f5d3SJohn Marino 
21686d7f5d3SJohn Marino int
mpz_odd_p(mpz_t a)21786d7f5d3SJohn Marino mpz_odd_p (mpz_t a)
21886d7f5d3SJohn Marino {
21986d7f5d3SJohn Marino   if (SIZ(a) == 0)
22086d7f5d3SJohn Marino     return 0;
22186d7f5d3SJohn Marino   else
22286d7f5d3SJohn Marino     return (PTR(a)[0] & 1) != 0;
22386d7f5d3SJohn Marino }
22486d7f5d3SJohn Marino 
22586d7f5d3SJohn Marino int
mpz_even_p(mpz_t a)22686d7f5d3SJohn Marino mpz_even_p (mpz_t a)
22786d7f5d3SJohn Marino {
22886d7f5d3SJohn Marino   if (SIZ(a) == 0)
22986d7f5d3SJohn Marino     return 1;
23086d7f5d3SJohn Marino   else
23186d7f5d3SJohn Marino     return (PTR(a)[0] & 1) == 0;
23286d7f5d3SJohn Marino }
23386d7f5d3SJohn Marino 
23486d7f5d3SJohn Marino size_t
mpz_sizeinbase(mpz_t a,int base)23586d7f5d3SJohn Marino mpz_sizeinbase (mpz_t a, int base)
23686d7f5d3SJohn Marino {
23786d7f5d3SJohn Marino   int an = ABSIZ (a);
23886d7f5d3SJohn Marino   mp_limb_t *ap = PTR (a);
23986d7f5d3SJohn Marino   int cnt;
24086d7f5d3SJohn Marino   mp_limb_t hi;
24186d7f5d3SJohn Marino 
24286d7f5d3SJohn Marino   if (base != 2)
24386d7f5d3SJohn Marino     abort ();
24486d7f5d3SJohn Marino 
24586d7f5d3SJohn Marino   if (an == 0)
24686d7f5d3SJohn Marino     return 1;
24786d7f5d3SJohn Marino 
24886d7f5d3SJohn Marino   cnt = 0;
24986d7f5d3SJohn Marino   for (hi = ap[an - 1]; hi != 0; hi >>= 1)
25086d7f5d3SJohn Marino     cnt += 1;
25186d7f5d3SJohn Marino   return (an - 1) * GMP_LIMB_BITS + cnt;
25286d7f5d3SJohn Marino }
25386d7f5d3SJohn Marino 
25486d7f5d3SJohn Marino void
mpz_set(mpz_t r,mpz_t a)25586d7f5d3SJohn Marino mpz_set (mpz_t r, mpz_t a)
25686d7f5d3SJohn Marino {
25786d7f5d3SJohn Marino   mpz_realloc (r, ABSIZ (a));
25886d7f5d3SJohn Marino   SIZ(r) = SIZ(a);
25986d7f5d3SJohn Marino   mpn_copyi (PTR(r), PTR(a), ABSIZ (a));
26086d7f5d3SJohn Marino }
26186d7f5d3SJohn Marino 
26286d7f5d3SJohn Marino void
mpz_init_set(mpz_t r,mpz_t a)26386d7f5d3SJohn Marino mpz_init_set (mpz_t r, mpz_t a)
26486d7f5d3SJohn Marino {
26586d7f5d3SJohn Marino   mpz_init (r);
26686d7f5d3SJohn Marino   mpz_set (r, a);
26786d7f5d3SJohn Marino }
26886d7f5d3SJohn Marino 
26986d7f5d3SJohn Marino void
mpz_set_ui(mpz_t r,unsigned long ui)27086d7f5d3SJohn Marino mpz_set_ui (mpz_t r, unsigned long ui)
27186d7f5d3SJohn Marino {
27286d7f5d3SJohn Marino   int  rn;
27386d7f5d3SJohn Marino   mpz_realloc (r, 2);
27486d7f5d3SJohn Marino   PTR(r)[0] = LO(ui);
27586d7f5d3SJohn Marino   PTR(r)[1] = HI(ui);
27686d7f5d3SJohn Marino   rn = 2;
27786d7f5d3SJohn Marino   mpn_normalize (PTR(r), &rn);
27886d7f5d3SJohn Marino   SIZ(r) = rn;
27986d7f5d3SJohn Marino }
28086d7f5d3SJohn Marino 
28186d7f5d3SJohn Marino void
mpz_init_set_ui(mpz_t r,unsigned long ui)28286d7f5d3SJohn Marino mpz_init_set_ui (mpz_t r, unsigned long ui)
28386d7f5d3SJohn Marino {
28486d7f5d3SJohn Marino   mpz_init (r);
28586d7f5d3SJohn Marino   mpz_set_ui (r, ui);
28686d7f5d3SJohn Marino }
28786d7f5d3SJohn Marino 
28886d7f5d3SJohn Marino void
mpz_setbit(mpz_t r,unsigned long bit)28986d7f5d3SJohn Marino mpz_setbit (mpz_t r, unsigned long bit)
29086d7f5d3SJohn Marino {
29186d7f5d3SJohn Marino   int        limb, rn, extend;
29286d7f5d3SJohn Marino   mp_limb_t  *rp;
29386d7f5d3SJohn Marino 
29486d7f5d3SJohn Marino   rn = SIZ(r);
29586d7f5d3SJohn Marino   if (rn < 0)
29686d7f5d3SJohn Marino     abort ();  /* only r>=0 */
29786d7f5d3SJohn Marino 
29886d7f5d3SJohn Marino   limb = bit / GMP_LIMB_BITS;
29986d7f5d3SJohn Marino   bit %= GMP_LIMB_BITS;
30086d7f5d3SJohn Marino 
30186d7f5d3SJohn Marino   mpz_realloc (r, limb+1);
30286d7f5d3SJohn Marino   rp = PTR(r);
30386d7f5d3SJohn Marino   extend = (limb+1) - rn;
30486d7f5d3SJohn Marino   if (extend > 0)
30586d7f5d3SJohn Marino     mpn_zero (rp + rn, extend);
30686d7f5d3SJohn Marino 
30786d7f5d3SJohn Marino   rp[limb] |= (mp_limb_t) 1 << bit;
30886d7f5d3SJohn Marino   SIZ(r) = MAX (rn, limb+1);
30986d7f5d3SJohn Marino }
31086d7f5d3SJohn Marino 
31186d7f5d3SJohn Marino int
mpz_tstbit(mpz_t r,unsigned long bit)31286d7f5d3SJohn Marino mpz_tstbit (mpz_t r, unsigned long bit)
31386d7f5d3SJohn Marino {
31486d7f5d3SJohn Marino   int  limb;
31586d7f5d3SJohn Marino 
31686d7f5d3SJohn Marino   if (SIZ(r) < 0)
31786d7f5d3SJohn Marino     abort ();  /* only r>=0 */
31886d7f5d3SJohn Marino 
31986d7f5d3SJohn Marino   limb = bit / GMP_LIMB_BITS;
32086d7f5d3SJohn Marino   if (SIZ(r) <= limb)
32186d7f5d3SJohn Marino     return 0;
32286d7f5d3SJohn Marino 
32386d7f5d3SJohn Marino   bit %= GMP_LIMB_BITS;
32486d7f5d3SJohn Marino   return (PTR(r)[limb] >> bit) & 1;
32586d7f5d3SJohn Marino }
32686d7f5d3SJohn Marino 
32786d7f5d3SJohn Marino int
popc_limb(mp_limb_t a)32886d7f5d3SJohn Marino popc_limb (mp_limb_t a)
32986d7f5d3SJohn Marino {
33086d7f5d3SJohn Marino   int  ret = 0;
33186d7f5d3SJohn Marino   while (a != 0)
33286d7f5d3SJohn Marino     {
33386d7f5d3SJohn Marino       ret += (a & 1);
33486d7f5d3SJohn Marino       a >>= 1;
33586d7f5d3SJohn Marino     }
33686d7f5d3SJohn Marino   return ret;
33786d7f5d3SJohn Marino }
33886d7f5d3SJohn Marino 
33986d7f5d3SJohn Marino unsigned long
mpz_popcount(mpz_t a)34086d7f5d3SJohn Marino mpz_popcount (mpz_t a)
34186d7f5d3SJohn Marino {
34286d7f5d3SJohn Marino   unsigned long  ret;
34386d7f5d3SJohn Marino   int            i;
34486d7f5d3SJohn Marino 
34586d7f5d3SJohn Marino   if (SIZ(a) < 0)
34686d7f5d3SJohn Marino     abort ();
34786d7f5d3SJohn Marino 
34886d7f5d3SJohn Marino   ret = 0;
34986d7f5d3SJohn Marino   for (i = 0; i < SIZ(a); i++)
35086d7f5d3SJohn Marino     ret += popc_limb (PTR(a)[i]);
35186d7f5d3SJohn Marino   return ret;
35286d7f5d3SJohn Marino }
35386d7f5d3SJohn Marino 
35486d7f5d3SJohn Marino void
mpz_add(mpz_t r,mpz_t a,mpz_t b)35586d7f5d3SJohn Marino mpz_add (mpz_t r, mpz_t a, mpz_t b)
35686d7f5d3SJohn Marino {
35786d7f5d3SJohn Marino   int an = ABSIZ (a), bn = ABSIZ (b), rn;
35886d7f5d3SJohn Marino   mp_limb_t *rp, *ap, *bp;
35986d7f5d3SJohn Marino   int i;
36086d7f5d3SJohn Marino   mp_limb_t t, cy;
36186d7f5d3SJohn Marino 
36286d7f5d3SJohn Marino   if ((SIZ (a) ^ SIZ (b)) < 0)
36386d7f5d3SJohn Marino     abort ();			/* really subtraction */
36486d7f5d3SJohn Marino   if (SIZ (a) < 0)
36586d7f5d3SJohn Marino     abort ();
36686d7f5d3SJohn Marino 
36786d7f5d3SJohn Marino   mpz_realloc (r, MAX (an, bn) + 1);
36886d7f5d3SJohn Marino   ap = PTR (a);  bp = PTR (b);  rp = PTR (r);
36986d7f5d3SJohn Marino   if (an < bn)
37086d7f5d3SJohn Marino     {
37186d7f5d3SJohn Marino       mp_limb_t *tp;  int tn;
37286d7f5d3SJohn Marino       tn = an; an = bn; bn = tn;
37386d7f5d3SJohn Marino       tp = ap; ap = bp; bp = tp;
37486d7f5d3SJohn Marino     }
37586d7f5d3SJohn Marino 
37686d7f5d3SJohn Marino   cy = 0;
37786d7f5d3SJohn Marino   for (i = 0; i < bn; i++)
37886d7f5d3SJohn Marino     {
37986d7f5d3SJohn Marino       t = ap[i] + bp[i] + cy;
38086d7f5d3SJohn Marino       rp[i] = LO (t);
38186d7f5d3SJohn Marino       cy = HI (t);
38286d7f5d3SJohn Marino     }
38386d7f5d3SJohn Marino   for (i = bn; i < an; i++)
38486d7f5d3SJohn Marino     {
38586d7f5d3SJohn Marino       t = ap[i] + cy;
38686d7f5d3SJohn Marino       rp[i] = LO (t);
38786d7f5d3SJohn Marino       cy = HI (t);
38886d7f5d3SJohn Marino     }
38986d7f5d3SJohn Marino   rp[an] = cy;
39086d7f5d3SJohn Marino   rn = an + 1;
39186d7f5d3SJohn Marino 
39286d7f5d3SJohn Marino   mpn_normalize (rp, &rn);
39386d7f5d3SJohn Marino   SIZ (r) = rn;
39486d7f5d3SJohn Marino }
39586d7f5d3SJohn Marino 
39686d7f5d3SJohn Marino void
mpz_add_ui(mpz_t r,mpz_t a,unsigned long int ui)39786d7f5d3SJohn Marino mpz_add_ui (mpz_t r, mpz_t a, unsigned long int ui)
39886d7f5d3SJohn Marino {
39986d7f5d3SJohn Marino   mpz_t b;
40086d7f5d3SJohn Marino 
40186d7f5d3SJohn Marino   mpz_init (b);
40286d7f5d3SJohn Marino   mpz_set_ui (b, ui);
40386d7f5d3SJohn Marino   mpz_add (r, a, b);
40486d7f5d3SJohn Marino   mpz_clear (b);
40586d7f5d3SJohn Marino }
40686d7f5d3SJohn Marino 
40786d7f5d3SJohn Marino void
mpz_sub(mpz_t r,mpz_t a,mpz_t b)40886d7f5d3SJohn Marino mpz_sub (mpz_t r, mpz_t a, mpz_t b)
40986d7f5d3SJohn Marino {
41086d7f5d3SJohn Marino   int an = ABSIZ (a), bn = ABSIZ (b), rn;
41186d7f5d3SJohn Marino   mp_limb_t *rp, *ap, *bp;
41286d7f5d3SJohn Marino   int i;
41386d7f5d3SJohn Marino   mp_limb_t t, cy;
41486d7f5d3SJohn Marino 
41586d7f5d3SJohn Marino   if ((SIZ (a) ^ SIZ (b)) < 0)
41686d7f5d3SJohn Marino     abort ();			/* really addition */
41786d7f5d3SJohn Marino   if (SIZ (a) < 0)
41886d7f5d3SJohn Marino     abort ();
41986d7f5d3SJohn Marino 
42086d7f5d3SJohn Marino   mpz_realloc (r, MAX (an, bn) + 1);
42186d7f5d3SJohn Marino   ap = PTR (a);  bp = PTR (b);  rp = PTR (r);
42286d7f5d3SJohn Marino   if (an < bn)
42386d7f5d3SJohn Marino     {
42486d7f5d3SJohn Marino       mp_limb_t *tp;  int tn;
42586d7f5d3SJohn Marino       tn = an; an = bn; bn = tn;
42686d7f5d3SJohn Marino       tp = ap; ap = bp; bp = tp;
42786d7f5d3SJohn Marino     }
42886d7f5d3SJohn Marino 
42986d7f5d3SJohn Marino   cy = 0;
43086d7f5d3SJohn Marino   for (i = 0; i < bn; i++)
43186d7f5d3SJohn Marino     {
43286d7f5d3SJohn Marino       t = ap[i] - bp[i] - cy;
43386d7f5d3SJohn Marino       rp[i] = LO (t);
43486d7f5d3SJohn Marino       cy = LO (-HI (t));
43586d7f5d3SJohn Marino     }
43686d7f5d3SJohn Marino   for (i = bn; i < an; i++)
43786d7f5d3SJohn Marino     {
43886d7f5d3SJohn Marino       t = ap[i] - cy;
43986d7f5d3SJohn Marino       rp[i] = LO (t);
44086d7f5d3SJohn Marino       cy = LO (-HI (t));
44186d7f5d3SJohn Marino     }
44286d7f5d3SJohn Marino   rp[an] = cy;
44386d7f5d3SJohn Marino   rn = an + 1;
44486d7f5d3SJohn Marino 
44586d7f5d3SJohn Marino   if (cy != 0)
44686d7f5d3SJohn Marino     {
44786d7f5d3SJohn Marino       cy = 0;
44886d7f5d3SJohn Marino       for (i = 0; i < rn; i++)
44986d7f5d3SJohn Marino 	{
45086d7f5d3SJohn Marino 	  t = -rp[i] - cy;
45186d7f5d3SJohn Marino 	  rp[i] = LO (t);
45286d7f5d3SJohn Marino 	  cy = LO (-HI (t));
45386d7f5d3SJohn Marino 	}
45486d7f5d3SJohn Marino       SIZ (r) = -rn;
45586d7f5d3SJohn Marino       return;
45686d7f5d3SJohn Marino     }
45786d7f5d3SJohn Marino 
45886d7f5d3SJohn Marino   mpn_normalize (rp, &rn);
45986d7f5d3SJohn Marino   SIZ (r) = rn;
46086d7f5d3SJohn Marino }
46186d7f5d3SJohn Marino 
46286d7f5d3SJohn Marino void
mpz_sub_ui(mpz_t r,mpz_t a,unsigned long int ui)46386d7f5d3SJohn Marino mpz_sub_ui (mpz_t r, mpz_t a, unsigned long int ui)
46486d7f5d3SJohn Marino {
46586d7f5d3SJohn Marino   mpz_t b;
46686d7f5d3SJohn Marino 
46786d7f5d3SJohn Marino   mpz_init (b);
46886d7f5d3SJohn Marino   mpz_set_ui (b, ui);
46986d7f5d3SJohn Marino   mpz_sub (r, a, b);
47086d7f5d3SJohn Marino   mpz_clear (b);
47186d7f5d3SJohn Marino }
47286d7f5d3SJohn Marino 
47386d7f5d3SJohn Marino void
mpz_mul(mpz_t r,mpz_t a,mpz_t b)47486d7f5d3SJohn Marino mpz_mul (mpz_t r, mpz_t a, mpz_t b)
47586d7f5d3SJohn Marino {
47686d7f5d3SJohn Marino   int an = ABSIZ (a), bn = ABSIZ (b), rn;
47786d7f5d3SJohn Marino   mp_limb_t *scratch, *tmp, *ap = PTR (a), *bp = PTR (b);
47886d7f5d3SJohn Marino   int ai, bi;
47986d7f5d3SJohn Marino   mp_limb_t t, cy;
48086d7f5d3SJohn Marino 
48186d7f5d3SJohn Marino   scratch = xmalloc_limbs (an + bn);
48286d7f5d3SJohn Marino   tmp = scratch;
48386d7f5d3SJohn Marino 
48486d7f5d3SJohn Marino   for (bi = 0; bi < bn; bi++)
48586d7f5d3SJohn Marino     tmp[bi] = 0;
48686d7f5d3SJohn Marino 
48786d7f5d3SJohn Marino   for (ai = 0; ai < an; ai++)
48886d7f5d3SJohn Marino     {
48986d7f5d3SJohn Marino       tmp = scratch + ai;
49086d7f5d3SJohn Marino       cy = 0;
49186d7f5d3SJohn Marino       for (bi = 0; bi < bn; bi++)
49286d7f5d3SJohn Marino 	{
49386d7f5d3SJohn Marino 	  t = ap[ai] * bp[bi] + tmp[bi] + cy;
49486d7f5d3SJohn Marino 	  tmp[bi] = LO (t);
49586d7f5d3SJohn Marino 	  cy = HI (t);
49686d7f5d3SJohn Marino 	}
49786d7f5d3SJohn Marino       tmp[bn] = cy;
49886d7f5d3SJohn Marino     }
49986d7f5d3SJohn Marino 
50086d7f5d3SJohn Marino   rn = an + bn;
50186d7f5d3SJohn Marino   mpn_normalize (scratch, &rn);
50286d7f5d3SJohn Marino   free (PTR (r));
50386d7f5d3SJohn Marino   PTR (r) = scratch;
50486d7f5d3SJohn Marino   SIZ (r) = (SIZ (a) ^ SIZ (b)) >= 0 ? rn : -rn;
50586d7f5d3SJohn Marino   ALLOC (r) = an + bn;
50686d7f5d3SJohn Marino }
50786d7f5d3SJohn Marino 
50886d7f5d3SJohn Marino void
mpz_mul_ui(mpz_t r,mpz_t a,unsigned long int ui)50986d7f5d3SJohn Marino mpz_mul_ui (mpz_t r, mpz_t a, unsigned long int ui)
51086d7f5d3SJohn Marino {
51186d7f5d3SJohn Marino   mpz_t b;
51286d7f5d3SJohn Marino 
51386d7f5d3SJohn Marino   mpz_init (b);
51486d7f5d3SJohn Marino   mpz_set_ui (b, ui);
51586d7f5d3SJohn Marino   mpz_mul (r, a, b);
51686d7f5d3SJohn Marino   mpz_clear (b);
51786d7f5d3SJohn Marino }
51886d7f5d3SJohn Marino 
51986d7f5d3SJohn Marino void
mpz_mul_2exp(mpz_t r,mpz_t a,unsigned long int bcnt)52086d7f5d3SJohn Marino mpz_mul_2exp (mpz_t r, mpz_t a, unsigned long int bcnt)
52186d7f5d3SJohn Marino {
52286d7f5d3SJohn Marino   mpz_set (r, a);
52386d7f5d3SJohn Marino   while (bcnt)
52486d7f5d3SJohn Marino     {
52586d7f5d3SJohn Marino       mpz_add (r, r, r);
52686d7f5d3SJohn Marino       bcnt -= 1;
52786d7f5d3SJohn Marino     }
52886d7f5d3SJohn Marino }
52986d7f5d3SJohn Marino 
53086d7f5d3SJohn Marino void
mpz_ui_pow_ui(mpz_t r,unsigned long b,unsigned long e)53186d7f5d3SJohn Marino mpz_ui_pow_ui (mpz_t r, unsigned long b, unsigned long e)
53286d7f5d3SJohn Marino {
53386d7f5d3SJohn Marino   unsigned long  i;
53486d7f5d3SJohn Marino   mpz_t          bz;
53586d7f5d3SJohn Marino 
53686d7f5d3SJohn Marino   mpz_init (bz);
53786d7f5d3SJohn Marino   mpz_set_ui (bz, b);
53886d7f5d3SJohn Marino 
53986d7f5d3SJohn Marino   mpz_set_ui (r, 1L);
54086d7f5d3SJohn Marino   for (i = 0; i < e; i++)
54186d7f5d3SJohn Marino     mpz_mul (r, r, bz);
54286d7f5d3SJohn Marino 
54386d7f5d3SJohn Marino   mpz_clear (bz);
54486d7f5d3SJohn Marino }
54586d7f5d3SJohn Marino 
54686d7f5d3SJohn Marino void
mpz_tdiv_q_2exp(mpz_t r,mpz_t a,unsigned long int bcnt)54786d7f5d3SJohn Marino mpz_tdiv_q_2exp (mpz_t r, mpz_t a, unsigned long int bcnt)
54886d7f5d3SJohn Marino {
54986d7f5d3SJohn Marino   int as, rn;
55086d7f5d3SJohn Marino   int cnt, tnc;
55186d7f5d3SJohn Marino   int lcnt;
55286d7f5d3SJohn Marino   mp_limb_t high_limb, low_limb;
55386d7f5d3SJohn Marino   int i;
55486d7f5d3SJohn Marino 
55586d7f5d3SJohn Marino   as = SIZ (a);
55686d7f5d3SJohn Marino   lcnt = bcnt / GMP_LIMB_BITS;
55786d7f5d3SJohn Marino   rn = ABS (as) - lcnt;
55886d7f5d3SJohn Marino   if (rn <= 0)
55986d7f5d3SJohn Marino     SIZ (r) = 0;
56086d7f5d3SJohn Marino   else
56186d7f5d3SJohn Marino     {
56286d7f5d3SJohn Marino       mp_limb_t *rp, *ap;
56386d7f5d3SJohn Marino 
56486d7f5d3SJohn Marino       mpz_realloc (r, rn);
56586d7f5d3SJohn Marino 
56686d7f5d3SJohn Marino       rp = PTR (r);
56786d7f5d3SJohn Marino       ap = PTR (a);
56886d7f5d3SJohn Marino 
56986d7f5d3SJohn Marino       cnt = bcnt % GMP_LIMB_BITS;
57086d7f5d3SJohn Marino       if (cnt != 0)
57186d7f5d3SJohn Marino         {
57286d7f5d3SJohn Marino 	  ap += lcnt;
57386d7f5d3SJohn Marino 	  tnc = GMP_LIMB_BITS - cnt;
57486d7f5d3SJohn Marino 	  high_limb = *ap++;
57586d7f5d3SJohn Marino 	  low_limb = high_limb >> cnt;
57686d7f5d3SJohn Marino 
57786d7f5d3SJohn Marino 	  for (i = rn - 1; i != 0; i--)
57886d7f5d3SJohn Marino 	    {
57986d7f5d3SJohn Marino 	      high_limb = *ap++;
58086d7f5d3SJohn Marino 	      *rp++ = low_limb | LO (high_limb << tnc);
58186d7f5d3SJohn Marino 	      low_limb = high_limb >> cnt;
58286d7f5d3SJohn Marino 	    }
58386d7f5d3SJohn Marino 	  *rp = low_limb;
58486d7f5d3SJohn Marino           rn -= low_limb == 0;
58586d7f5d3SJohn Marino         }
58686d7f5d3SJohn Marino       else
58786d7f5d3SJohn Marino         {
58886d7f5d3SJohn Marino 	  ap += lcnt;
58986d7f5d3SJohn Marino           mpn_copyi (rp, ap, rn);
59086d7f5d3SJohn Marino         }
59186d7f5d3SJohn Marino 
59286d7f5d3SJohn Marino       SIZ (r) = as >= 0 ? rn : -rn;
59386d7f5d3SJohn Marino     }
59486d7f5d3SJohn Marino }
59586d7f5d3SJohn Marino 
59686d7f5d3SJohn Marino void
mpz_tdiv_r_2exp(mpz_t r,mpz_t a,unsigned long int bcnt)59786d7f5d3SJohn Marino mpz_tdiv_r_2exp (mpz_t r, mpz_t a, unsigned long int bcnt)
59886d7f5d3SJohn Marino {
59986d7f5d3SJohn Marino   int    rn, bwhole;
60086d7f5d3SJohn Marino 
60186d7f5d3SJohn Marino   mpz_set (r, a);
60286d7f5d3SJohn Marino   rn = ABSIZ(r);
60386d7f5d3SJohn Marino 
60486d7f5d3SJohn Marino   bwhole = bcnt / GMP_LIMB_BITS;
60586d7f5d3SJohn Marino   bcnt %= GMP_LIMB_BITS;
60686d7f5d3SJohn Marino   if (rn > bwhole)
60786d7f5d3SJohn Marino     {
60886d7f5d3SJohn Marino       rn = bwhole+1;
60986d7f5d3SJohn Marino       PTR(r)[rn-1] &= ((mp_limb_t) 1 << bcnt) - 1;
61086d7f5d3SJohn Marino       mpn_normalize (PTR(r), &rn);
61186d7f5d3SJohn Marino       SIZ(r) = (SIZ(r) >= 0 ? rn : -rn);
61286d7f5d3SJohn Marino     }
61386d7f5d3SJohn Marino }
61486d7f5d3SJohn Marino 
61586d7f5d3SJohn Marino int
mpz_cmp(mpz_t a,mpz_t b)61686d7f5d3SJohn Marino mpz_cmp (mpz_t a, mpz_t b)
61786d7f5d3SJohn Marino {
61886d7f5d3SJohn Marino   mp_limb_t *ap, *bp, al, bl;
61986d7f5d3SJohn Marino   int as = SIZ (a), bs = SIZ (b);
62086d7f5d3SJohn Marino   int i;
62186d7f5d3SJohn Marino   int sign;
62286d7f5d3SJohn Marino 
62386d7f5d3SJohn Marino   if (as != bs)
62486d7f5d3SJohn Marino     return as > bs ? 1 : -1;
62586d7f5d3SJohn Marino 
62686d7f5d3SJohn Marino   sign = as > 0 ? 1 : -1;
62786d7f5d3SJohn Marino 
62886d7f5d3SJohn Marino   ap = PTR (a);
62986d7f5d3SJohn Marino   bp = PTR (b);
63086d7f5d3SJohn Marino   for (i = ABS (as) - 1; i >= 0; i--)
63186d7f5d3SJohn Marino     {
63286d7f5d3SJohn Marino       al = ap[i];
63386d7f5d3SJohn Marino       bl = bp[i];
63486d7f5d3SJohn Marino       if (al != bl)
63586d7f5d3SJohn Marino 	return al > bl ? sign : -sign;
63686d7f5d3SJohn Marino     }
63786d7f5d3SJohn Marino   return 0;
63886d7f5d3SJohn Marino }
63986d7f5d3SJohn Marino 
64086d7f5d3SJohn Marino int
mpz_cmp_ui(mpz_t a,unsigned long b)64186d7f5d3SJohn Marino mpz_cmp_ui (mpz_t a, unsigned long b)
64286d7f5d3SJohn Marino {
64386d7f5d3SJohn Marino   mpz_t  bz;
64486d7f5d3SJohn Marino   int    ret;
64586d7f5d3SJohn Marino   mpz_init_set_ui (bz, b);
64686d7f5d3SJohn Marino   ret = mpz_cmp (a, bz);
64786d7f5d3SJohn Marino   mpz_clear (bz);
64886d7f5d3SJohn Marino   return ret;
64986d7f5d3SJohn Marino }
65086d7f5d3SJohn Marino 
65186d7f5d3SJohn Marino void
mpz_tdiv_qr(mpz_t q,mpz_t r,mpz_t a,mpz_t b)65286d7f5d3SJohn Marino mpz_tdiv_qr (mpz_t q, mpz_t r, mpz_t a, mpz_t b)
65386d7f5d3SJohn Marino {
65486d7f5d3SJohn Marino   mpz_t          tmpr, tmpb;
65586d7f5d3SJohn Marino   unsigned long  cnt;
65686d7f5d3SJohn Marino 
65786d7f5d3SJohn Marino   ASSERT (mpz_sgn(a) >= 0);
65886d7f5d3SJohn Marino   ASSERT (mpz_sgn(b) > 0);
65986d7f5d3SJohn Marino 
66086d7f5d3SJohn Marino   mpz_init_set (tmpr, a);
66186d7f5d3SJohn Marino   mpz_init_set (tmpb, b);
66286d7f5d3SJohn Marino   mpz_set_ui (q, 0L);
66386d7f5d3SJohn Marino 
66486d7f5d3SJohn Marino   if (mpz_cmp (tmpr, tmpb) > 0)
66586d7f5d3SJohn Marino     {
66686d7f5d3SJohn Marino       cnt = mpz_sizeinbase (tmpr, 2) - mpz_sizeinbase (tmpb, 2) + 1;
66786d7f5d3SJohn Marino       mpz_mul_2exp (tmpb, tmpb, cnt);
66886d7f5d3SJohn Marino 
66986d7f5d3SJohn Marino       for ( ; cnt > 0; cnt--)
67086d7f5d3SJohn Marino         {
67186d7f5d3SJohn Marino           mpz_mul_2exp (q, q, 1);
67286d7f5d3SJohn Marino           mpz_tdiv_q_2exp (tmpb, tmpb, 1L);
67386d7f5d3SJohn Marino           if (mpz_cmp (tmpr, tmpb) >= 0)
67486d7f5d3SJohn Marino             {
67586d7f5d3SJohn Marino               mpz_sub (tmpr, tmpr, tmpb);
67686d7f5d3SJohn Marino               mpz_add_ui (q, q, 1L);
67786d7f5d3SJohn Marino               ASSERT (mpz_cmp (tmpr, tmpb) < 0);
67886d7f5d3SJohn Marino             }
67986d7f5d3SJohn Marino         }
68086d7f5d3SJohn Marino     }
68186d7f5d3SJohn Marino 
68286d7f5d3SJohn Marino   mpz_set (r, tmpr);
68386d7f5d3SJohn Marino   mpz_clear (tmpr);
68486d7f5d3SJohn Marino   mpz_clear (tmpb);
68586d7f5d3SJohn Marino }
68686d7f5d3SJohn Marino 
68786d7f5d3SJohn Marino void
mpz_tdiv_qr_ui(mpz_t q,mpz_t r,mpz_t a,unsigned long b)68886d7f5d3SJohn Marino mpz_tdiv_qr_ui (mpz_t q, mpz_t r, mpz_t a, unsigned long b)
68986d7f5d3SJohn Marino {
69086d7f5d3SJohn Marino   mpz_t  bz;
69186d7f5d3SJohn Marino   mpz_init_set_ui (bz, b);
69286d7f5d3SJohn Marino   mpz_tdiv_qr (q, r, a, bz);
69386d7f5d3SJohn Marino   mpz_clear (bz);
69486d7f5d3SJohn Marino }
69586d7f5d3SJohn Marino 
69686d7f5d3SJohn Marino void
mpz_tdiv_q(mpz_t q,mpz_t a,mpz_t b)69786d7f5d3SJohn Marino mpz_tdiv_q (mpz_t q, mpz_t a, mpz_t b)
69886d7f5d3SJohn Marino {
69986d7f5d3SJohn Marino   mpz_t  r;
70086d7f5d3SJohn Marino 
70186d7f5d3SJohn Marino   mpz_init (r);
70286d7f5d3SJohn Marino   mpz_tdiv_qr (q, r, a, b);
70386d7f5d3SJohn Marino   mpz_clear (r);
70486d7f5d3SJohn Marino }
70586d7f5d3SJohn Marino 
70686d7f5d3SJohn Marino void
mpz_tdiv_r(mpz_t r,mpz_t a,mpz_t b)70786d7f5d3SJohn Marino mpz_tdiv_r (mpz_t r, mpz_t a, mpz_t b)
70886d7f5d3SJohn Marino {
70986d7f5d3SJohn Marino   mpz_t  q;
71086d7f5d3SJohn Marino 
71186d7f5d3SJohn Marino   mpz_init (q);
71286d7f5d3SJohn Marino   mpz_tdiv_qr (q, r, a, b);
71386d7f5d3SJohn Marino   mpz_clear (q);
71486d7f5d3SJohn Marino }
71586d7f5d3SJohn Marino 
71686d7f5d3SJohn Marino void
mpz_tdiv_q_ui(mpz_t q,mpz_t n,unsigned long d)71786d7f5d3SJohn Marino mpz_tdiv_q_ui (mpz_t q, mpz_t n, unsigned long d)
71886d7f5d3SJohn Marino {
71986d7f5d3SJohn Marino   mpz_t  dz;
72086d7f5d3SJohn Marino   mpz_init_set_ui (dz, d);
72186d7f5d3SJohn Marino   mpz_tdiv_q (q, n, dz);
72286d7f5d3SJohn Marino   mpz_clear (dz);
72386d7f5d3SJohn Marino }
72486d7f5d3SJohn Marino 
72586d7f5d3SJohn Marino /* Set inv to the inverse of d, in the style of invert_limb, ie. for
72686d7f5d3SJohn Marino    udiv_qrnnd_preinv.  */
72786d7f5d3SJohn Marino void
mpz_preinv_invert(mpz_t inv,mpz_t d,int numb_bits)72886d7f5d3SJohn Marino mpz_preinv_invert (mpz_t inv, mpz_t d, int numb_bits)
72986d7f5d3SJohn Marino {
73086d7f5d3SJohn Marino   mpz_t  t;
73186d7f5d3SJohn Marino   int    norm;
73286d7f5d3SJohn Marino   ASSERT (SIZ(d) > 0);
73386d7f5d3SJohn Marino 
73486d7f5d3SJohn Marino   norm = numb_bits - mpz_sizeinbase (d, 2);
73586d7f5d3SJohn Marino   ASSERT (norm >= 0);
73686d7f5d3SJohn Marino   mpz_init_set_ui (t, 1L);
73786d7f5d3SJohn Marino   mpz_mul_2exp (t, t, 2*numb_bits - norm);
73886d7f5d3SJohn Marino   mpz_tdiv_q (inv, t, d);
73986d7f5d3SJohn Marino   mpz_set_ui (t, 1L);
74086d7f5d3SJohn Marino   mpz_mul_2exp (t, t, numb_bits);
74186d7f5d3SJohn Marino   mpz_sub (inv, inv, t);
74286d7f5d3SJohn Marino 
74386d7f5d3SJohn Marino   mpz_clear (t);
74486d7f5d3SJohn Marino }
74586d7f5d3SJohn Marino 
74686d7f5d3SJohn Marino /* Remove leading '0' characters from the start of a string, by copying the
74786d7f5d3SJohn Marino    remainder down. */
74886d7f5d3SJohn Marino void
strstrip_leading_zeros(char * s)74986d7f5d3SJohn Marino strstrip_leading_zeros (char *s)
75086d7f5d3SJohn Marino {
75186d7f5d3SJohn Marino   char  c, *p;
75286d7f5d3SJohn Marino 
75386d7f5d3SJohn Marino   p = s;
75486d7f5d3SJohn Marino   while (*s == '0')
75586d7f5d3SJohn Marino     s++;
75686d7f5d3SJohn Marino 
75786d7f5d3SJohn Marino   do
75886d7f5d3SJohn Marino     {
75986d7f5d3SJohn Marino       c = *s++;
76086d7f5d3SJohn Marino       *p++ = c;
76186d7f5d3SJohn Marino     }
76286d7f5d3SJohn Marino   while (c != '\0');
76386d7f5d3SJohn Marino }
76486d7f5d3SJohn Marino 
76586d7f5d3SJohn Marino char *
mpz_get_str(char * buf,int base,mpz_t a)76686d7f5d3SJohn Marino mpz_get_str (char *buf, int base, mpz_t a)
76786d7f5d3SJohn Marino {
76886d7f5d3SJohn Marino   static char  tohex[] = "0123456789abcdef";
76986d7f5d3SJohn Marino 
77086d7f5d3SJohn Marino   mp_limb_t  alimb, *ap;
77186d7f5d3SJohn Marino   int        an, bn, i, j;
77286d7f5d3SJohn Marino   char       *bp;
77386d7f5d3SJohn Marino 
77486d7f5d3SJohn Marino   if (base != 16)
77586d7f5d3SJohn Marino     abort ();
77686d7f5d3SJohn Marino   if (SIZ (a) < 0)
77786d7f5d3SJohn Marino     abort ();
77886d7f5d3SJohn Marino 
77986d7f5d3SJohn Marino   if (buf == 0)
78086d7f5d3SJohn Marino     buf = xmalloc (ABSIZ (a) * (GMP_LIMB_BITS / 4) + 3);
78186d7f5d3SJohn Marino 
78286d7f5d3SJohn Marino   an = ABSIZ (a);
78386d7f5d3SJohn Marino   if (an == 0)
78486d7f5d3SJohn Marino     {
78586d7f5d3SJohn Marino       buf[0] = '0';
78686d7f5d3SJohn Marino       buf[1] = '\0';
78786d7f5d3SJohn Marino       return buf;
78886d7f5d3SJohn Marino     }
78986d7f5d3SJohn Marino 
79086d7f5d3SJohn Marino   ap = PTR (a);
79186d7f5d3SJohn Marino   bn = an * (GMP_LIMB_BITS / 4);
79286d7f5d3SJohn Marino   bp = buf + bn;
79386d7f5d3SJohn Marino 
79486d7f5d3SJohn Marino   for (i = 0; i < an; i++)
79586d7f5d3SJohn Marino     {
79686d7f5d3SJohn Marino       alimb = ap[i];
79786d7f5d3SJohn Marino       for (j = 0; j < GMP_LIMB_BITS / 4; j++)
79886d7f5d3SJohn Marino         {
79986d7f5d3SJohn Marino           bp--;
80086d7f5d3SJohn Marino           *bp = tohex [alimb & 0xF];
80186d7f5d3SJohn Marino           alimb >>= 4;
80286d7f5d3SJohn Marino         }
80386d7f5d3SJohn Marino       ASSERT (alimb == 0);
80486d7f5d3SJohn Marino     }
80586d7f5d3SJohn Marino   ASSERT (bp == buf);
80686d7f5d3SJohn Marino 
80786d7f5d3SJohn Marino   buf[bn] = '\0';
80886d7f5d3SJohn Marino 
80986d7f5d3SJohn Marino   strstrip_leading_zeros (buf);
81086d7f5d3SJohn Marino   return buf;
81186d7f5d3SJohn Marino }
81286d7f5d3SJohn Marino 
81386d7f5d3SJohn Marino void
mpz_out_str(FILE * file,int base,mpz_t a)81486d7f5d3SJohn Marino mpz_out_str (FILE *file, int base, mpz_t a)
81586d7f5d3SJohn Marino {
81686d7f5d3SJohn Marino   char *str;
81786d7f5d3SJohn Marino 
81886d7f5d3SJohn Marino   if (file == 0)
81986d7f5d3SJohn Marino     file = stdout;
82086d7f5d3SJohn Marino 
82186d7f5d3SJohn Marino   str = mpz_get_str (0, 16, a);
82286d7f5d3SJohn Marino   fputs (str, file);
82386d7f5d3SJohn Marino   free (str);
82486d7f5d3SJohn Marino }
82586d7f5d3SJohn Marino 
82686d7f5d3SJohn Marino /* Calculate r satisfying r*d == 1 mod 2^n. */
82786d7f5d3SJohn Marino void
mpz_invert_2exp(mpz_t r,mpz_t a,unsigned long n)82886d7f5d3SJohn Marino mpz_invert_2exp (mpz_t r, mpz_t a, unsigned long n)
82986d7f5d3SJohn Marino {
83086d7f5d3SJohn Marino   unsigned long  i;
83186d7f5d3SJohn Marino   mpz_t  inv, prod;
83286d7f5d3SJohn Marino 
83386d7f5d3SJohn Marino   ASSERT (mpz_odd_p (a));
83486d7f5d3SJohn Marino 
83586d7f5d3SJohn Marino   mpz_init_set_ui (inv, 1L);
83686d7f5d3SJohn Marino   mpz_init (prod);
83786d7f5d3SJohn Marino 
83886d7f5d3SJohn Marino   for (i = 1; i < n; i++)
83986d7f5d3SJohn Marino     {
84086d7f5d3SJohn Marino       mpz_mul (prod, inv, a);
84186d7f5d3SJohn Marino       if (mpz_tstbit (prod, i) != 0)
84286d7f5d3SJohn Marino         mpz_setbit (inv, i);
84386d7f5d3SJohn Marino     }
84486d7f5d3SJohn Marino 
84586d7f5d3SJohn Marino   mpz_mul (prod, inv, a);
84686d7f5d3SJohn Marino   mpz_tdiv_r_2exp (prod, prod, n);
84786d7f5d3SJohn Marino   ASSERT (mpz_cmp_ui (prod, 1L) == 0);
84886d7f5d3SJohn Marino 
84986d7f5d3SJohn Marino   mpz_set (r, inv);
85086d7f5d3SJohn Marino 
85186d7f5d3SJohn Marino   mpz_clear (inv);
85286d7f5d3SJohn Marino   mpz_clear (prod);
85386d7f5d3SJohn Marino }
85486d7f5d3SJohn Marino 
85586d7f5d3SJohn Marino /* Calculate inv satisfying r*a == 1 mod 2^n. */
85686d7f5d3SJohn Marino void
mpz_invert_ui_2exp(mpz_t r,unsigned long a,unsigned long n)85786d7f5d3SJohn Marino mpz_invert_ui_2exp (mpz_t r, unsigned long a, unsigned long n)
85886d7f5d3SJohn Marino {
85986d7f5d3SJohn Marino   mpz_t  az;
86086d7f5d3SJohn Marino   mpz_init_set_ui (az, a);
86186d7f5d3SJohn Marino   mpz_invert_2exp (r, az, n);
86286d7f5d3SJohn Marino   mpz_clear (az);
86386d7f5d3SJohn Marino }
86486d7f5d3SJohn Marino 
86586d7f5d3SJohn Marino /* x=y^z */
86686d7f5d3SJohn Marino void
mpz_pow_ui(mpz_t x,mpz_t y,unsigned long z)86786d7f5d3SJohn Marino mpz_pow_ui (mpz_t x, mpz_t y, unsigned long z)
86886d7f5d3SJohn Marino {
86986d7f5d3SJohn Marino   mpz_t t;
87086d7f5d3SJohn Marino 
87186d7f5d3SJohn Marino   mpz_init_set_ui (t, 1);
87286d7f5d3SJohn Marino   for (; z != 0; z--)
87386d7f5d3SJohn Marino     mpz_mul (t, t, y);
87486d7f5d3SJohn Marino   mpz_set (x, t);
87586d7f5d3SJohn Marino   mpz_clear (t);
87686d7f5d3SJohn Marino }
87786d7f5d3SJohn Marino 
87886d7f5d3SJohn Marino /* x=x+y*z */
87986d7f5d3SJohn Marino void
mpz_addmul_ui(mpz_t x,mpz_t y,unsigned long z)88086d7f5d3SJohn Marino mpz_addmul_ui (mpz_t x, mpz_t y, unsigned long z)
88186d7f5d3SJohn Marino {
88286d7f5d3SJohn Marino   mpz_t t;
88386d7f5d3SJohn Marino 
88486d7f5d3SJohn Marino   mpz_init (t);
88586d7f5d3SJohn Marino   mpz_mul_ui (t, y, z);
88686d7f5d3SJohn Marino   mpz_add (x, x, t);
88786d7f5d3SJohn Marino   mpz_clear (t);
88886d7f5d3SJohn Marino }
88986d7f5d3SJohn Marino 
89086d7f5d3SJohn Marino /* x=floor(y^(1/z)) */
89186d7f5d3SJohn Marino void
mpz_root(mpz_t x,mpz_t y,unsigned long z)89286d7f5d3SJohn Marino mpz_root (mpz_t x, mpz_t y, unsigned long z)
89386d7f5d3SJohn Marino {
89486d7f5d3SJohn Marino   mpz_t t, u;
89586d7f5d3SJohn Marino 
89686d7f5d3SJohn Marino   if (mpz_sgn (y) < 0)
89786d7f5d3SJohn Marino     {
89886d7f5d3SJohn Marino       fprintf (stderr, "mpz_root does not accept negative values\n");
89986d7f5d3SJohn Marino       abort ();
90086d7f5d3SJohn Marino     }
90186d7f5d3SJohn Marino   if (mpz_cmp_ui (y, 1) <= 0)
90286d7f5d3SJohn Marino     {
90386d7f5d3SJohn Marino       mpz_set (x, y);
90486d7f5d3SJohn Marino       return;
90586d7f5d3SJohn Marino     }
90686d7f5d3SJohn Marino   mpz_init (t);
90786d7f5d3SJohn Marino   mpz_init_set (u, y);
90886d7f5d3SJohn Marino   do
90986d7f5d3SJohn Marino     {
91086d7f5d3SJohn Marino       mpz_pow_ui (t, u, z - 1);
91186d7f5d3SJohn Marino       mpz_tdiv_q (t, y, t);
91286d7f5d3SJohn Marino       mpz_addmul_ui (t, u, z - 1);
91386d7f5d3SJohn Marino       mpz_tdiv_q_ui (t, t, z);
91486d7f5d3SJohn Marino       if (mpz_cmp (t, u) >= 0)
91586d7f5d3SJohn Marino 	break;
91686d7f5d3SJohn Marino       mpz_set (u, t);
91786d7f5d3SJohn Marino     }
91886d7f5d3SJohn Marino   while (1);
91986d7f5d3SJohn Marino   mpz_set (x, u);
92086d7f5d3SJohn Marino   mpz_clear (t);
92186d7f5d3SJohn Marino   mpz_clear (u);
92286d7f5d3SJohn Marino }
923