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