home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume40 / fgmp / part01 < prev    next >
Encoding:
Text File  |  1993-11-01  |  51.1 KB  |  2,119 lines

  1. Newsgroups: comp.sources.misc
  2. From: markh@vanbc.wimsey.com (Mark C. Henderson)
  3. Subject: v40i074:  fgmp - Public domain multiple precision integer routines, Part01/01
  4. Message-ID: <1993Nov1.221614.10185@sparky.sterling.com>
  5. X-Md4-Signature: 87bfc6652ee9237438b9af0a463e74a9
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Wimsey Information Services
  8. Date: Mon, 1 Nov 1993 22:16:14 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: markh@vanbc.wimsey.com (Mark C. Henderson)
  12. Posting-number: Volume 40, Issue 74
  13. Archive-name: fgmp/part01
  14. Environment: UNIX, MS-DOS
  15.  
  16. FGMP is a collection of routines for doing multiple precision integer 
  17. arithmetic with the same API as the GNU MP library (Version 1.3.2).
  18. (In fact, only a subset of the functionality of GNU MP is implemented).
  19.  
  20. For instance, you can link the following trivial program with either
  21. this code, or GNU MP and get the same results.
  22.  ------------
  23.  #include <stdio.h>
  24.  #include "gmp.h"
  25.  main()
  26.  {
  27.      MP_INT a; MP_INT b; MP_INT c;
  28.  
  29.      mpz_init_set_ui(&a,1); mpz_init_set_ui(&b,2); mpz_init(&c);
  30.      mpz_add(&c,&a,&b);
  31.      printf("\n%s\n", mpz_get_str(NULL,10,&c));
  32.  }
  33.  ------------
  34.  
  35. FGMP is considerably slower than GNU MP. The main advantage FGMP has over
  36. GNU MP is that FGMP is in the public domain, while GNU MP is covered by
  37. the GPL.
  38.  
  39. FGMP has been ported to the following platforms.:
  40. Linux 0.99 (gcc 2.3, i486)
  41. IBM RS6000/AIX 3.2 (IBM cc, gcc 2.4)
  42. HP/UX 8.0 (HP cc, gcc 2.3)
  43. Sun OS 4.1, Sun 3/4 (sun cc, gcc 2.2)
  44. SGI Irix 4.0.5 (SGI cc, gcc 2.3)
  45. DEC Alpha OSF/1 (DEC cc)
  46.     (only lightly tested, 64 bit longs do make a difference,
  47.      thanks to DEC for providing access on axposf.pa.dec.com).
  48.      Define B64 for this platform.
  49. MSDOS 286 C compiler (see credits above)
  50.  
  51. -------------cut here---------------
  52. #! /bin/sh
  53. # This is a shell archive.  Remove anything before this line, then unpack
  54. # it by saving it into a file and typing "sh file".  To overwrite existing
  55. # files, type "sh file -c".  You can also feed this as standard input via
  56. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  57. # will see the following message at the end:
  58. #        "End of shell archive."
  59. # Contents:  notes gmp.h gmp.c
  60. # Wrapped by mch@squid on Fri Oct 22 13:39:21 1993
  61. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  62. if test -f 'notes' -a "${1}" != "-c" ; then 
  63.   echo shar: Will not clobber existing file \"'notes'\"
  64. else
  65. echo shar: Extracting \"'notes'\" \(3666 characters\)
  66. sed "s/^X//" >'notes' <<'END_OF_FILE'
  67. XWELCOME TO FGMP.
  68. X
  69. XFGMP is a public domain implementation of a subset of the GNU gmp library
  70. Xwith the same API. 
  71. X
  72. XFor instance, you can link the following trivial program with either 
  73. Xthis code, or libgmp.a and get the same results.
  74. X------------
  75. X#include <stdio.h>
  76. X#include "gmp.h"
  77. Xmain()
  78. X{
  79. X    MP_INT a; MP_INT b; MP_INT c;
  80. X
  81. X    mpz_init_set_ui(&a,1); mpz_init_set_ui(&b,2); mpz_init(&c);
  82. X    mpz_add(&c,&a,&b);
  83. X    printf("\n%s\n", mpz_get_str(NULL,10,&c));
  84. X}
  85. X
  86. X------------
  87. X
  88. XFGMP is really in the public domain. You can do whatever you want with
  89. Xit.
  90. X
  91. XI wrote FGMP so that we would all have access to a (truly free)
  92. Ximplementation of this subset of the API of GNU libgmp. I encourage
  93. Xeveryone to distribute this as widely as possible.
  94. X
  95. XIf you need more documentation, I suggest you look at the file
  96. Xgmp.texi which is included with the GNU gmp library. 
  97. X
  98. XYou can send me bug reports, implementations of missing functions, flames
  99. Xand rants by Email. 
  100. X
  101. XAny submissions of new code to be integrated into fgmp must also be 
  102. Xplaced in the public domain (For the particularly dense, you can 
  103. Xrelease a new fgmp yourself under different licensing terms. This 
  104. Xis a condition for including a submission in a release of FGMP that 
  105. XI personally prepare).
  106. X
  107. XMark Henderson <markh@wimsey.bc.ca>
  108. X
  109. X---
  110. XThis is FGMP 1.0
  111. X
  112. XI hearby place this file and all of FGMP in the public domain.
  113. X
  114. XThanks to Paul Rouse <par@r-cube.demon.co.uk> for changes to get fgmp 
  115. Xto work on a 286 MSDOS compiler, the functions mpz_sqrt and 
  116. Xmpz_sqrtrem, plus other general bug fixes. 
  117. X
  118. XThanks also to Erick Gallesio <eg@kaolin.unice.fr> for a fix
  119. Xto mpz_init_set_str
  120. X
  121. XDefine B64 if your "long" type is 64 bits. Otherwise we assume 32
  122. Xbit longs. (The 64 bit version hasn't been tested enough)
  123. X
  124. X
  125. X
  126. XPlatforms:
  127. X
  128. XFGMP has been ported to the following platforms.:
  129. X
  130. XLinux 0.99 (gcc 2.3, i486)
  131. XIBM RS6000/AIX 3.2 (IBM cc, gcc 2.4)
  132. XHP/UX 8.0 (HP cc, gcc 2.3)
  133. XSun OS 4.1, Sun 3/4 (sun cc, gcc 2.2)
  134. XSGI Irix 4.0.5 (SGI cc, gcc 2.3)
  135. XDEC Alpha OSF/1 (DEC cc) 
  136. X    (only lightly tested, 64 bit longs do make a difference,
  137. X     thanks to DEC for providing access on axposf.pa.dec.com). 
  138. X     Define B64 for this platform.
  139. XMSDOS 286 C compiler (see credits above)
  140. X
  141. X---
  142. XSome differences between gmp and fgmp
  143. X
  144. X1. fgmp is considerably slower than gmp
  145. X2. fgmp does not implement the following:
  146. X    all mpq_*
  147. X    internal mpn_* functions
  148. X    mpz_perfect_square_p
  149. X    mpz_inp_raw, mpz_out_raw
  150. X    mp_set_memory_functions, mpz_out_str, mpz_inp_str
  151. X3. fgmp implements the following in addition to the routines in GNU gmp.
  152. X    int mpz_jacobi(MP_INT *a, MP_INT *b)
  153. X    - finds the jacobi symbol (a/b)
  154. X4. mpz_sizeinbase often overestimates the exact value
  155. X
  156. X5. To convert your gmp based program to fgmp (subject to the
  157. Xabove)
  158. X
  159. X- recompile your source. Make sure to include the gmp.h file included
  160. X  with fgmp rather than that included with gmp. (The point is to recompile
  161. X  all files which include gmp.h)
  162. X- link with gmp.o instead of libgmp.a
  163. X
  164. XHere's a complete sorted list of function implemented in fgmp:
  165. X
  166. X_mpz_realloc
  167. Xmpz_abs
  168. Xmpz_add
  169. Xmpz_add_ui
  170. Xmpz_and
  171. Xmpz_clear
  172. Xmpz_cmp
  173. Xmpz_cmp_si
  174. Xmpz_cmp_ui
  175. Xmpz_div
  176. Xmpz_div_2exp
  177. Xmpz_div_ui
  178. Xmpz_divmod
  179. Xmpz_divmod_ui
  180. Xmpz_fac_ui
  181. Xmpz_gcd
  182. Xmpz_gcdext
  183. Xmpz_get_si
  184. Xmpz_get_str
  185. Xmpz_get_ui
  186. Xmpz_init
  187. Xmpz_init_set
  188. Xmpz_init_set_si
  189. Xmpz_init_set_str
  190. Xmpz_init_set_ui
  191. Xmpz_jacobi
  192. Xmpz_mdiv
  193. Xmpz_mdiv_ui
  194. Xmpz_mdivmod
  195. Xmpz_mdivmod_ui
  196. Xmpz_mmod
  197. Xmpz_mmod_ui
  198. Xmpz_mod
  199. Xmpz_mod_2exp
  200. Xmpz_mod_ui
  201. Xmpz_mul
  202. Xmpz_mul_2exp
  203. Xmpz_mul_ui
  204. Xmpz_neg
  205. Xmpz_or
  206. Xmpz_pow_ui
  207. Xmpz_powm
  208. Xmpz_powm_ui
  209. Xmpz_probab_prime_p
  210. Xmpz_random
  211. Xmpz_random2
  212. Xmpz_set
  213. Xmpz_set_si
  214. Xmpz_set_str
  215. Xmpz_set_ui
  216. Xmpz_size
  217. Xmpz_sizeinbase
  218. Xmpz_sqrt
  219. Xmpz_sqrtrem
  220. Xmpz_sub
  221. Xmpz_sub_ui
  222. Xmpz_xor
  223. END_OF_FILE
  224. if test 3666 -ne `wc -c <'notes'`; then
  225.     echo shar: \"'notes'\" unpacked with wrong size!
  226. fi
  227. # end of 'notes'
  228. fi
  229. if test -f 'gmp.h' -a "${1}" != "-c" ; then 
  230.   echo shar: Will not clobber existing file \"'gmp.h'\"
  231. else
  232. echo shar: Extracting \"'gmp.h'\" \(4201 characters\)
  233. sed "s/^X//" >'gmp.h' <<'END_OF_FILE'
  234. X/*
  235. X * FREE GMP - a public domain implementation of a subset of the 
  236. X *           gmp library
  237. X *
  238. X * I hearby place the file in the public domain.
  239. X *
  240. X * Do whatever you want with this code. Change it. Sell it. Claim you
  241. X *  wrote it. 
  242. X * Bugs, complaints, flames, rants: please send email to 
  243. X *    Mark Henderson <markh@wimsey.bc.ca>
  244. X * I'm already aware that fgmp is considerably slower than gmp
  245. X *
  246. X * CREDITS:
  247. X *  Paul Rouse <par@r-cube.demon.co.uk> - generic bug fixes, mpz_sqrt and
  248. X *    mpz_sqrtrem, and modifications to get fgmp to compile on a system 
  249. X *    with int and long of different sizes (specifically MSDOS,286 compiler)
  250. X *  Also see the file "notes" included with the fgmp distribution, for
  251. X *    more credits.
  252. X *
  253. X * VERSION 1.0
  254. X */
  255. X
  256. X#include <stdio.h>
  257. X#include <sys/types.h>
  258. X
  259. X/* for malloc and free */
  260. X#include <stdlib.h>
  261. X
  262. X#ifndef NULL
  263. X#define NULL ((void *)0)
  264. X#endif
  265. X
  266. Xtypedef long mp_limb;
  267. Xtypedef unsigned mp_size;
  268. X
  269. Xtypedef struct mp_int {
  270. X    mp_limb *p;
  271. X    short sn;
  272. X    mp_size sz;
  273. X} MP_INT;
  274. X
  275. X#ifdef __STDC__
  276. X#define PROTO(x) x
  277. X#else
  278. X#define PROTO(x) ()
  279. X#endif
  280. X
  281. Xvoid mpz_init PROTO((MP_INT *s));
  282. Xvoid mpz_init_set PROTO((MP_INT *s, MP_INT *t));
  283. Xvoid mpz_init_set_ui PROTO((MP_INT *s, unsigned long v));
  284. Xvoid mpz_init_set_si PROTO((MP_INT *y, long v));
  285. Xvoid mpz_clear PROTO((MP_INT *s));
  286. Xvoid _mpz_realloc PROTO((MP_INT *x, mp_size size));
  287. Xvoid mpz_set PROTO((MP_INT *y, MP_INT *x));
  288. Xvoid mpz_set_ui PROTO((MP_INT *y, unsigned long v));
  289. Xunsigned long mpz_get_ui PROTO((MP_INT *y));
  290. Xlong mpz_get_si PROTO((MP_INT *y));
  291. Xvoid mpz_set_si PROTO((MP_INT *y, long v));
  292. Xint mpz_cmp PROTO((MP_INT *x, MP_INT *y));
  293. Xvoid mpz_mul PROTO((MP_INT *ww,MP_INT *u, MP_INT *v));
  294. Xvoid mpz_mul_2exp PROTO((MP_INT *z, MP_INT *x, unsigned long e));
  295. Xvoid mpz_div_2exp PROTO((MP_INT *z, MP_INT *x, unsigned long e));
  296. Xvoid mpz_mod_2exp PROTO((MP_INT *z, MP_INT *x, unsigned long e));
  297. Xvoid mpz_add PROTO((MP_INT *zz,MP_INT *x,MP_INT *y));
  298. Xvoid mpz_add_ui PROTO((MP_INT *x,MP_INT *y, unsigned long n));
  299. Xvoid mpz_mul_ui PROTO((MP_INT *x,MP_INT *y, unsigned long n));
  300. Xvoid mpz_sub PROTO((MP_INT *z,MP_INT *x, MP_INT *y));
  301. Xvoid mpz_sub_ui PROTO((MP_INT *x,MP_INT *y, unsigned long n));
  302. Xvoid mpz_div PROTO((MP_INT *q, MP_INT *x, MP_INT *y));
  303. Xvoid mpz_mdiv PROTO((MP_INT *q, MP_INT *x, MP_INT *y));
  304. Xvoid mpz_mod PROTO((MP_INT *r, MP_INT *x, MP_INT *y));
  305. Xvoid mpz_divmod PROTO((MP_INT *q, MP_INT *r, MP_INT *x, MP_INT *y));
  306. Xvoid mpz_mmod PROTO((MP_INT *r, MP_INT *x, MP_INT *y));
  307. Xvoid mpz_mdivmod PROTO((MP_INT *q,MP_INT *r, MP_INT *x, MP_INT *y));
  308. Xvoid mpz_mod_ui PROTO((MP_INT *x,MP_INT *y, unsigned long n));
  309. Xvoid mpz_mmod_ui PROTO((MP_INT *x,MP_INT *y, unsigned long n));
  310. Xvoid mpz_div_ui PROTO((MP_INT *x,MP_INT *y, unsigned long n));
  311. Xvoid mpz_mdiv_ui PROTO((MP_INT *x,MP_INT *y, unsigned long n));
  312. Xvoid mpz_divmod_ui PROTO((MP_INT *q,MP_INT *x,MP_INT *y, unsigned long n));
  313. Xvoid mpz_mdivmod_ui PROTO((MP_INT *q,MP_INT *x,MP_INT *y, unsigned long n));
  314. Xunsigned int mpz_sizeinbase PROTO((MP_INT *x, int base));
  315. Xchar *mpz_get_str PROTO((char *s,  int base, MP_INT *x));
  316. Xint mpz_set_str PROTO((MP_INT *x, char *s, int base));
  317. Xint mpz_init_set_str PROTO((MP_INT *x, char *s, int base));
  318. Xvoid mpz_random PROTO((MP_INT *x, mp_size size));
  319. Xvoid mpz_random2 PROTO((MP_INT *x, mp_size size));
  320. Xsize_t mpz_size PROTO((MP_INT *x));
  321. Xvoid mpz_abs PROTO((MP_INT *, MP_INT *));
  322. Xvoid mpz_neg PROTO((MP_INT *, MP_INT *));
  323. Xvoid mpz_fac_ui PROTO((MP_INT *, unsigned long));
  324. Xvoid mpz_gcd PROTO((MP_INT *, MP_INT *, MP_INT *));
  325. Xvoid mpz_gcdext PROTO((MP_INT *, MP_INT *, MP_INT *, MP_INT *, MP_INT *));
  326. Xint mpz_jacobi PROTO((MP_INT *, MP_INT *));
  327. Xint mpz_cmp_ui PROTO((MP_INT *, unsigned long));
  328. Xint mpz_cmp_si PROTO((MP_INT *, long));
  329. Xvoid mpz_and PROTO((MP_INT *, MP_INT *, MP_INT *));
  330. Xvoid mpz_or PROTO((MP_INT *, MP_INT *, MP_INT *));
  331. Xvoid mpz_xor PROTO((MP_INT *, MP_INT *, MP_INT *));
  332. Xvoid mpz_pow_ui PROTO((MP_INT *, MP_INT *, unsigned long));
  333. Xvoid mpz_powm PROTO((MP_INT *, MP_INT *, MP_INT *, MP_INT *));
  334. Xvoid mpz_powm_ui PROTO((MP_INT *, MP_INT *, unsigned long, MP_INT *));
  335. Xint mpz_probab_prime_p  PROTO((MP_INT *, int));
  336. Xvoid mpz_sqrtrem PROTO((MP_INT *, MP_INT *, MP_INT *));
  337. Xvoid mpz_sqrt PROTO((MP_INT *, MP_INT *));
  338. END_OF_FILE
  339. if test 4201 -ne `wc -c <'gmp.h'`; then
  340.     echo shar: \"'gmp.h'\" unpacked with wrong size!
  341. fi
  342. # end of 'gmp.h'
  343. fi
  344. if test -f 'gmp.c' -a "${1}" != "-c" ; then 
  345.   echo shar: Will not clobber existing file \"'gmp.c'\"
  346. else
  347. echo shar: Extracting \"'gmp.c'\" \(38872 characters\)
  348. sed "s/^X//" >'gmp.c' <<'END_OF_FILE'
  349. X/*
  350. X * FREE GMP - a public domain implementation of a subset of the 
  351. X *           gmp library
  352. X *
  353. X * I hearby place the file in the public domain.
  354. X *
  355. X * Do whatever you want with this code. Change it. Sell it. Claim you
  356. X *  wrote it. 
  357. X * Bugs, complaints, flames, rants: please send email to 
  358. X *    Mark Henderson <markh@wimsey.bc.ca>
  359. X * I'm already aware that fgmp is considerably slower than gmp
  360. X *
  361. X * CREDITS:
  362. X *  Paul Rouse <par@r-cube.demon.co.uk> - generic bug fixes, mpz_sqrt and
  363. X *    mpz_sqrtrem, and modifications to get fgmp to compile on a system 
  364. X *    with int and long of different sizes (specifically MSDOS,286 compiler)
  365. X *  Also see the file "notes" included with the fgmp distribution, for
  366. X *    more credits.
  367. X *
  368. X * VERSION 1.0
  369. X */
  370. X
  371. X#include "gmp.h"
  372. X#ifndef NULL
  373. X#define NULL ((void *)0)
  374. X#endif
  375. X
  376. X#define iabs(x) ((x>0) ? (x) : (-x))
  377. X#define imax(x,y) ((x>y)?x:y)
  378. X#define LONGBITS (sizeof(mp_limb) * 8)
  379. X#define DIGITBITS (LONGBITS - 2)
  380. X#define HALFDIGITBITS ((LONGBITS -2)/2)
  381. X#ifndef init
  382. X#define init(g) { g = (MP_INT *)malloc(sizeof(MP_INT));  mpz_init(g); }
  383. X#endif
  384. X#ifndef clear
  385. X#define clear(g) { mpz_clear(g); free(g); }
  386. X#endif
  387. X#ifndef even
  388. X#define even(a) (!((a)->p[0] & 1))
  389. X#endif
  390. X#ifndef odd
  391. X#define odd(a) (((a)->p[0] & 1))
  392. X#endif
  393. X
  394. X
  395. X#ifndef B64
  396. X/* 
  397. X * The values below are for 32 bit machines (i.e. machines with a 
  398. X *  32 bit long type)
  399. X * You'll need to change them, if you're using something else
  400. X * If DIGITBITS is odd, see the comment at the top of mpz_sqrtrem
  401. X */
  402. X#define LMAX 0x3fffffffL
  403. X#define LC   0xc0000000L
  404. X#define OVMASK 0x2
  405. X#define CMASK (LMAX+1)
  406. X#define FC ((double)CMASK)
  407. X#define HLMAX 0x7fffL
  408. X#define HCMASK (HLMAX + 1)
  409. X#define HIGH(x) (((x) & 0x3fff8000L) >> 15)
  410. X#define LOW(x)  ((x) & 0x7fffL)
  411. X#else
  412. X
  413. X/* 64 bit long type */
  414. X#define LMAX 0x3fffffffffffffffL
  415. X#define LC 0xc000000000000000L
  416. X#define OVMASK 0x2
  417. X#define CMASK (LMAX+1)
  418. X#define FC ((double)CMASK)
  419. X#define HLMAX 0x7fffffffL
  420. X#define HCMASK (HLMAX + 1)
  421. X#define HIGH(x) (((x) & 0x3fffffff80000000L) >> 31)
  422. X#define LOW(x) ((x) & 0x7fffffffL)
  423. X
  424. X#endif
  425. X
  426. X#define hd(x,i)  (((i)>=2*(x->sz))? 0:(((i)%2) ? HIGH((x)->p[(i)/2]) \
  427. X    : LOW((x)->p[(i)/2])))
  428. X#define dg(x,i) ((i < x->sz) ? (x->p)[i] : 0)
  429. X
  430. X#ifdef __GNUC__
  431. X#define INLINE inline
  432. X#else
  433. X#define INLINE
  434. X#endif
  435. X
  436. X#define lowdigit(x) (((x)->p)[0])
  437. X
  438. Xstruct is {
  439. X    mp_limb v;
  440. X    struct is *next;
  441. X};
  442. X
  443. X
  444. XINLINE static void push(i,sp)
  445. Xmp_limb i;struct is **sp;
  446. X{
  447. X    struct is *tmp;
  448. X    tmp = *sp;
  449. X    *sp = (struct is *) malloc(sizeof(struct is));
  450. X    (*sp)->v = i;
  451. X    (*sp)->next=tmp;
  452. X}
  453. X
  454. XINLINE static mp_limb pop(sp)
  455. Xstruct is **sp;
  456. X{
  457. X    struct is *tmp;
  458. X    mp_limb i;
  459. X    if (!(*sp))
  460. X        return (-1);
  461. X    tmp = *sp;
  462. X    *sp = (*sp)->next;
  463. X    i = tmp->v;
  464. X    tmp->v = 0;
  465. X    free(tmp);
  466. X    return i;
  467. X}
  468. X
  469. Xvoid fatal(s)
  470. Xchar *s;
  471. X{
  472. X    fprintf(stderr,"%s\n",s);
  473. X    exit(123);
  474. X}
  475. X
  476. Xvoid mpz_init(s)
  477. XMP_INT *s;
  478. X{
  479. X    s->p = (mp_limb *)malloc(sizeof(mp_limb)*2);
  480. X#ifdef DEBUG
  481. X    printf("malloc: 8 bytes, %08lx\n", (long)(s->p));
  482. X#endif
  483. X    if (!(s->p))
  484. X        fatal("mpz_init: cannot allocate memory");
  485. X    (s->p)[0] = 0;
  486. X    (s->p)[1] = 0;
  487. X    s->sn=0;
  488. X    s->sz=2;
  489. X}
  490. X
  491. Xvoid mpz_init_set(s,t)
  492. XMP_INT *s,*t;
  493. X{
  494. X    int i;
  495. X    s->p = (mp_limb *)malloc(sizeof(mp_limb) * t->sz);
  496. X    if (!(s->p))
  497. X        fatal("mpz_init: cannot allocate memory");
  498. X    for (i=0;i < t->sz ; i++)
  499. X        (s->p)[i] = (t->p)[i];
  500. X
  501. X    s->sn = t->sn;
  502. X    s->sz = t->sz;
  503. X}
  504. X
  505. Xvoid mpz_init_set_ui(s,v)
  506. XMP_INT *s;
  507. Xunsigned long v;
  508. X{
  509. X    s->p = (mp_limb *)malloc(sizeof(mp_limb)*2);
  510. X    if (!(s->p))
  511. X        fatal("mpz_init: cannot allocate memory");
  512. X    s->p[0] = (v & LMAX);
  513. X    s->p[1] = (v & LC) >> DIGITBITS;
  514. X    if (v) 
  515. X        s->sn = 1;
  516. X    else
  517. X        s->sn = 0;
  518. X    s->sz = 2;
  519. X}
  520. X
  521. Xvoid mpz_init_set_si(y,v)
  522. XMP_INT *y;
  523. Xlong v;
  524. X{
  525. X    y->p = (mp_limb *)malloc(sizeof(mp_limb)*2);
  526. X    if (!(y->p))
  527. X        fatal("mpz_init: cannot allocate memory");
  528. X    if (v < 0) {
  529. X        y->sn = -1;
  530. X        y->p[0] = (-v) & LMAX;
  531. X        y->p[1] = ((-v) & LC) >> DIGITBITS;
  532. X    }
  533. X    else if (v > 0) {
  534. X        y->sn = 1;
  535. X        y->p[0] = v & LMAX;
  536. X        y->p[1] = (v & LC) >> DIGITBITS;
  537. X    }
  538. X    else {
  539. X        y->sn=0;
  540. X        y->p[0] = 0;
  541. X        y->p[1] = 0;
  542. X    }
  543. X    y -> sz = 2;
  544. X}
  545. X
  546. X
  547. X
  548. Xvoid mpz_clear(s)
  549. XMP_INT *s;
  550. X{
  551. X#ifdef DEBUG
  552. X    printf("free: %08lx\n", (long)(s->p));
  553. X#endif
  554. X    if (s->p)
  555. X        free(s->p);
  556. X    s->p=NULL;
  557. X    s->sn=0;
  558. X    s->sz=0;
  559. X}
  560. X
  561. X/* number of leading zero bits in digit */
  562. Xstatic int lzb(a)
  563. Xmp_limb a;
  564. X{
  565. X    mp_limb i; int j;
  566. X    j = 0;
  567. X    for (i = ((mp_limb)1 << (DIGITBITS-1)); i && !(a&i) ; j++,i>>=1) 
  568. X        ;
  569. X    return j;
  570. X}
  571. X
  572. Xvoid _mpz_realloc(x,size)
  573. XMP_INT *x; mp_size size;
  574. X{
  575. X    if (size > 1 && x->sz < size) {
  576. X        int i;
  577. X#ifdef DEBUG
  578. X    printf("realloc %08lx to size = %ld ", (long)(x->p),(long)(size));
  579. X#endif
  580. X
  581. X        if (x->p) 
  582. X            x->p=(mp_limb *)realloc(x->p,size * sizeof(mp_limb));
  583. X        else
  584. X            x->p=(mp_limb *)malloc(size * sizeof(mp_limb));
  585. X#ifdef DEBUG
  586. X    printf("becomes %08lx\n", (long)(x->p));
  587. X#endif
  588. X
  589. X        if (!(x->p))
  590. X            fatal("_mpz_realloc: cannot allocate memory");
  591. X        for (i=x->sz;i<size;i++)
  592. X            (x->p)[i] = 0;
  593. X        x->sz = size;
  594. X    }
  595. X}
  596. X
  597. Xvoid dgset(x,i,n)
  598. XMP_INT *x; unsigned int i; mp_limb n;
  599. X{
  600. X    if (n) {
  601. X        if (i >= x->sz) {
  602. X            _mpz_realloc(x,(mp_size)(i+1));
  603. X            x->sz = i+1;
  604. X        }
  605. X        (x->p)[i] = n;
  606. X    }
  607. X}
  608. X
  609. Xstatic unsigned int digits(x)
  610. XMP_INT *x;
  611. X{
  612. X    int i;
  613. X    for (i = (x->sz) - 1; i>=0 && (x->p)[i] == 0 ; i--) 
  614. X        ;
  615. X    return i+1;
  616. X}
  617. X        
  618. X/* y = x */
  619. Xvoid mpz_set(y,x)
  620. XMP_INT *y; MP_INT *x; 
  621. X{
  622. X    unsigned int i,k = x->sz;
  623. X    if (y->sz < k) {
  624. X        k=digits(x);
  625. X        _mpz_realloc(y,(mp_size)k);
  626. X    }
  627. X    if (y->sz > x->sz) {
  628. X        mpz_clear(y); mpz_init(y); _mpz_realloc(y,(mp_size)(x->sz));
  629. X    }
  630. X
  631. X    for (i=0;i < k; i++)
  632. X        (y->p)[i] = (x->p)[i];
  633. X
  634. X    for (;i<y->sz;i++)
  635. X        (y->p)[i] = 0;
  636. X
  637. X    y->sn = x->sn;
  638. X}
  639. X
  640. Xvoid mpz_set_ui(y,v)
  641. XMP_INT *y; unsigned long v; {
  642. X    int i;
  643. X    for (i=1;i<y->sz;i++)
  644. X        y->p[i] = 0;
  645. X    y->p[0] = (v & LMAX);
  646. X    y->p[1] = (v & LC) >> (DIGITBITS);
  647. X    if (v)
  648. X        y->sn=1;
  649. X    else
  650. X        y->sn=0;
  651. X}
  652. X
  653. Xunsigned long mpz_get_ui(y) 
  654. XMP_INT *y; {
  655. X    return (y->p[0] | (y->p[1] << DIGITBITS));
  656. X}
  657. X
  658. Xlong mpz_get_si(y)
  659. XMP_INT *y; {
  660. X    if (y->sn == 0)
  661. X        return 0;
  662. X    else
  663. X        return (y->sn * (y->p[0] | (y->p[1] & 1) << DIGITBITS));
  664. X}
  665. X        
  666. Xvoid mpz_set_si(y,v)
  667. XMP_INT *y; long v; {
  668. X    int i;
  669. X    for (i=1;i<y->sz;i++)
  670. X        y->p[i] = 0;
  671. X    if (v < 0) {
  672. X        y->sn = -1;
  673. X        y->p[0] = (-v) & LMAX;
  674. X        y->p[1] = ((-v) & LC) >> DIGITBITS;
  675. X    }
  676. X    else if (v > 0) {
  677. X        y->sn = 1;
  678. X        y->p[0] = v & LMAX;
  679. X        y->p[1] = (v & LC) >> DIGITBITS;
  680. X    }
  681. X    else {
  682. X        y->sn=0;
  683. X        y->p[0] = 0;
  684. X        y->p[1] = 0;
  685. X    }
  686. X}
  687. X
  688. X/* z = x + y, without regard for sign */
  689. Xstatic void uadd(z,x,y)
  690. XMP_INT *z; MP_INT *x; MP_INT *y;
  691. X{
  692. X    mp_limb c;
  693. X    int i;
  694. X    MP_INT *t;
  695. X
  696. X    if (y->sz < x->sz) {
  697. X        t=x; x=y; y=t;
  698. X    }
  699. X
  700. X    /* now y->sz >= x->sz */
  701. X
  702. X    _mpz_realloc(z,(mp_size)((y->sz)+1));
  703. X
  704. X    c=0;
  705. X    for (i=0;i<x->sz;i++) {
  706. X        if (( z->p[i] = y->p[i] + x->p[i] + c ) & CMASK) {
  707. X            c=1; 
  708. X            (z->p[i]) &=LMAX;
  709. X        }
  710. X        else 
  711. X            c=0;
  712. X    }
  713. X    for (;i<y->sz;i++) {
  714. X        if ((z->p[i] = (y->p[i] + c)) & CMASK)
  715. X            z->p[i]=0;
  716. X        else
  717. X            c=0;
  718. X    }
  719. X    (z->p)[y->sz]=c;
  720. X}
  721. X
  722. X/* z = y - x, ignoring sign */
  723. X/* precondition: abs(y) >= abs(x) */
  724. Xstatic void usub(z,y,x)
  725. XMP_INT *z; MP_INT *y; MP_INT *x; 
  726. X{
  727. X    int i;
  728. X    mp_limb b,m;
  729. X    _mpz_realloc(z,(mp_size)(y->sz));
  730. X    b=0;
  731. X    for (i=0;i<y->sz;i++) {
  732. X        m=((y->p)[i]-b)-dg(x,i);
  733. X        if (m < 0) {
  734. X            b = 1;
  735. X            m = LMAX + 1 + m;
  736. X        }
  737. X        else
  738. X            b = 0;
  739. X        z->p[i] = m;
  740. X    }
  741. X}
  742. X
  743. X/* compare abs(x) and abs(y) */
  744. Xstatic int ucmp(y,x)
  745. XMP_INT *y;MP_INT *x;
  746. X{
  747. X    int i;
  748. X    for (i=imax(x->sz,y->sz)-1;i>=0;i--) {
  749. X        if (dg(y,i) < dg(x,i))
  750. X            return (-1);
  751. X        else if (dg(y,i) > dg(x,i))
  752. X            return 1;
  753. X    }
  754. X    return 0;
  755. X}
  756. X
  757. Xint mpz_cmp(x,y)
  758. XMP_INT *x; MP_INT *y;
  759. X{
  760. X    int abscmp;
  761. X    if (x->sn < 0 && y->sn > 0)
  762. X        return (-1);
  763. X    if (x->sn > 0 && y->sn < 0)
  764. X        return 1;
  765. X    abscmp=ucmp(x,y);
  766. X    if (x->sn >=0 && y->sn >=0)
  767. X        return abscmp;
  768. X    if (x->sn <=0 && y->sn <=0)
  769. X        return (-abscmp);
  770. X}
  771. X    
  772. X/* is abs(x) == 0 */
  773. Xstatic int uzero(x)
  774. XMP_INT *x;
  775. X{
  776. X    int i;
  777. X    for (i=0; i < x->sz; i++)
  778. X        if ((x->p)[i] != 0)
  779. X            return 0;
  780. X    return 1;
  781. X}
  782. X
  783. Xstatic void zero(x)
  784. XMP_INT *x;
  785. X{
  786. X    int i;
  787. X    x->sn=0;
  788. X    for (i=0;i<x->sz;i++)
  789. X        (x->p)[i] = 0;
  790. X}
  791. X
  792. X
  793. X/* w = u * v */
  794. Xvoid mpz_mul(ww,u,v)
  795. XMP_INT *ww;MP_INT *u; MP_INT *v; {
  796. X    int i,j;
  797. X    mp_limb t0,t1,t2,t3;
  798. X    mp_limb cc;
  799. X    MP_INT *w;
  800. X
  801. X    w = (MP_INT *)malloc(sizeof(MP_INT));
  802. X    mpz_init(w);
  803. X    _mpz_realloc(w,(mp_size)(u->sz + v->sz));
  804. X    for (j=0; j < 2*u->sz; j++) {
  805. X        cc = (mp_limb)0;
  806. X        t3 = hd(u,j);
  807. X            for (i=0; i < 2*v->sz; i++) {
  808. X                t0 = t3 * hd(v,i);
  809. X                t1 = HIGH(t0); t0 = LOW(t0);
  810. X                if ((i+j)%2) 
  811. X                    t2 = HIGH(w->p[(i+j)/2]);
  812. X                else
  813. X                    t2 = LOW(w->p[(i+j)/2]);
  814. X                t2 += cc;
  815. X                if (t2 & HCMASK) {
  816. X                    cc = 1; t2&=HLMAX;
  817. X                }
  818. X                else
  819. X                    cc = 0;
  820. X                t2 += t0;
  821. X                if (t2 & HCMASK) {
  822. X                    cc++ ; t2&=HLMAX;
  823. X                }
  824. X                cc+=t1;
  825. X                if ((i+j)%2)
  826. X                    w->p[(i+j)/2] = LOW(w->p[(i+j)/2]) |
  827. X                        (t2 << HALFDIGITBITS);
  828. X                else
  829. X                    w->p[(i+j)/2] = (HIGH(w->p[(i+j)/2]) << HALFDIGITBITS) |
  830. X                        t2;
  831. X                    
  832. X            }
  833. X        if (cc) {
  834. X            if ((j+i)%2) 
  835. X                w->p[(i+j)/2] += cc << HALFDIGITBITS;
  836. X            else
  837. X                w->p[(i+j)/2] += cc;
  838. X        }
  839. X    }
  840. X    w->sn = (u->sn) * (v->sn);
  841. X    if (w != ww) {
  842. X        mpz_set(ww,w);
  843. X        mpz_clear(w);
  844. X        free(w);
  845. X    }
  846. X}
  847. X
  848. X/* n must be < DIGITBITS */
  849. Xstatic void urshift(c1,a,n)
  850. XMP_INT *c1;MP_INT *a;int n;
  851. X{
  852. X    mp_limb cc = 0;
  853. X    if (n >= DIGITBITS)
  854. X        fatal("urshift: n >= DIGITBITS");
  855. X    if (n == 0)
  856. X        mpz_set(c1,a);
  857. X    else {
  858. X        MP_INT c; int i;
  859. X        mp_limb rm = (((mp_limb)1<<n) - 1);
  860. X        mpz_init(&c); _mpz_realloc(&c,(mp_size)(a->sz));
  861. X        for (i=a->sz-1;i >= 0; i--) {
  862. X            c.p[i] = ((a->p[i] >> n) | cc) & LMAX;
  863. X            cc = (a->p[i] & rm) << (DIGITBITS - n);
  864. X        }
  865. X        mpz_set(c1,&c);
  866. X        mpz_clear(&c);
  867. X    }
  868. X}
  869. X    
  870. X/* n must be < DIGITBITS */
  871. Xstatic void ulshift(c1,a,n)
  872. XMP_INT *c1;MP_INT *a;int n;
  873. X{
  874. X    mp_limb cc = 0;
  875. X    if (n >= DIGITBITS)
  876. X        fatal("ulshift: n >= DIGITBITS");
  877. X    if (n == 0)
  878. X        mpz_set(c1,a);
  879. X    else {
  880. X        MP_INT c; int i;
  881. X        mp_limb rm = (((mp_limb)1<<n) - 1) << (DIGITBITS -n);
  882. X        mpz_init(&c); _mpz_realloc(&c,(mp_size)(a->sz + 1));
  883. X        for (i=0;i < a->sz; i++) {
  884. X            c.p[i] = ((a->p[i] << n) | cc) & LMAX;
  885. X            cc = (a->p[i] & rm) >> (DIGITBITS -n);
  886. X        }
  887. X        c.p[i] = cc;
  888. X        mpz_set(c1,&c);
  889. X        mpz_clear(&c);
  890. X    }
  891. X}
  892. X
  893. Xvoid mpz_div_2exp(z,x,e) 
  894. XMP_INT *z; MP_INT *x; unsigned long e;
  895. X{
  896. X    short sn = x->sn;
  897. X    if (e==0)
  898. X        mpz_set(z,x);
  899. X    else {
  900. X        unsigned long i;
  901. X        long digs = (e / DIGITBITS);
  902. X        unsigned long bs = (e % (DIGITBITS));
  903. X        MP_INT y; mpz_init(&y);
  904. X        _mpz_realloc(&y,(mp_size)((x->sz) - digs));
  905. X        for (i=0; i < (x->sz - digs); i++)
  906. X            (y.p)[i] = (x->p)[i+digs];
  907. X        if (bs) {
  908. X            urshift(z,&y,bs);
  909. X        }
  910. X        else {
  911. X            mpz_set(z,&y);
  912. X        }
  913. X        if (uzero(z))
  914. X            z->sn = 0;
  915. X        else
  916. X            z->sn = sn;
  917. X        mpz_clear(&y);
  918. X    }
  919. X}
  920. X
  921. Xvoid mpz_mul_2exp(z,x,e) 
  922. XMP_INT *z; MP_INT *x; unsigned long e;
  923. X{
  924. X    short sn = x->sn;
  925. X    if (e==0)
  926. X        mpz_set(z,x);
  927. X    else {
  928. X        unsigned long i;
  929. X        long digs = (e / DIGITBITS);
  930. X        unsigned long bs = (e % (DIGITBITS));
  931. X        MP_INT y; mpz_init(&y);
  932. X        _mpz_realloc(&y,(mp_size)((x->sz)+digs));
  933. X        for (i=digs;i<((x->sz) + digs);i++)
  934. X            (y.p)[i] = (x->p)[i - digs];
  935. X        if (bs) {
  936. X            ulshift(z,&y,bs);
  937. X        }
  938. X        else {
  939. X            mpz_set(z,&y);
  940. X        }
  941. X        z->sn = sn;
  942. X        mpz_clear(&y);
  943. X    }
  944. X}
  945. X
  946. Xvoid mpz_mod_2exp(z,x,e) 
  947. XMP_INT *z; MP_INT *x; unsigned long e;
  948. X{
  949. X    short sn = x->sn;
  950. X    if (e==0)
  951. X        mpz_set_ui(z,0L);
  952. X    else {
  953. X        unsigned long i;
  954. X        MP_INT y;
  955. X        long digs = (e / DIGITBITS);
  956. X        unsigned long bs = (e % (DIGITBITS));
  957. X        if (digs > x->sz || (digs == (x->sz) && bs)) {
  958. X            mpz_set(z,x);
  959. X            return;
  960. X        }
  961. X            
  962. X        mpz_init(&y);
  963. X        if (bs)
  964. X            _mpz_realloc(&y,(mp_size)(digs+1));
  965. X        else
  966. X            _mpz_realloc(&y,(mp_size)digs);
  967. X        for (i=0; i<digs; i++)
  968. X            (y.p)[i] = (x->p)[i];
  969. X        if (bs) {
  970. X            (y.p)[digs] = ((x->p)[digs]) & (((mp_limb)1 << bs) - 1);
  971. X        }
  972. X        mpz_set(z,&y);
  973. X        if (uzero(z))
  974. X            z->sn = 0;
  975. X        else
  976. X            z->sn = sn;
  977. X        mpz_clear(&y);
  978. X    }
  979. X}
  980. X    
  981. X
  982. X/* internal routine to compute x/y and x%y ignoring signs */
  983. Xstatic void udiv(qq,rr,xx,yy)
  984. XMP_INT *qq; MP_INT *rr; MP_INT *xx; MP_INT *yy;
  985. X{
  986. X    MP_INT *q, *x, *y, *r;
  987. X    int ns,xd,yd,j,f,i,ccc;
  988. X    mp_limb zz,z,qhat,b,u,m;
  989. X    ccc=0;
  990. X
  991. X    if (uzero(yy))
  992. X        return;
  993. X    q = (MP_INT *)malloc(sizeof(MP_INT));
  994. X    r = (MP_INT *)malloc(sizeof(MP_INT));
  995. X    x = (MP_INT *)malloc(sizeof(MP_INT)); 
  996. X    y = (MP_INT *)malloc(sizeof(MP_INT));
  997. X    if (!x || !y || !q || !r)
  998. X        fatal("udiv: cannot allocate memory");
  999. X    mpz_init(q); mpz_init(x);mpz_init(y);mpz_init(r);
  1000. X    _mpz_realloc(x,(mp_size)((xx->sz)+1));
  1001. X    yd = digits(yy);
  1002. X    ns = lzb(yy->p[yd-1]);
  1003. X    ulshift(x,xx,ns);
  1004. X    ulshift(y,yy,ns);
  1005. X    xd = digits(x); 
  1006. X    _mpz_realloc(q,(mp_size)xd);
  1007. X    xd*=2; yd*=2;
  1008. X    z = hd(y,yd-1);;
  1009. X    for (j=(xd-yd);j>=0;j--) {
  1010. X#ifdef DEBUG
  1011. X    printf("y=");
  1012. X    for (i=yd-1;i>=0;i--)
  1013. X        printf(" %04lx", (long)hd(y,i));
  1014. X    printf("\n");
  1015. X    printf("x=");
  1016. X    for (i=xd-1;i>=0;i--)
  1017. X        printf(" %04lx", (long)hd(x,i));
  1018. X    printf("\n");
  1019. X    printf("z=%08lx\n",(long)z);
  1020. X#endif
  1021. X        
  1022. X        if (z == LMAX)
  1023. X            qhat = hd(x,j+yd);
  1024. X        else {
  1025. X            qhat = ((hd(x,j+yd)<< HALFDIGITBITS) + hd(x,j+yd-1)) / (z+1);
  1026. X        }
  1027. X#ifdef DEBUG
  1028. X    printf("qhat=%08lx\n",(long)qhat);
  1029. X    printf("hd=%04lx/%04lx\n",(long)hd(x,j+yd),(long)hd(x,j+yd-1));
  1030. X#endif
  1031. X        b = 0; zz=0;
  1032. X        if (qhat) {
  1033. X            for (i=0; i < yd; i++) {
  1034. X                zz = qhat * hd(y,i);
  1035. X                u = hd(x,i+j);
  1036. X                u-=b;
  1037. X                if (u<0) {
  1038. X                    b=1; u+=HLMAX+1;
  1039. X                }
  1040. X                else
  1041. X                    b=0;
  1042. X                u-=LOW(zz);
  1043. X                if (u < 0) {
  1044. X                    b++;
  1045. X                    u+=HLMAX+1;
  1046. X                }
  1047. X                b+=HIGH(zz);
  1048. X                if ((i+j)%2) 
  1049. X                    x->p[(i+j)/2] = LOW(x->p[(i+j)/2]) | (u << HALFDIGITBITS);
  1050. X                else
  1051. X                    x->p[(i+j)/2] = (HIGH(x->p[(i+j)/2]) 
  1052. X                        << HALFDIGITBITS) | u;
  1053. X            }
  1054. X            if (b) {
  1055. X                if ((j+i)%2) 
  1056. X                    x->p[(i+j)/2] -= b << HALFDIGITBITS;
  1057. X                else
  1058. X                    x->p[(i+j)/2] -= b;
  1059. X            }
  1060. X        }
  1061. X#ifdef DEBUG
  1062. X        printf("x after sub=");
  1063. X        for (i=xd-1;i>=0;i--)
  1064. X            printf(" %04lx", (long)hd(x,i));
  1065. X        printf("\n");
  1066. X#endif
  1067. X        for(;;zz++) {
  1068. X            f=1;
  1069. X            if (!hd(x,j+yd)) {
  1070. X                for(i=yd-1; i>=0; i--) {
  1071. X                    if (hd(x,j+i) > hd(y,i)) {
  1072. X                        f=1;
  1073. X                        break;
  1074. X                    }
  1075. X                    if (hd(x,j+i) < hd(y,i)) {
  1076. X                        f=0;
  1077. X                        break;
  1078. X                    }
  1079. X                }
  1080. X            }
  1081. X            if (!f)
  1082. X                break;
  1083. X            qhat++;
  1084. X            ccc++;
  1085. X#ifdef DEBUG
  1086. X            printf("corrected qhat = %08lx\n", (long)qhat);
  1087. X#endif
  1088. X            b=0;
  1089. X            for (i=0;i<yd;i++) {
  1090. X                m = hd(x,i+j)-hd(y,i)-b;
  1091. X                if (m < 0) {
  1092. X                    b = 1;
  1093. X                    m = HLMAX + 1 + m;
  1094. X                }
  1095. X                else
  1096. X                    b = 0;
  1097. X                if ((i+j)%2) 
  1098. X                    x->p[(i+j)/2] = LOW(x->p[(i+j)/2]) | (m << HALFDIGITBITS);
  1099. X                else
  1100. X                    x->p[(i+j)/2] 
  1101. X                        = (HIGH(x->p[(i+j)/2]) << HALFDIGITBITS) | m;
  1102. X            }
  1103. X            if (b) {
  1104. X                if ((j+i)%2) 
  1105. X                    x->p[(i+j)/2] -= b << HALFDIGITBITS;
  1106. X                else
  1107. X                    x->p[(i+j)/2] -= b;
  1108. X            }
  1109. X#ifdef DEBUG
  1110. X            printf("x after cor=");
  1111. X            for (i=2*(x->sz)-1;i>=0;i--)
  1112. X                printf(" %04lx", (long)hd(x,i));
  1113. X            printf("\n");
  1114. X#endif
  1115. X        }
  1116. X        if (j%2) 
  1117. X            q->p[j/2] |= qhat << HALFDIGITBITS;
  1118. X        else
  1119. X            q->p[j/2] |= qhat;
  1120. X#ifdef DEBUG
  1121. X            printf("x after cor=");
  1122. X            for (i=xd - 1;i>=0;i--)
  1123. X                printf(" %04lx", (long)hd(q,i));
  1124. X            printf("\n");
  1125. X#endif
  1126. X    }
  1127. X    _mpz_realloc(r,(mp_size)(yy->sz));
  1128. X    zero(r);
  1129. X    urshift(r,x,ns);
  1130. X    mpz_set(rr,r);
  1131. X    mpz_set(qq,q);
  1132. X    mpz_clear(x); mpz_clear(y);
  1133. X    mpz_clear(q);  mpz_clear(r);
  1134. X    free(q); free(x); free(y); free(r);
  1135. X}
  1136. X
  1137. Xvoid mpz_add(zz,x,y)
  1138. XMP_INT *zz;MP_INT *x;MP_INT *y;
  1139. X{
  1140. X    int mg;
  1141. X    MP_INT *z;
  1142. X    if (x->sn == 0) {
  1143. X        mpz_set(zz,y);
  1144. X        return;
  1145. X    }
  1146. X    if (y->sn == 0) {
  1147. X        mpz_set(zz,x);
  1148. X        return;
  1149. X    }
  1150. X    z = (MP_INT *)malloc(sizeof(MP_INT));
  1151. X    mpz_init(z);
  1152. X
  1153. X    if (x->sn > 0 && y->sn > 0) {
  1154. X        uadd(z,x,y); z->sn = 1;
  1155. X    }
  1156. X    else if (x->sn < 0 && y->sn < 0) {
  1157. X        uadd(z,x,y); z->sn = -1;
  1158. X    }
  1159. X    else {
  1160. X        /* signs differ */
  1161. X        if ((mg = ucmp(x,y)) == 0) {
  1162. X            zero(z);
  1163. X        }
  1164. X        else if (mg > 0) {  /* abs(y) < abs(x) */
  1165. X            usub(z,x,y);    
  1166. X            z->sn = (x->sn > 0 && y->sn < 0) ? 1 : (-1);
  1167. X        }
  1168. X        else { /* abs(y) > abs(x) */
  1169. X            usub(z,y,x);    
  1170. X            z->sn = (x->sn < 0 && y->sn > 0) ? 1 : (-1);
  1171. X        }
  1172. X    }
  1173. X    mpz_set(zz,z);
  1174. X    mpz_clear(z);
  1175. X    free(z);
  1176. X}
  1177. X
  1178. Xvoid mpz_add_ui(x,y,n)
  1179. XMP_INT *x;MP_INT *y; unsigned long n;
  1180. X{
  1181. X    MP_INT z;
  1182. X    mpz_init_set_ui(&z,n);
  1183. X    mpz_add(x,y,&z);
  1184. X    mpz_clear(&z);
  1185. X}
  1186. X
  1187. Xint mpz_cmp_ui(x,n)
  1188. XMP_INT *x; unsigned long n;
  1189. X{
  1190. X    MP_INT z; int ret;
  1191. X    mpz_init_set_ui(&z,n);
  1192. X    ret=mpz_cmp(x,&z);
  1193. X    mpz_clear(&z);
  1194. X    return ret;
  1195. X}
  1196. X
  1197. Xint mpz_cmp_si(x,n)
  1198. XMP_INT *x; long n;
  1199. X{
  1200. X    MP_INT z; int ret;
  1201. X    mpz_init(&z);
  1202. X    mpz_set_si(&z,n);
  1203. X    ret=mpz_cmp(x,&z);
  1204. X    mpz_clear(&z);
  1205. X    return ret;
  1206. X}
  1207. X
  1208. X
  1209. Xvoid mpz_mul_ui(x,y,n)
  1210. XMP_INT *x;MP_INT *y; unsigned long n;
  1211. X{
  1212. X    MP_INT z;
  1213. X    mpz_init_set_ui(&z,n);
  1214. X    mpz_mul(x,y,&z);
  1215. X    mpz_clear(&z);
  1216. X}
  1217. X    
  1218. X    
  1219. X/* z = x - y  -- just use mpz_add - I'm lazy */
  1220. Xvoid mpz_sub(z,x,y)
  1221. XMP_INT *z;MP_INT *x; MP_INT *y;
  1222. X{
  1223. X    MP_INT u;
  1224. X    mpz_init(&u);
  1225. X    mpz_set(&u,y);
  1226. X    u.sn = -(u.sn);
  1227. X    mpz_add(z,x,&u);
  1228. X    mpz_clear(&u);
  1229. X}
  1230. X
  1231. Xvoid mpz_sub_ui(x,y,n)
  1232. XMP_INT *x;MP_INT *y; unsigned long n;
  1233. X{
  1234. X    MP_INT z;
  1235. X    mpz_init_set_ui(&z,n);
  1236. X    mpz_sub(x,y,&z);
  1237. X    mpz_clear(&z);
  1238. X}
  1239. X
  1240. Xvoid mpz_div(q,x,y)
  1241. XMP_INT *q; MP_INT *x; MP_INT *y;
  1242. X{
  1243. X    MP_INT r; 
  1244. X    short sn1 = x->sn, sn2 = y->sn;
  1245. X    mpz_init(&r);
  1246. X    udiv(q,&r,x,y);
  1247. X    q->sn = sn1*sn2;
  1248. X    if (uzero(q))
  1249. X        q->sn = 0;
  1250. X    mpz_clear(&r);
  1251. X}
  1252. X
  1253. Xvoid mpz_mdiv(q,x,y)
  1254. XMP_INT *q; MP_INT *x; MP_INT *y;
  1255. X{
  1256. X    MP_INT r; 
  1257. X    short sn1 = x->sn, sn2 = y->sn, qsign;
  1258. X    mpz_init(&r);
  1259. X    udiv(q,&r,x,y);
  1260. X    qsign = q->sn = sn1*sn2;
  1261. X    if (uzero(q))
  1262. X        q->sn = 0;
  1263. X    /* now if r != 0 and q < 0 we need to round q towards -inf */
  1264. X    if (!uzero(&r) && qsign < 0) 
  1265. X        mpz_sub_ui(q,q,1L);
  1266. X    mpz_clear(&r);
  1267. X}
  1268. X
  1269. Xvoid mpz_mod(r,x,y)
  1270. XMP_INT *r; MP_INT *x; MP_INT *y;
  1271. X{
  1272. X    MP_INT q;
  1273. X    short sn = x->sn;
  1274. X    mpz_init(&q);
  1275. X    if (x->sn == 0) {
  1276. X        zero(r);
  1277. X        return;
  1278. X    }
  1279. X    udiv(&q,r,x,y);
  1280. X    r->sn = sn;
  1281. X    if (uzero(r))
  1282. X        r->sn = 0;
  1283. X    mpz_clear(&q);
  1284. X}
  1285. X
  1286. Xvoid mpz_divmod(q,r,x,y)
  1287. XMP_INT *q; MP_INT *r; MP_INT *x; MP_INT *y;
  1288. X{
  1289. X    short sn1 = x->sn, sn2 = y->sn;
  1290. X    if (x->sn == 0) {
  1291. X        zero(q);
  1292. X        zero(r);
  1293. X        return;
  1294. X    }
  1295. X    udiv(q,r,x,y);
  1296. X    q->sn = sn1*sn2;
  1297. X    if (uzero(q))
  1298. X        q->sn = 0;
  1299. X    r->sn = sn1;
  1300. X    if (uzero(r))
  1301. X        r->sn = 0;
  1302. X}
  1303. X
  1304. Xvoid mpz_mmod(r,x,y)
  1305. XMP_INT *r; MP_INT *x; MP_INT *y;
  1306. X{
  1307. X    MP_INT q;
  1308. X    short sn1 = x->sn, sn2 = y->sn;
  1309. X    mpz_init(&q);
  1310. X    if (sn1 == 0) {
  1311. X        zero(r);
  1312. X        return;
  1313. X    }
  1314. X    udiv(&q,r,x,y);
  1315. X    if (uzero(r)) {
  1316. X        r->sn = 0;
  1317. X        return;
  1318. X    }
  1319. X    q.sn = sn1*sn2;
  1320. X    if (q.sn > 0) 
  1321. X        r->sn = sn1;
  1322. X    else if (sn1 < 0 && sn2 > 0) {
  1323. X        r->sn = 1;
  1324. X        mpz_sub(r,y,r);
  1325. X    }
  1326. X    else {
  1327. X        r->sn = 1;
  1328. X        mpz_add(r,y,r);
  1329. X    }
  1330. X}
  1331. X
  1332. Xvoid mpz_mdivmod(q,r,x,y)
  1333. XMP_INT *q;MP_INT *r; MP_INT *x; MP_INT *y;
  1334. X{
  1335. X    short sn1 = x->sn, sn2 = y->sn, qsign;
  1336. X    if (sn1 == 0) {
  1337. X        zero(q);
  1338. X        zero(r);
  1339. X        return;
  1340. X    }
  1341. X    udiv(q,r,x,y);
  1342. X    qsign = q->sn = sn1*sn2;
  1343. X    if (uzero(r)) {
  1344. X        /* q != 0, since q=r=0 would mean x=0, which was tested above */
  1345. X        r->sn = 0;
  1346. X        return;
  1347. X    }
  1348. X    if (q->sn > 0) 
  1349. X        r->sn = sn1;
  1350. X    else if (sn1 < 0 && sn2 > 0) {
  1351. X        r->sn = 1;
  1352. X        mpz_sub(r,y,r);
  1353. X    }
  1354. X    else {
  1355. X        r->sn = 1;
  1356. X        mpz_add(r,y,r);
  1357. X    }
  1358. X    if (uzero(q))
  1359. X        q->sn = 0;
  1360. X    /* now if r != 0 and q < 0 we need to round q towards -inf */
  1361. X    if (!uzero(r) && qsign < 0) 
  1362. X        mpz_sub_ui(q,q,1L);
  1363. X}
  1364. X
  1365. Xvoid mpz_mod_ui(x,y,n)
  1366. XMP_INT *x;MP_INT *y; unsigned long n;
  1367. X{
  1368. X    MP_INT z;
  1369. X    mpz_init(&z);
  1370. X    mpz_set_ui(&z,n);
  1371. X    mpz_mod(x,y,&z);
  1372. X    mpz_clear(&z);
  1373. X}
  1374. X
  1375. Xvoid mpz_mmod_ui(x,y,n)
  1376. XMP_INT *x;MP_INT *y; unsigned long n;
  1377. X{
  1378. X    MP_INT z;
  1379. X    mpz_init(&z);
  1380. X    mpz_set_ui(&z,n);
  1381. X    mpz_mmod(x,y,&z);
  1382. X    mpz_clear(&z);
  1383. X}
  1384. X
  1385. Xvoid mpz_div_ui(x,y,n)
  1386. XMP_INT *x;MP_INT *y; unsigned long n;
  1387. X{
  1388. X    MP_INT z;
  1389. X    mpz_init_set_ui(&z,n);
  1390. X    mpz_div(x,y,&z);
  1391. X    mpz_clear(&z);
  1392. X}
  1393. X
  1394. Xvoid mpz_mdiv_ui(x,y,n)
  1395. XMP_INT *x;MP_INT *y; unsigned long n;
  1396. X{
  1397. X    MP_INT z;
  1398. X    mpz_init_set_ui(&z,n);
  1399. X    mpz_mdiv(x,y,&z);
  1400. X    mpz_clear(&z);
  1401. X}
  1402. Xvoid mpz_divmod_ui(q,x,y,n)
  1403. XMP_INT *q;MP_INT *x;MP_INT *y; unsigned long n;
  1404. X{
  1405. X    MP_INT z;
  1406. X    mpz_init_set_ui(&z,n);
  1407. X    mpz_divmod(q,x,y,&z);
  1408. X    mpz_clear(&z);
  1409. X}
  1410. X
  1411. Xvoid mpz_mdivmod_ui(q,x,y,n)
  1412. XMP_INT *q;MP_INT *x;MP_INT *y; unsigned long n;
  1413. X{
  1414. X    MP_INT z;
  1415. X    mpz_init_set_ui(&z,n);
  1416. X    mpz_mdivmod(q,x,y,&z);
  1417. X    mpz_clear(&z);
  1418. X}
  1419. X
  1420. X
  1421. X/* 2<=base <=36 - this overestimates the optimal value, which is OK */
  1422. Xunsigned int mpz_sizeinbase(x,base)
  1423. XMP_INT *x; int base;
  1424. X{
  1425. X    int i,j;
  1426. X    int bits = digits(x) * DIGITBITS;
  1427. X    if (base < 2 || base > 36)
  1428. X        fatal("mpz_sizeinbase: invalid base");
  1429. X    for (j=0,i=1; i<=base;i*=2,j++)
  1430. X        ;
  1431. X    return ((bits)/(j-1)+1);
  1432. X}
  1433. X
  1434. Xchar *mpz_get_str(s,base,x)
  1435. Xchar *s;  int base; MP_INT *x; {
  1436. X    MP_INT xx,q,r,bb;
  1437. X    char *p,*t,*ps;
  1438. X    int sz = mpz_sizeinbase(x,base);
  1439. X    mp_limb d;
  1440. X    if (base < 2 || base > 36)
  1441. X        return s;
  1442. X    t = (char *)malloc(sz+2);
  1443. X    if (!t) 
  1444. X        fatal("cannot allocate memory in mpz_get_str");
  1445. X    if (!s) {
  1446. X        s=(char *)malloc(sz+2);
  1447. X        if (!s) 
  1448. X            fatal("cannot allocate memory in mpz_get_str");
  1449. X    }
  1450. X    if (uzero(x)) {
  1451. X        *s='0';
  1452. X        *(s+1)='\0';
  1453. X        return s;
  1454. X    }
  1455. X    mpz_init(&xx); mpz_init(&q); mpz_init(&r); mpz_init(&bb);
  1456. X    mpz_set(&xx,x);
  1457. X    mpz_set_ui(&bb,(unsigned long)base);
  1458. X    ps = s;
  1459. X    if (x->sn < 0) {
  1460. X        *ps++= '-';
  1461. X        xx.sn = 1;
  1462. X    }
  1463. X    p = t;
  1464. X    while (!uzero(&xx)) {
  1465. X        udiv(&xx,&r,&xx,&bb);
  1466. X        d = r.p[0];
  1467. X        if (d < 10) 
  1468. X            *p++  = (char) (r.p[0] + '0');
  1469. X        else 
  1470. X            *p++  = (char) (r.p[0] + -10 + 'a');
  1471. X    }
  1472. X
  1473. X    p--;
  1474. X    for (;p>=t;p--,ps++)
  1475. X        *ps = *p;
  1476. X    *ps='\0';
  1477. X    
  1478. X    mpz_clear(&q); mpz_clear(&r); free(t);  
  1479. X    return s;
  1480. X}
  1481. X
  1482. X
  1483. Xint mpz_set_str(x,s,base)
  1484. XMP_INT *x; char *s; int base;
  1485. X{
  1486. X    int l,i;
  1487. X    int retval = 0;
  1488. X    MP_INT t,m,bb;
  1489. X    short sn;
  1490. X    unsigned int k;
  1491. X    mpz_init(&m);
  1492. X    mpz_init(&t);
  1493. X    mpz_init(&bb);
  1494. X    mpz_set_ui(&m,1L);
  1495. X    zero(x);
  1496. X    while (*s==' ' || *s=='\t' || *s=='\n')
  1497. X        s++;
  1498. X    if (*s == '-') {
  1499. X        sn = -1; s++;
  1500. X    }
  1501. X    else
  1502. X        sn = 1;
  1503. X    if (base == 0) {
  1504. X        if (*s == '0') {
  1505. X            if (*(s+1) == 'x' || *(s+1) == 'X') {
  1506. X                base = 16;
  1507. X                s+=2;   /* toss 0x */
  1508. X            }
  1509. X            else {
  1510. X                base = 8;
  1511. X                s++;    /* toss 0 */
  1512. X            }
  1513. X        }
  1514. X        else
  1515. X            base=10;
  1516. X    }
  1517. X    if (base < 2 || base > 36)
  1518. X        fatal("mpz_set_str: invalid base");
  1519. X    mpz_set_ui(&bb,(unsigned long)base);
  1520. X    l=strlen(s);
  1521. X    for (i = l-1; i>=0; i--) {
  1522. X        if (s[i]==' ' || s[i]=='\t' || s[i]=='\n') 
  1523. X            continue;
  1524. X        if (s[i] >= '0' && s[i] <= '9')
  1525. X            k = (unsigned int)s[i] - (unsigned int)'0';
  1526. X        else if (s[i] >= 'A' && s[i] <= 'Z')
  1527. X            k = (unsigned int)s[i] - (unsigned int)'A'+10;
  1528. X        else if (s[i] >= 'a' && s[i] <= 'z')
  1529. X            k = (unsigned int)s[i] - (unsigned int)'a'+10;
  1530. X        else {
  1531. X            retval = (-1);
  1532. X            break;
  1533. X        }
  1534. X        if (k >= base) {
  1535. X            retval = (-1);
  1536. X            break;
  1537. X        }
  1538. X        mpz_mul_ui(&t,&m,(unsigned long)k);
  1539. X        mpz_add(x,x,&t);
  1540. X        mpz_mul(&m,&m,&bb);
  1541. X#ifdef DEBUG
  1542. X        printf("k=%d\n",k);
  1543. X        printf("t=%s\n",mpz_get_str(NULL,10,&t));
  1544. X        printf("x=%s\n",mpz_get_str(NULL,10,x));
  1545. X        printf("m=%s\n",mpz_get_str(NULL,10,&m));
  1546. X#endif
  1547. X    }
  1548. X    if (x->sn)
  1549. X        x->sn = sn;
  1550. X    mpz_clear(&m);
  1551. X    mpz_clear(&bb);
  1552. X    mpz_clear(&t);
  1553. X    return retval;
  1554. X}
  1555. X
  1556. Xint mpz_init_set_str(x,s,base)
  1557. XMP_INT *x; char *s; int base;
  1558. X{
  1559. X    mpz_init(x); return mpz_set_str(x,s,base);
  1560. X}
  1561. X
  1562. X#define mpz_randombyte (rand()& 0xff)
  1563. X
  1564. Xvoid mpz_random(x,size)
  1565. XMP_INT *x; unsigned int size;
  1566. X{
  1567. X    unsigned int bits = size * LONGBITS;
  1568. X    unsigned int digits = bits/DIGITBITS;
  1569. X    unsigned int oflow = bits % DIGITBITS;
  1570. X    unsigned int i,j;
  1571. X    long t;
  1572. X    if (oflow)
  1573. X        digits++;
  1574. X    _mpz_realloc(x,(mp_size)digits);
  1575. X
  1576. X    for (i=0; i<digits; i++) {
  1577. X        t = 0;
  1578. X        for (j=0; j < DIGITBITS; j+=8)
  1579. X            t = (t << 8) | mpz_randombyte; 
  1580. X        (x->p)[i] = t & LMAX;
  1581. X    }
  1582. X    if (oflow) 
  1583. X        (x->p)[digits-1] &= (((mp_limb)1 << oflow) - 1);
  1584. X}
  1585. Xvoid mpz_random2(x,size)
  1586. XMP_INT *x; unsigned int size;
  1587. X{
  1588. X    unsigned int bits = size * LONGBITS;
  1589. X    unsigned int digits = bits/DIGITBITS;
  1590. X    unsigned int oflow = bits % DIGITBITS;
  1591. X    unsigned int i,j;
  1592. X    long t;
  1593. X    if (oflow)
  1594. X        digits++;
  1595. X    _mpz_realloc(x,(mp_size)digits);
  1596. X
  1597. X    for (i=0; i<digits; i++) {
  1598. X        t = 0;
  1599. X        for (j=0; j < DIGITBITS; j+=8)
  1600. X            t = (t << 8) | mpz_randombyte; 
  1601. X        (x->p)[i] = (t & LMAX) % 2;
  1602. X    }
  1603. X    if (oflow) 
  1604. X        (x->p)[digits-1] &= (((mp_limb)1 << oflow) - 1);
  1605. X}
  1606. X
  1607. Xsize_t mpz_size(x)
  1608. XMP_INT *x;
  1609. X{
  1610. X    int bits = (x->sz)*DIGITBITS;
  1611. X    size_t r;
  1612. X    
  1613. X    r = bits/LONGBITS;
  1614. X    if (bits % LONGBITS)
  1615. X        r++;
  1616. X    return r;
  1617. X}
  1618. X
  1619. Xvoid mpz_abs(x,y)
  1620. XMP_INT *x; MP_INT *y;
  1621. X{
  1622. X    if (x!=y)
  1623. X        mpz_set(x,y);
  1624. X    if (uzero(x))
  1625. X        x->sn = 0;
  1626. X    else
  1627. X        x->sn = 1;
  1628. X}
  1629. X
  1630. Xvoid mpz_neg(x,y)
  1631. XMP_INT *x; MP_INT *y;
  1632. X{
  1633. X    if (x!=y)
  1634. X        mpz_set(x,y);
  1635. X    x->sn = -(y->sn);
  1636. X}
  1637. X
  1638. Xvoid mpz_fac_ui(x,n)
  1639. XMP_INT *x; unsigned long n;
  1640. X{
  1641. X    mpz_set_ui(x,1L);
  1642. X    if (n==0 || n == 1)
  1643. X        return;
  1644. X    for (;n>1;n--)
  1645. X        mpz_mul_ui(x,x,n);
  1646. X}
  1647. X
  1648. Xvoid mpz_gcd(gg,aa,bb)
  1649. XMP_INT *gg;
  1650. XMP_INT *aa;
  1651. XMP_INT *bb;
  1652. X{
  1653. X    MP_INT *g,*t,*a,*b;
  1654. X    int freeg;
  1655. X    
  1656. X    t = (MP_INT *)malloc(sizeof(MP_INT));
  1657. X    g = (MP_INT *)malloc(sizeof(MP_INT));
  1658. X    a = (MP_INT *)malloc(sizeof(MP_INT));
  1659. X    b = (MP_INT *)malloc(sizeof(MP_INT));
  1660. X    if (!a || !b || !g || !t)
  1661. X        fatal("mpz_gcd: cannot allocate memory");
  1662. X    mpz_init(g); mpz_init(t); mpz_init(a); mpz_init(b);
  1663. X    mpz_abs(a,aa); mpz_abs(b,bb); 
  1664. X
  1665. X    while (!uzero(b)) {
  1666. X        mpz_mod(t,a,b);
  1667. X        mpz_set(a,b);
  1668. X        mpz_set(b,t);
  1669. X    }
  1670. X    
  1671. X    mpz_set(gg,a);
  1672. X    mpz_clear(g); mpz_clear(t); mpz_clear(a); mpz_clear(b);
  1673. X    free(g); free(t); free(a); free(b);
  1674. X}
  1675. X
  1676. Xvoid mpz_gcdext(gg,xx,yy,aa,bb)
  1677. XMP_INT *gg,*xx,*yy,*aa,*bb;
  1678. X{
  1679. X    MP_INT *x, *y, *g, *u, *q;
  1680. X
  1681. X    if (uzero(bb)) {
  1682. X        mpz_set(gg,aa);
  1683. X        mpz_set_ui(xx,1L);
  1684. X        if (yy)
  1685. X            mpz_set_ui(yy,0L);
  1686. X        return;
  1687. X    }
  1688. X    
  1689. X    g = (MP_INT *)malloc(sizeof(MP_INT)); mpz_init(g);
  1690. X    q = (MP_INT *)malloc(sizeof(MP_INT)); mpz_init(q);
  1691. X    y = (MP_INT *)malloc(sizeof(MP_INT)); mpz_init(y);
  1692. X    x = (MP_INT *)malloc(sizeof(MP_INT)); mpz_init(x);
  1693. X    u = (MP_INT *)malloc(sizeof(MP_INT)); mpz_init(u);
  1694. X
  1695. X    if (!g || !q || !y || !x || !u)
  1696. X        fatal("mpz_gcdext: cannot allocate memory");
  1697. X
  1698. X    mpz_divmod(q,u,aa,bb);
  1699. X    mpz_gcdext(g,x,y,bb,u);
  1700. X    if (yy) {
  1701. X        mpz_mul(u,q,y);
  1702. X        mpz_sub(yy,x,u);
  1703. X    }
  1704. X    mpz_set(xx,y);
  1705. X    mpz_set(gg,g);
  1706. X    mpz_clear(g); mpz_clear(q); mpz_clear(y); mpz_clear(x); mpz_clear(u);
  1707. X    free(g); free(q); free(y); free(x); free(u);
  1708. X}
  1709. X
  1710. X
  1711. X/*
  1712. X *    a is a quadratic residue mod b if
  1713. X *    x^2 = a mod b      has an integer solution x.
  1714. X *
  1715. X *    J(a,b) = if a==1 then 1 else
  1716. X *             if a is even then J(a/2,b) * ((-1)^(b^2-1)/8))
  1717. X *             else J(b mod a, a) * ((-1)^((a-1)*(b-1)/4)))
  1718. X *
  1719. X *  b>0  b odd
  1720. X *
  1721. X *
  1722. X */
  1723. X
  1724. Xint mpz_jacobi(ac,bc)
  1725. XMP_INT *ac, *bc;
  1726. X{
  1727. X    int sgn = 1;
  1728. X    unsigned long c;
  1729. X    MP_INT *t,*a,*b; 
  1730. X    if (bc->sn <=0)
  1731. X        fatal("mpz_jacobi call with b <= 0");
  1732. X    if (even(bc))
  1733. X        fatal("mpz_jacobi call with b even");
  1734. X
  1735. X    init(t); init(a); init(b);
  1736. X
  1737. X    /* if ac < 0, then we use the fact that 
  1738. X     *  (-1/b)= -1 if b mod 4 == 3
  1739. X     *          +1 if b mod 4 == 1
  1740. X     */
  1741. X
  1742. X    if (mpz_cmp_ui(ac,0L) < 0 && (lowdigit(bc) % 4) == 3)
  1743. X        sgn=-sgn;
  1744. X
  1745. X    mpz_abs(a,ac); mpz_set(b,bc);
  1746. X
  1747. X    /* while (a > 1) { */
  1748. X    while(mpz_cmp_ui(a,1L) > 0) {
  1749. X
  1750. X        if (even(a)) {
  1751. X
  1752. X            /* c = b % 8 */
  1753. X            c = lowdigit(b) & 0x07;
  1754. X
  1755. X            /* b odd, then (b^2-1)/8 is even iff (b%8 == 3,5) */
  1756. X
  1757. X            /* if b % 8 == 3 or 5 */
  1758. X            if (c == 3 || c == 5)
  1759. X                sgn = -sgn;
  1760. X
  1761. X            /* a = a / 2 */
  1762. X            mpz_div_2exp(a,a,1L); 
  1763. X
  1764. X        } 
  1765. X        else {
  1766. X            /* note: (a-1)(b-1)/4 odd iff a mod 4==b mod 4==3 */
  1767. X
  1768. X            /* if a mod 4 == 3 and b mod 4 == 3 */
  1769. X            if (((lowdigit(a) & 3) == 3) && ((lowdigit(b) & 3) == 3))
  1770. X                sgn = -sgn;
  1771. X
  1772. X            /* set (a,b) = (b mod a,a) */
  1773. X            mpz_set(t,a); mpz_mmod(a,b,t); mpz_set(b,t);
  1774. X        } 
  1775. X    }
  1776. X
  1777. X    /* if a == 0 then sgn = 0 */
  1778. X    if (uzero(a))
  1779. X        sgn=0;
  1780. X
  1781. X    clear(t); clear(a); clear(b);
  1782. X    return (sgn);
  1783. X}
  1784. X
  1785. Xvoid mpz_and(z,x,y) /* not the most efficient way to do this */
  1786. XMP_INT *z,*x,*y;
  1787. X{
  1788. X    int i,sz;
  1789. X    sz = imax(x->sz, y->sz);
  1790. X    _mpz_realloc(z,(mp_size)sz);
  1791. X    for (i=0; i < sz; i++)
  1792. X        (z->p)[i] = dg(x,i) & dg(y,i);
  1793. X    if (x->sn < 0 && y->sn < 0)
  1794. X        z->sn = (-1);
  1795. X    else
  1796. X        z->sn = 1;
  1797. X    if (uzero(z))
  1798. X        z->sn = 0;
  1799. X}
  1800. X
  1801. Xvoid mpz_or(z,x,y)  /* not the most efficient way to do this */
  1802. XMP_INT *z,*x,*y;
  1803. X{
  1804. X    int i,sz;
  1805. X    sz = imax(x->sz, y->sz);
  1806. X    _mpz_realloc(z,(mp_size)sz);
  1807. X    for (i=0; i < sz; i++)
  1808. X        (z->p)[i] = dg(x,i) | dg(y,i);
  1809. X    if (x->sn < 0 || y->sn < 0)
  1810. X        z->sn = (-1);
  1811. X    else
  1812. X        z->sn = 1;
  1813. X    if (uzero(z))
  1814. X        z->sn = 0;
  1815. X}
  1816. X
  1817. Xvoid mpz_xor(z,x,y)  /* not the most efficient way to do this */
  1818. XMP_INT *z,*x,*y;
  1819. X{
  1820. X    int i,sz;
  1821. X    sz = imax(x->sz, y->sz);
  1822. X    _mpz_realloc(z,(mp_size)sz);
  1823. X    for (i=0; i < sz; i++)
  1824. X        (z->p)[i] = dg(x,i) ^ dg(y,i);
  1825. X    if ((x->sn <= 0 && y->sn > 0) || (x->sn > 0 && y->sn <=0))
  1826. X        z->sn = (-1);
  1827. X    else
  1828. X        z->sn = 1;
  1829. X    if (uzero(z))
  1830. X        z->sn = 0;
  1831. X}
  1832. Xvoid mpz_pow_ui(zz,x,e)
  1833. XMP_INT *zz, *x;
  1834. Xunsigned long e;
  1835. X{
  1836. X    MP_INT *t;
  1837. X    unsigned long mask = (1L<< (LONGBITS-1));
  1838. X    
  1839. X    if (e==0) {
  1840. X        mpz_set_ui(zz,1L);
  1841. X        return;
  1842. X    }
  1843. X
  1844. X    init(t);
  1845. X    mpz_set(t,x);
  1846. X    for (;!(mask &e); mask>>=1) 
  1847. X        ;
  1848. X    mask>>=1;
  1849. X    for (;mask!=0; mask>>=1) {
  1850. X        mpz_mul(t,t,t);
  1851. X        if (e & mask)
  1852. X            mpz_mul(t,t,x);
  1853. X    }
  1854. X    mpz_set(zz,t);
  1855. X    clear(t);
  1856. X}
  1857. X
  1858. Xvoid mpz_powm(zz,x,ee,n)
  1859. XMP_INT *zz,*x,*ee,*n;
  1860. X{
  1861. X    MP_INT *t,*e;
  1862. X    struct is *stack = NULL;
  1863. X    int k,i;
  1864. X    
  1865. X    if (uzero(ee)) {
  1866. X        mpz_set_ui(zz,1L);
  1867. X        return;
  1868. X    }
  1869. X
  1870. X    if (ee->sn < 0) {
  1871. X        return;
  1872. X    }
  1873. X    init(e); init(t); mpz_set(e,ee);
  1874. X
  1875. X    for (k=0;!uzero(e);k++,mpz_div_2exp(e,e,1L))
  1876. X        push(lowdigit(e) & 1,&stack);
  1877. X    k--;
  1878. X    i=pop(&stack);
  1879. X
  1880. X    mpz_mod(t,x,n);  /* t=x%n */
  1881. X
  1882. X    for (i=k-1;i>=0;i--) {
  1883. X        mpz_mul(t,t,t); 
  1884. X        mpz_mod(t,t,n);  
  1885. X        if (pop(&stack)) {
  1886. X            mpz_mul(t,t,x); 
  1887. X            mpz_mod(t,t,n);
  1888. X        }
  1889. X    }
  1890. X    mpz_set(zz,t);
  1891. X    clear(t);
  1892. X}
  1893. X
  1894. Xvoid mpz_powm_ui(z,x,e,n)
  1895. XMP_INT *z,*x,*n; unsigned long e;
  1896. X{
  1897. X    MP_INT f;
  1898. X    mpz_init(&f);
  1899. X    mpz_set_ui(&f,e);
  1900. X    mpz_powm(z,x,&f,n);
  1901. X    mpz_clear(&f);
  1902. X}
  1903. X    
  1904. X    
  1905. X
  1906. X/* Miller-Rabin */
  1907. Xstatic int witness(x,n)
  1908. XMP_INT *x, *n;
  1909. X{
  1910. X    MP_INT *t,*e, *e1;
  1911. X    struct is *stack = NULL;
  1912. X    int trivflag = 0;
  1913. X    int k,i;
  1914. X    
  1915. X    init(e1); init(e); init(t); mpz_sub_ui(e,n,1L); mpz_set(e1,e);
  1916. X
  1917. X    for (k=0;!uzero(e);k++,mpz_div_2exp(e,e,1L))
  1918. X        push(lowdigit(e) & 1,&stack);
  1919. X    k--;
  1920. X    i=pop(&stack);
  1921. X
  1922. X    mpz_mod(t,x,n);  /* t=x%n */
  1923. X
  1924. X    for (i=k-1;i>=0;i--) {
  1925. X        trivflag = !mpz_cmp_ui(t,1L) || !mpz_cmp(t,e1);
  1926. X        mpz_mul(t,t,t); mpz_mod(t,t,n);  
  1927. X        if (!trivflag && !mpz_cmp_ui(t,1L)) {
  1928. X            clear(t); clear(e); clear(e1);
  1929. X            return 1;
  1930. X        }
  1931. X            
  1932. X        if (pop(&stack)) {
  1933. X            mpz_mul(t,t,x); 
  1934. X            mpz_mod(t,t,n);
  1935. X        }
  1936. X    }
  1937. X    if (mpz_cmp_ui(t,1L))  { /* t!=1 */
  1938. X        clear(t); clear(e); clear(e1);
  1939. X        return 1;
  1940. X    }
  1941. X    else {
  1942. X        clear(t); clear(e); clear(e1);
  1943. X        return 0;
  1944. X    }
  1945. X}
  1946. X
  1947. Xunsigned long smallp[] = {2,3,5,7,11,13,17};
  1948. Xint mpz_probab_prime_p(nn,s)
  1949. XMP_INT *nn; int s;
  1950. X{   
  1951. X    MP_INT *a,*n;
  1952. X    int j,k,i;
  1953. X    long t;
  1954. X
  1955. X    if (uzero(nn))
  1956. X        return 0;
  1957. X    init(n); mpz_abs(n,nn);
  1958. X    if (!mpz_cmp_ui(n,1L)) {
  1959. X        clear(n);
  1960. X        return 0;
  1961. X    }
  1962. X    init(a);
  1963. X    for (i=0;i<sizeof(smallp)/sizeof(unsigned long); i++) {
  1964. X        mpz_mod_ui(a,n,smallp[i]);
  1965. X        if (uzero(a)) {
  1966. X            clear(a); clear(n); return 0;
  1967. X        }
  1968. X    }
  1969. X    _mpz_realloc(a,(mp_size)(n->sz));
  1970. X    for (k=0; k<s; k++) {
  1971. X
  1972. X        /* generate a "random" a */
  1973. X            for (i=0; i<n->sz; i++) {
  1974. X                t = 0;
  1975. X                for (j=0; j < DIGITBITS; j+=8)
  1976. X                    t = (t << 8) | mpz_randombyte; 
  1977. X                (a->p)[i] = t & LMAX;
  1978. X            }
  1979. X            a->sn = 1;
  1980. X            mpz_mod(a,a,n);
  1981. X
  1982. X        if (witness(a,n)) {
  1983. X            clear(a); clear(n);
  1984. X            return 0;
  1985. X        }
  1986. X    }
  1987. X    clear(a);clear(n);
  1988. X    return 1;
  1989. X}   
  1990. X
  1991. X
  1992. X/* Square roots are found by Newton's method, but since we are working
  1993. X * with integers we have to consider carefully the termination conditions.
  1994. X * If we are seeking x = floor(sqrt(a)), the iteration is
  1995. X *     x_{n+1} = floor ((floor (a/x_n) + x_n)/2) == floor ((a + x_n^2)/(2*x))
  1996. X * If eps_n represents the error (exactly, eps_n and sqrt(a) real) in the 
  1997. X *  form:
  1998. X *     x_n = (1 + eps_n) sqrt(a)
  1999. X * then it is easy to show that for a >= 4
  2000. X *     if 0 <= eps_n, then either 0 <= eps_{n+1} <= (eps_n^2)/2
  2001. X *                         or x_{n+1} = floor (sqrt(a))
  2002. X *     if x_n = floor (sqrt(a)), then either x_{n+1} = floor (sqrt(a))
  2003. X *                               or x_{n+1} = floor (sqrt(a)) + 1
  2004. X * Therefore, if the initial approximation x_0 is chosen so that
  2005. X *     0 <= eps_0 <= 1/2
  2006. X * then the error remains postive and monotonically decreasing with
  2007. X *     eps_n <= 2 ^ (-(2^(n+1) - 1))
  2008. X * unless we reach the correct floor(sqrt(a)), after which we may oscillate
  2009. X * between it and the value one higher.
  2010. X * We choose the number of iterations, k, to guarantee
  2011. X *     eps_k sqrt(a) < 1,  so x_k <= floor (sqrt (a)) + 1
  2012. X * so finally x_k is either the required answer or one too big (which we
  2013. X * check by a simple multiplication and comparison).
  2014. X *
  2015. X * The calculation of the initial approximation *assumes* DIGITBITS is even.
  2016. X * It probably always will be, so for now let's leave the code simple,
  2017. X * clear and all reachable in testing!
  2018. X */
  2019. Xvoid mpz_sqrtrem (root, rem, a)
  2020. X    MP_INT *root;
  2021. X    MP_INT *rem;
  2022. X    MP_INT *a;
  2023. X{
  2024. X    MP_INT tmp;
  2025. X    MP_INT r;
  2026. X    mp_limb z;
  2027. X    unsigned long j, h;
  2028. X    int k;
  2029. X
  2030. X    if (a->sn < 0)
  2031. X        /* Negative operand, nothing correct we can do */
  2032. X        return;
  2033. X
  2034. X    /* Now, a good enough approximation to the root is obtained by writing
  2035. X     *     a = z * 2^(2j) + y,  4 <= z <= 15 and 0 <= y < 2^(2j)
  2036. X     * then taking
  2037. X     *     root = ciel (sqrt(z+1)) * 2^j
  2038. X     */
  2039. X
  2040. X    for (j = a->sz - 1; j != 0 && (a->p)[j] == 0; j--);
  2041. X    z = (a->p)[j];
  2042. X    if (z < 4) {
  2043. X        if (j == 0) {
  2044. X            /* Special case for small operand (main interation not valid) */
  2045. X            mpz_set_ui (root, (z>0) ? 1L : 0L);
  2046. X            if (rem)
  2047. X                mpz_set_ui (rem, (z>1) ? z-1L : 0L);
  2048. X            return;
  2049. X        } else {
  2050. X            z = (z << 2) + ((a->p)[j-1] >> (DIGITBITS-2));
  2051. X            j = j * DIGITBITS - 2;
  2052. X        }
  2053. X    } else {
  2054. X        j = j * DIGITBITS;
  2055. X        while (z & ~0xf) {
  2056. X            z >>= 2;
  2057. X            j += 2;
  2058. X        }
  2059. X    }
  2060. X    j >>= 1;                            /* z and j now as described above */
  2061. X    for (k=1, h=4; h < j+3; k++, h*=2); 
  2062. X        /* 2^(k+1) >= j+3, since a < 2^(2j+4) */
  2063. X    mpz_init_set_ui (&r, (z>8) ? 4L : 3L);
  2064. X    mpz_mul_2exp (&r, &r, j);
  2065. X
  2066. X#ifdef DEBUG
  2067. X    printf ("mpz_sqrtrem: z = %lu, j = %lu, k = %d\n", (long)z, j, k);
  2068. X#endif
  2069. X
  2070. X    /* Main iteration */
  2071. X    mpz_init (&tmp);
  2072. X    for ( ; k > 0; k--) {
  2073. X        mpz_div (&tmp, a, &r);
  2074. X        mpz_add (&r, &tmp, &r);
  2075. X        mpz_div_2exp (&r, &r, 1L);
  2076. X    }
  2077. X
  2078. X    /* Adjust result (which may be one too big) and set remainder */
  2079. X    mpz_mul (&tmp, &r, &r);
  2080. X    if (mpz_cmp (&tmp, a) > 0) {
  2081. X        mpz_sub_ui (root, &r, 1L);
  2082. X        if (rem) {
  2083. X            mpz_sub (rem, a, &tmp);
  2084. X            mpz_add (rem, rem, &r);
  2085. X            mpz_add (rem, rem, &r);
  2086. X            mpz_sub_ui (rem, rem, 1L);
  2087. X        }
  2088. X    } else {
  2089. X        mpz_set (root, &r);
  2090. X        if (rem)
  2091. X            mpz_sub (rem, a, &tmp);
  2092. X    }
  2093. X
  2094. X    mpz_clear (&tmp);
  2095. X    mpz_clear (&r);
  2096. X}
  2097. X
  2098. X
  2099. Xvoid mpz_sqrt (root, a)
  2100. X    MP_INT *root;
  2101. X    MP_INT *a;
  2102. X{
  2103. X    mpz_sqrtrem (root, NULL, a);
  2104. X}
  2105. END_OF_FILE
  2106. if test 38872 -ne `wc -c <'gmp.c'`; then
  2107.     echo shar: \"'gmp.c'\" unpacked with wrong size!
  2108. fi
  2109. # end of 'gmp.c'
  2110. fi
  2111. echo shar: End of shell archive.
  2112. exit 0
  2113. -- 
  2114. Mark Henderson      markh@wimsey.bc.ca (personal account)
  2115. RIPEM key available by key server/finger/E-mail
  2116.   MD5OfPublicKey: F1F5F0C3984CBEAF3889ADAFA2437433
  2117.  
  2118. exit 0 # Just in case...
  2119.