source: git/ntl/src/c_lip_impl.h @ 26e030

spielwiese
Last change on this file since 26e030 was 26e030, checked in by Hans Schönemann <hannes@…>, 14 years ago
*hannes: update to 5.5.1 git-svn-id: file:///usr/local/Singular/svn/trunk@11949 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 153.0 KB
Line 
1
2#include <NTL/lip.h>
3
4#include <NTL/ctools.h>
5
6
7#include <stdlib.h>
8#include <stdio.h>
9#include <math.h>
10
11
12
13
14
15
16#define MustAlloc(c, len)  (!(c) || ((c)[-1] >> 1) < (len))
17   /* Fast test to determine if allocation is necessary */
18
19
20static 
21void zhalt(char *c)
22{
23   fprintf(stderr,"fatal error:\n   %s\nexit...\n",c);
24   fflush(stderr);
25   _ntl_abort();
26}
27
28
29
30#define NTL_GMP_MUL_CROSS (4)
31#define NTL_GMP_SQR_CROSS (4)
32#define NTL_GMP_DIV_CROSS (4)
33#define NTL_GMP_REM_CROSS (4)
34#define NTL_GMP_QREM_CROSS (4)
35#define NTL_GMP_SQRT_CROSS (2)
36#define NTL_GMP_GCD_CROSS (1)
37#define NTL_GMP_XGCD_CROSS (4)
38#define NTL_GMP_INVMOD_CROSS (2)
39
40#ifdef NTL_GMP_HACK
41
42/* using GMP */
43
44#ifdef NTL_SINGLE_MUL
45#error "sorry...not implemented"
46#endif
47
48#if (NTL_NBITS != NTL_NBITS_MAX)
49#error "sorry...not implemented"
50#endif
51
52int _ntl_gmp_hack = 1;
53
54
55#include <gmp.h>
56
57
58static mp_limb_t *gspace_data = 0;
59static long gspace_size = 0;
60
61
62static void alloc_gspace(long n)
63{
64   if (n <= gspace_size) return;
65   
66   if (n <= gspace_size*1.1)
67      n = ((long) (gspace_size*1.1)) + 10;
68
69   if (gspace_data)
70      gspace_data = 
71         (mp_limb_t *) NTL_REALLOC(gspace_data, n, sizeof(mp_limb_t), 0);   
72   else
73      gspace_data = (mp_limb_t *) NTL_MALLOC(n, sizeof(mp_limb_t), 0);
74
75   if (!gspace_data) zhalt("alloc_gspace: out of memory");
76
77   gspace_size = n;
78}
79
80
81#define NTL_GSPACE(n) \
82{ long _n = (n);  if (_n > gspace_size) alloc_gspace(_n); }
83
84
85static mpz_t gt_1, gt_2, gt_3, gt_4, gt_5;
86static long gt_init = 0;
87
88static
89void do_gt_init()
90{
91   gt_init = 1;
92   mpz_init(gt_1);
93   mpz_init(gt_2);
94   mpz_init(gt_3);
95   mpz_init(gt_4);
96   mpz_init(gt_5);
97}
98
99#define GT_INIT { if (!gt_init) do_gt_init(); }
100
101#include "lip_gmp_aux_impl.h"
102
103
104/* Check that we really have it...otherwise, some compilers
105 * only issue warnings for missing functions.
106 */
107
108
109#ifndef HAVE_LIP_GMP_AUX
110
111#error "do not have lip_gmp_aux.h"
112
113#endif
114
115static
116void lip_to_mpz(const long *x, mpz_t y)
117{
118   long sx;
119   long neg;
120   long gsx;
121
122   if (!x || (x[0] == 1 && x[1] == 0)) {
123      mpz_set_ui(y, 0);
124      return;
125   }
126
127   sx = x[0];
128   if (sx < 0) {
129      neg = 1;
130      sx = -sx;
131   }
132   else
133      neg = 0;
134
135   gsx = L_TO_G(sx);
136
137   if (gsx > y->_mp_alloc) _mpz_realloc(y, gsx);
138   lip_to_gmp(x+1, y->_mp_d, sx);
139   while (y->_mp_d[gsx-1] == 0) gsx--;
140   if (neg) gsx = -gsx;
141   y->_mp_size = gsx;
142}
143
144static
145void mpz_to_lip(long **x, mpz_t y)
146{
147   long gsy;
148   long neg;
149   long sx;
150   long *xp;
151
152   gsy = y->_mp_size;
153
154   if (gsy == 0) {
155      _ntl_zzero(x);
156      return;
157   }
158
159   if (gsy < 0) {
160      neg = 1;
161      gsy = -gsy;
162   }
163   else
164      neg = 0;
165
166   sx = G_TO_L(gsy);
167
168   xp = *x;
169   if (MustAlloc(xp, sx)) { 
170      _ntl_zsetlength(x, sx); 
171      xp = *x;
172   }
173
174   gmp_to_lip1(xp+1, y->_mp_d, sx);
175
176   while (xp[sx] == 0) sx--;
177   if (neg) sx = -sx;
178   xp[0] = sx; 
179}
180
181
182void _ntl_gmp_powermod(long **x, long *a, long *e, long *n)
183{
184   long neg = 0;
185
186   GT_INIT
187
188
189   lip_to_mpz(a, gt_2);
190   lip_to_mpz(e, gt_3);
191   lip_to_mpz(n, gt_4);
192
193   if (mpz_sgn(gt_3) < 0) {
194      mpz_neg(gt_3, gt_3);
195      neg = 1;
196   }
197
198   mpz_powm(gt_1, gt_2, gt_3, gt_4);
199
200   /* This fixes a bug in GMP 3.0.1 */
201   if (mpz_cmp(gt_1, gt_4) >= 0) 
202      mpz_sub(gt_1, gt_1, gt_4);
203
204   if (neg) {
205      if (!mpz_invert(gt_1, gt_1, gt_4))
206         zhalt("Modular inverse not defined");
207   }
208
209   mpz_to_lip(x, gt_1);
210}
211
212
213#else
214
215/* not using GMP */
216
217int _ntl_gmp_hack = 0;
218
219
220#endif
221
222
223
224#define DENORMALIZE  NTL_FDOUBLE_PRECISION
225
226
227#define MIN_SETL        (4)
228   /* _ntl_zsetlength allocates a multiple of MIN_SETL digits */
229
230
231
232#if (defined(NTL_SINGLE_MUL) && !defined(NTL_FAST_INT_MUL))
233#define MulLo(rres,a,b) \
234{ \
235   double _x = ((double) a) * ((double) b) + (DENORMALIZE); \
236   unsigned long _x_lo; \
237   NTL_FetchLo(_x_lo, _x); \
238   rres =  _x_lo; \
239}
240#else
241#define MulLo(rres,a,b) rres = (a)*(b)
242#endif
243
244
245
246
247
248
249/*
250 * definitions of zaddmulp, zxmulp, zaddmulpsq for the various
251 * long integer arithmentic implementation options.
252 */
253
254
255#if (defined(NTL_SINGLE_MUL))
256
257#define zaddmulp(a,b,d,t) \
258{ \
259   long _a = (a), _b = (b), _d = (d), _t = (t); \
260   unsigned long  __lhi, __llo;\
261   double __lx = ((double) ((_a) + (_t))) + ((double) _b)*((double) _d); \
262  __lx += (DENORMALIZE); \
263   NTL_FetchHiLo(__lhi,__llo,__lx);\
264   __lhi = ((__lhi<<6)|(__llo>>26)) & 0x3FFFFFF; \
265   __llo &= 0x3FFFFFF; \
266   (a) = __llo;\
267   (t) = __lhi;\
268}
269
270#define zxmulp(a,b,d,t) \
271{ \
272   long _b = (b), _d = (d), _t = (t); \
273   unsigned long  __lhi, __llo;\
274   double __lx = ((double) ((_t))) + ((double) _b)*((double) _d); \
275  __lx += (DENORMALIZE); \
276   NTL_FetchHiLo(__lhi,__llo,__lx);\
277   __lhi = ((__lhi<<6)|(__llo>>26)) & 0x3FFFFFF; \
278   __llo &= 0x3FFFFFF; \
279   (a) = __llo;\
280   (t) = __lhi;\
281}
282
283#define zaddmulpsq(a,b,t) \
284{ \
285   long _a = (a), _b = (b); \
286   unsigned long  __lhi, __llo; \
287   double __lx = ((double) (_a)) + ((double) _b)*((double) _b); \
288   __lx += (DENORMALIZE); \
289   NTL_FetchHiLo(__lhi,__llo,__lx);\
290   __lhi = ((__lhi<<6)|(__llo>>26)) & 0x3FFFFFF; \
291   __llo &= 0x3FFFFFF; \
292   (a) =  __llo;\
293   (t) =  __lhi;\
294}
295
296#elif (defined(NTL_LONG_LONG))
297
298
299#if (!defined(NTL_CLEAN_INT))
300
301/*
302 * One might get slightly better code with this version.
303 */
304
305#define zaddmulp(a, b, d, t) { \
306   NTL_LL_TYPE _pp = ((NTL_LL_TYPE) (b)) * ((NTL_LL_TYPE) (d)) + ((t)+(a)); \
307   (a) = ((long)(_pp)) & NTL_RADIXM; \
308   (t) = (long) (_pp >> NTL_NBITS); \
309}
310
311
312#define zxmulp(a, b, d, t) { \
313   NTL_LL_TYPE _pp = ((NTL_LL_TYPE) (b)) * ((NTL_LL_TYPE) (d)) + (t); \
314   (a) = ((long)(_pp)) & NTL_RADIXM; \
315   (t) = (long) (_pp >> NTL_NBITS); \
316}
317
318#define zaddmulpsq(a,b,t) { \
319   NTL_LL_TYPE _pp = ((NTL_LL_TYPE) (b)) * ((NTL_LL_TYPE) (b)) + (a); \
320   (a) = ((long)(_pp)) & NTL_RADIXM; \
321   (t) = (long) (_pp >> NTL_NBITS); \
322}
323
324#else
325
326/*
327 * This version conforms to the language standard when d is non-negative.
328 * Some compilers may emit sub-optimal code, though.
329 */
330
331
332
333#define zaddmulp(a, b, d, t) { \
334   NTL_LL_TYPE _pp = ((NTL_LL_TYPE) (b)) * ((NTL_LL_TYPE) (d)) + ((t)+(a)); \
335   (a) = (long) (_pp & NTL_RADIXM); \
336   (t) = (long) (_pp >> NTL_NBITS); \
337}
338
339
340#define zxmulp(a, b, d, t) { \
341   NTL_LL_TYPE _pp = ((NTL_LL_TYPE) (b)) * ((NTL_LL_TYPE) (d)) + (t); \
342   (a) = (long) (_pp & NTL_RADIXM); \
343   (t) = (long) (_pp >> NTL_NBITS); \
344}
345
346#define zaddmulpsq(a,b,t) { \
347   NTL_LL_TYPE _pp = ((NTL_LL_TYPE) (b)) * ((NTL_LL_TYPE) (b)) + (a); \
348   (a) = (long) (_pp & NTL_RADIXM); \
349   (t) = (long) (_pp >> NTL_NBITS); \
350}
351
352
353#endif
354
355
356#elif (defined(NTL_AVOID_FLOAT))
357   
358
359#define zaddmulp(  a,  b,  d,  t) { \
360        unsigned long _b1 = b & NTL_RADIXROOTM; \
361        unsigned long _d1 = d & NTL_RADIXROOTM; \
362        unsigned long _bd,_b1d1,_m,_aa= (a) + (t); \
363        unsigned long _ld = (d>>NTL_NBITSH); \
364        unsigned long _lb = (b>>NTL_NBITSH); \
365 \
366        _bd=_lb*_ld; \
367        _b1d1=_b1*_d1; \
368        _m=(_lb+_b1)*(_ld+_d1) - _bd - _b1d1; \
369        _aa += ( _b1d1+ ((_m&NTL_RADIXROOTM)<<NTL_NBITSH)); \
370        (t) = (_aa >> NTL_NBITS) + _bd + (_m>>NTL_NBITSH); \
371        (a) = _aa & NTL_RADIXM; \
372}
373
374
375
376
377
378#define zxmulp(  a,  b,  d,  t) { \
379        unsigned long _b1 = b & NTL_RADIXROOTM; \
380        unsigned long _d1 = d & NTL_RADIXROOTM; \
381        unsigned long _bd,_b1d1,_m,_aa= (t); \
382        unsigned long _ld = (d>>NTL_NBITSH); \
383        unsigned long _lb = (b>>NTL_NBITSH); \
384 \
385        _bd=_lb*_ld; \
386        _b1d1=_b1*_d1; \
387        _m=(_lb+_b1)*(_ld+_d1) - _bd - _b1d1; \
388        _aa += ( _b1d1+ ((_m&NTL_RADIXROOTM)<<NTL_NBITSH)); \
389        (t) = (_aa >> NTL_NBITS) + _bd + (_m>>NTL_NBITSH); \
390        (a) = _aa & NTL_RADIXM; \
391}
392
393
394#define zaddmulpsq(_a, _b, _t) \
395{ \
396        long _lb = (_b); \
397        long _b1 = (_b) & NTL_RADIXROOTM; \
398        long _aa = (_a) + _b1 * _b1; \
399 \
400        _b1 = (_b1 * (_lb >>= NTL_NBITSH) << 1) + (_aa >> NTL_NBITSH); \
401        _aa = (_aa & NTL_RADIXROOTM) + ((_b1 & NTL_RADIXROOTM) << NTL_NBITSH); \
402        (_t) = _lb * _lb + (_b1 >> NTL_NBITSH) + (_aa >> NTL_NBITS); \
403        (_a) = (_aa & NTL_RADIXM); \
404}
405
406
407
408#else
409
410/* default long integer arithemtic */
411/* various "software pipelining" routines are also defined */
412
413
414/*
415 * The macros CARRY_TYPE and CARRY_CONV are only used in the submul
416 * logic.
417 */
418
419
420#if (defined(NTL_CLEAN_INT))
421
422#define CARRY_TYPE unsigned long
423#define CARRY_CONV(x) (-((long)(-x)))
424
425#else
426
427#define CARRY_TYPE long
428#define CARRY_CONV(x) (x)
429
430#endif
431
432
433#if (NTL_BITS_PER_LONG <= NTL_NBITS + 2)
434
435#if (NTL_ARITH_RIGHT_SHIFT && !defined(NTL_CLEAN_INT))
436/* value right-shifted is -1..1 */
437#define zaddmulp(a, b, d, t) \
438{ \
439   long _a = (a), _b = (b), _d = (d), _t = (t); \
440   long _t1 =  _b*_d; \
441   long _t2 = (long) ( ((double) _b)*(((double) _d)*NTL_FRADIX_INV) ); \
442   _t2 = _t2 + ((_t1 - (_t2 << NTL_NBITS)) >> NTL_NBITS); \
443   _t1 = (_t1 & NTL_RADIXM) + _a +_t; \
444   (t) = _t2 + (((unsigned long)_t1) >> NTL_NBITS); \
445   (a) = _t1 & NTL_RADIXM; \
446}
447
448
449#define zxmulp(a, b, d, t) \
450{ \
451   long _b = (b), _d = (d), _t = (t); \
452   long _t1 =  _b*_d + _t; \
453   long _t2 = (long) ( ((double) _b)*(((double) _d)*NTL_FRADIX_INV) ) - 1; \
454   (t) = _t2 + (((unsigned long)(_t1 - (_t2 << NTL_NBITS))) >> NTL_NBITS); \
455   (a) = _t1 & NTL_RADIXM; \
456}
457
458/* value shifted is -1..1 */
459#define zaddmulpsq(a, b, t) \
460{ \
461   long _a = (a), _b = (b); \
462   long _t1 = _b*_b; \
463   long _t2 = (long) ( ((double) _b)*(((double) _b)*NTL_FRADIX_INV) ); \
464   _t2 = _t2 + ((_t1 - (_t2 << NTL_NBITS)) >> NTL_NBITS); \
465   _t1 = (_t1 & NTL_RADIXM) + _a; \
466   (t) = _t2 + (((unsigned long)_t1) >> NTL_NBITS); \
467   (a) = _t1 & NTL_RADIXM; \
468}
469
470/*
471 * In the following definition of zam_init, the value _ds is computed so that
472 * it is slightly bigger than s*NTL_RADIX_INV.  This has the consequence that
473 * the value _hi is equal to floor(_b*_s/NTL_RADIX) or
474 * floor(_b*_s/NTL_RADIX) + 1, assuming only that (1) conversion of "small"
475 * integer to doubles is exact, (2) multiplication by powers of 2 is exact, and
476 * (3) multiplication of two general doubles yields a result with relative
477 * error 1/2^{NTL_DOUBLE_PRECISION-1}.  These assumptions are very
478 * conservative, and in fact, the IEEE floating point standard would guarantee
479 * this result *without* making _ds slightly bigger.
480 */
481
482#define zam_decl double _ds; long _hi, _lo, _s;
483
484#define zam_init(b,s) \
485{ \
486   long _b = (b); \
487   _s = (s); \
488   _ds = ((_s << 1)+1)*(NTL_FRADIX_INV/2.0); \
489   _lo = _b*_s; \
490   _hi = (long) (((double) _b)*_ds); \
491}
492
493/* value shifted is 0..3 */
494#define zam_loop(a,t,nb) \
495{ \
496   long _a = (a), _t = (t), _nb = (nb); \
497   long _vv; \
498   double _yy; \
499   _vv = _nb*_s; \
500   _yy = ((double) _nb)*_ds; \
501   _lo = _lo + _a + _t; \
502   _hi--; \
503   (t) = _hi + (((unsigned long)(_lo - (_hi<<NTL_NBITS))) >> NTL_NBITS); \
504   (a) = _lo & NTL_RADIXM; \
505   _lo = _vv; \
506   _hi = (long) _yy; \
507}
508
509/* shift is -1..+1 */
510#define zsx_loop(a,t,nb) \
511{ \
512   long  _t = (t), _nb = (nb); \
513   long _vv; \
514   double _yy; \
515   _vv = _nb*_s; \
516   _yy = ((double) _nb)*_ds; \
517   _lo = _lo + _t; \
518   (t) = _hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS); \
519   (a) = _lo & NTL_RADIXM; \
520   _lo = _vv; \
521   _hi = (long) _yy; \
522}
523
524
525/* value shifted is -2..+1 */
526#define zam_subloop(a,t,nb) \
527{ \
528   long _a = (a), _t = (t), _nb = (nb); \
529   long _vv; \
530   double _yy; \
531   _vv = _nb*_s; \
532   _yy = ((double) _nb)*_ds; \
533   _lo = _a + _t - _lo; \
534   (t) = ((_lo + (_hi<<NTL_NBITS)) >> NTL_NBITS) - _hi; \
535   (a) = _lo & NTL_RADIXM; \
536   _lo = _vv; \
537   _hi = (long) _yy; \
538}
539
540/* value shifted is 0..3 */
541#define zam_finish(a,t) \
542{ \
543   long _a = (a), _t = (t); \
544   _lo = _lo + _a + _t; \
545   _hi--; \
546   (t) = _hi + (((unsigned long)(_lo - (_hi<<NTL_NBITS))) >> NTL_NBITS); \
547   (a) = _lo & NTL_RADIXM; \
548}
549
550/* value shifted is -1..+1 */
551#define zsx_finish(a,t) \
552{ \
553   long _t = (t); \
554   _lo = _lo + _t; \
555   (t) = _hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS); \
556   (a) = _lo & NTL_RADIXM; \
557}
558
559/* value shifted is -2..+1 */
560#define zam_subfinish(a,t) \
561{ \
562   long _a = (a), _t = (t); \
563   _lo = _a + _t - _lo; \
564   (t) = ((_lo + (_hi<<NTL_NBITS)) >> NTL_NBITS) - _hi; \
565   (a) = _lo & NTL_RADIXM; \
566}
567
568#elif (!defined(NTL_CLEAN_INT))
569
570/* right shift is not arithmetic */
571
572/* value right-shifted is 0..2 */
573#define zaddmulp(a, b, d, t) \
574{ \
575   long _a = (a), _b = (b), _d = (d), _t = (t); \
576   long _t1 =  _b*_d; \
577   long _t2 = (long) ( ((double) _b)*(((double) _d)*NTL_FRADIX_INV) ) - 1; \
578   _t2 = _t2 + ( ((unsigned long) (_t1 - (_t2 << NTL_NBITS))) >> NTL_NBITS ); \
579   _t1 = (_t1 & NTL_RADIXM) + _a +_t; \
580   (t) = _t2 + (((unsigned long)_t1) >> NTL_NBITS); \
581   (a) = _t1 & NTL_RADIXM; \
582}
583
584
585#define zxmulp(a, b, d, t) \
586{ \
587   long _b = (b), _d = (d), _t = (t); \
588   long _t1 =  _b*_d + _t; \
589   long _t2 = (long) ( ((double) _b)*(((double) _d)*NTL_FRADIX_INV) ) - 1; \
590   (t) = _t2 + (((unsigned long)(_t1 - (_t2 << NTL_NBITS))) >> NTL_NBITS); \
591   (a) = _t1 & NTL_RADIXM; \
592}
593
594/* value shifted is 0..2 */
595#define zaddmulpsq(a, b, t) \
596{ \
597   long _a = (a), _b = (b); \
598   long _t1 = _b*_b; \
599   long _t2 = (long) ( ((double) _b)*(((double) _b)*NTL_FRADIX_INV) ) - 1; \
600   _t2 = _t2 + ( ((unsigned long) (_t1 - (_t2 << NTL_NBITS))) >> NTL_NBITS ); \
601   _t1 = (_t1 & NTL_RADIXM) + _a; \
602   (t) = _t2 + (((unsigned long)_t1) >> NTL_NBITS); \
603   (a) = _t1 & NTL_RADIXM; \
604}
605
606#define zam_decl double _ds; long _hi, _lo, _s;
607
608#define zam_init(b,s) \
609{ \
610   long _b = (b); \
611   _s = (s); \
612   _ds = ((_s << 1)+1)*(NTL_FRADIX_INV/2.0); \
613   _lo = _b*_s; \
614   _hi = (long) (((double) _b)*_ds); \
615}
616
617/* value shifted is 0..3 */
618#define zam_loop(a,t,nb) \
619{ \
620   long _a = (a), _t = (t), _nb = (nb); \
621   long _vv; \
622   double _yy; \
623   _vv = _nb*_s; \
624   _yy = ((double) _nb)*_ds; \
625   _lo = _lo + _a + _t; \
626   _hi--; \
627   (t) = _hi + (((unsigned long)(_lo - (_hi<<NTL_NBITS))) >> NTL_NBITS); \
628   (a) = _lo & NTL_RADIXM; \
629   _lo = _vv; \
630   _hi = (long) _yy; \
631}
632
633/* value shifted is 0..2 */
634#define zsx_loop(a,t,nb) \
635{ \
636   long _t = (t), _nb = (nb); \
637   long _vv; \
638   double _yy; \
639   _vv = _nb*_s; \
640   _yy = ((double) _nb)*_ds; \
641   _lo = _lo + _t; \
642   _hi--; \
643   (t) = _hi + (((unsigned long)(_lo - (_hi<<NTL_NBITS))) >> NTL_NBITS); \
644   (a) = _lo & NTL_RADIXM; \
645   _lo = _vv; \
646   _hi = (long) _yy; \
647}
648
649/* value shifted is 0..3 */
650#define zam_subloop(a,t,nb) \
651{ \
652   long _a = (a), _t = (t), _nb = (nb); \
653   long _vv; \
654   double _yy; \
655   _vv = _nb*_s; \
656   _yy = ((double) _nb)*_ds; \
657   _hi += 2; \
658   _lo = _a + _t - _lo; \
659   (t) = (((unsigned long)(_lo + (_hi<<NTL_NBITS))) >> NTL_NBITS) - _hi; \
660   (a) = _lo & NTL_RADIXM; \
661   _lo = _vv; \
662   _hi = (long) _yy; \
663}
664
665/* value shifted is 0..3 */
666#define zam_finish(a,t) \
667{ \
668   long _a = (a), _t = (t); \
669   _lo = _lo + _a + _t; \
670   _hi--; \
671   (t) = _hi + (((unsigned long)(_lo - (_hi<<NTL_NBITS))) >> NTL_NBITS); \
672   (a) = _lo & NTL_RADIXM; \
673}
674
675/* value shifted is 0..2 */
676#define zsx_finish(a,t) \
677{ \
678   long _a = (a), _t = (t); \
679   _lo = _lo + _t; \
680   _hi--; \
681   (t) = _hi + (((unsigned long)(_lo - (_hi<<NTL_NBITS))) >> NTL_NBITS); \
682   (a) = _lo & NTL_RADIXM; \
683}
684
685/* value shifted is 0..3 */
686#define zam_subfinish(a,t) \
687{ \
688   long _a = (a), _t = (t); \
689   _hi += 2; \
690   _lo = _a + _t - _lo; \
691   (t) = (((unsigned long)(_lo + (_hi<<NTL_NBITS))) >> NTL_NBITS) - _hi; \
692   (a) = _lo & NTL_RADIXM; \
693}
694
695#else
696/* clean int version */
697
698
699/* value right-shifted is 0..2 */
700#define zaddmulp(a, b, d, t) \
701{ \
702   long _a = (a), _b = (b), _d = (d), _t = (t); \
703   unsigned long _t1 = ((unsigned long) _b)*((unsigned long) _d); \
704   unsigned long _t2 = (long) ( ((double) _b)*(((double) _d)*NTL_FRADIX_INV) ) - 1; \
705   _t2 = _t2 + ( (_t1 - (_t2 << NTL_NBITS)) >> NTL_NBITS ); \
706   _t1 = (_t1 & NTL_RADIXM) + ((unsigned long) _a) + ((unsigned long) _t); \
707   (t) = (long) (_t2 + (_t1 >> NTL_NBITS)); \
708   (a) = (long) (_t1 & NTL_RADIXM); \
709}
710
711
712#define zxmulp(a, b, d, t) \
713{ \
714   long _b = (b), _d = (d), _t = (t); \
715   unsigned long _t1 =  ((unsigned long) _b)*((unsigned long) _d) + ((unsigned long) _t); \
716   unsigned long _t2 = (long) ( ((double) _b)*(((double) _d)*NTL_FRADIX_INV) ) - 1; \
717   (t) = (long) (_t2 + ((_t1 - (_t2 << NTL_NBITS)) >> NTL_NBITS)); \
718   (a) = (long) (_t1 & NTL_RADIXM); \
719}
720
721/* value shifted is 0..2 */
722#define zaddmulpsq(a, b, t) \
723{ \
724   long _a = (a), _b = (b); \
725   unsigned long _t1 = ((unsigned long) _b)*((unsigned long) _b); \
726   unsigned long _t2 = (long) ( ((double) _b)*(((double) _b)*NTL_FRADIX_INV) ) - 1; \
727   _t2 = _t2 + ( (_t1 - (_t2 << NTL_NBITS)) >> NTL_NBITS ); \
728   _t1 = (_t1 & NTL_RADIXM) + ((unsigned long) _a); \
729   (t) = (long) (_t2 + (_t1 >> NTL_NBITS)); \
730   (a) = (long) (_t1 & NTL_RADIXM); \
731}
732
733#define zam_decl double _ds; long _s; unsigned long _hi, _lo;
734
735#define zam_init(b,s) \
736{ \
737   long _b = (b); \
738   _s = (s); \
739   _ds = ((_s << 1)+1)*(NTL_FRADIX_INV/2.0); \
740   _lo = ((unsigned long) _b)*((unsigned long) _s); \
741   _hi = (long) (((double) _b)*_ds); \
742}
743
744/* value shifted is 0..3 */
745#define zam_loop(a,t,nb) \
746{ \
747   long _a = (a), _t = (t), _nb = (nb); \
748   unsigned long _vv; \
749   double _yy; \
750   _vv = ((unsigned long) _nb)*((unsigned long)_s); \
751   _yy = ((double) _nb)*_ds; \
752   _lo = _lo + ((unsigned long) _a) + ((unsigned long) _t); \
753   _hi--; \
754   (t) = (long) (_hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS)); \
755   (a) = (long) (_lo & NTL_RADIXM); \
756   _lo = _vv; \
757   _hi = (long) _yy; \
758}
759
760/* value shifted is 0..2 */
761#define zsx_loop(a,t,nb) \
762{ \
763   long _t = (t), _nb = (nb); \
764   unsigned long _vv; \
765   double _yy; \
766   _vv = ((unsigned long) _nb)*((unsigned long) _s); \
767   _yy = ((double) _nb)*_ds; \
768   _lo = _lo + ((unsigned long) _t); \
769   _hi--; \
770   (t) = (long) (_hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS)); \
771   (a) = (long) (_lo & NTL_RADIXM); \
772   _lo = _vv; \
773   _hi = (long) _yy; \
774}
775
776/* value shifted is 0..3 */
777#define zam_subloop(a,t,nb) \
778{ \
779   long _a = (a); unsigned long _t = (t); long _nb = (nb); \
780   unsigned long _vv; \
781   double _yy; \
782   _vv = ((unsigned long) _nb)*((unsigned long) _s); \
783   _yy = ((double) _nb)*_ds; \
784   _hi += 2; \
785   _lo = ((unsigned long) _a) + _t - _lo; \
786   (t) = ((_lo + (_hi<<NTL_NBITS)) >> NTL_NBITS) - _hi; \
787   (a) = (long) (_lo & NTL_RADIXM); \
788   _lo = _vv; \
789   _hi = (long) _yy; \
790}
791
792/* value shifted is 0..3 */
793#define zam_finish(a,t) \
794{ \
795   long _a = (a), _t = (t); \
796   _lo = _lo + ((unsigned long) _a) + ((unsigned long) _t); \
797   _hi--; \
798   (t) = (long) (_hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS)); \
799   (a) = (long) (_lo & NTL_RADIXM); \
800}
801
802/* value shifted is 0..2 */
803#define zsx_finish(a,t) \
804{ \
805   long _a = (a), _t = (t); \
806   _lo = _lo + ((unsigned long) _t); \
807   _hi--; \
808   (t) = (long) (_hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS)); \
809   (a) = (long) (_lo & NTL_RADIXM); \
810}
811
812/* value shifted is 0..3 */
813#define zam_subfinish(a,t) \
814{ \
815   long _a = (a); unsigned long _t = (t); \
816   _hi += 2; \
817   _lo = ((unsigned long) _a) + _t - _lo; \
818   (t) = ((_lo + (_hi<<NTL_NBITS)) >> NTL_NBITS) - _hi; \
819   (a) = (long) (_lo & NTL_RADIXM); \
820}
821
822#endif
823/* end of arithmemtic-right-shift if-then else */
824   
825#else
826/*  NTL_BITS_PER_LONG > NTL_NBITS + 2, and certain optimizations can be
827    made.  Useful on 64-bit machines.  */
828
829#if (NTL_ARITH_RIGHT_SHIFT && !defined(NTL_CLEAN_INT))
830/* shift is -1..+3 */
831#define zaddmulp(a, b, d, t) \
832{ \
833   long _a = (a), _b = (b), _d = (d), _t = (t); \
834   long _t1 =  _b*_d + _a + _t; \
835   long _t2 = (long) ( ((double) _b)*(((double) _d)*NTL_FRADIX_INV) ); \
836   (t) = _t2 + ((_t1 - (_t2 << NTL_NBITS)) >> NTL_NBITS); \
837   (a) = _t1 & NTL_RADIXM; \
838}
839
840#define zxmulp(a, b, d, t) \
841{ \
842   long _b = (b), _d = (d), _t = (t); \
843   long _t1 =  _b*_d + _t; \
844   long _t2 = (long) ( ((double) _b)*(((double) _d)*NTL_FRADIX_INV) ); \
845   (t) = _t2 + ((_t1 - (_t2 << NTL_NBITS)) >> NTL_NBITS); \
846   (a) = _t1 & NTL_RADIXM; \
847}
848
849/* shift is -1..+2 */
850#define zaddmulpsq(a, b, t) \
851{ \
852   long _a = (a), _b = (b), _t = (t); \
853   long _t1 = _b*_b + _a; \
854   long _t2 = (long) ( ((double) _b)*(((double) _b)*NTL_FRADIX_INV) ); \
855   (t) = _t2 + ((_t1 - (_t2 << NTL_NBITS)) >> NTL_NBITS); \
856   (a) = _t1 & NTL_RADIXM; \
857}
858
859#define zam_decl double _ds; long _hi, _lo, _s;
860
861#define zam_init(b,s) \
862{ \
863   long _b = (b); \
864   _s = (s); \
865   _ds = _s*NTL_FRADIX_INV; \
866   _lo = _b*_s; \
867   _hi = (long) (((double) _b)*_ds); \
868}
869
870/* shift is -1..+3 */
871#define zam_loop(a,t,nb) \
872{ \
873   long _a = (a), _t = (t), _nb = (nb); \
874   long _vv; \
875   double _yy; \
876   _vv = _nb*_s; \
877   _yy = ((double) _nb)*_ds; \
878   _lo = _lo + _a + _t; \
879   (t) = _hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS); \
880   (a) = _lo & NTL_RADIXM; \
881   _lo = _vv; \
882   _hi = (long) _yy; \
883}
884
885/* shift is -1..+2 */
886#define zsx_loop(a,t,nb) \
887{ \
888   long _t = (t), _nb = (nb); \
889   long _vv; \
890   double _yy; \
891   _vv = _nb*_s; \
892   _yy = ((double) _nb)*_ds; \
893   _lo = _lo + _t; \
894   (t) = _hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS); \
895   (a) = _lo & NTL_RADIXM; \
896   _lo = _vv; \
897   _hi = (long) _yy; \
898}
899
900/* shift is -3..+1 */
901#define zam_subloop(a,t,nb) \
902{ \
903   long _a = (a), _t = (t), _nb = (nb); \
904   long _vv; \
905   double _yy; \
906   _vv = _nb*_s; \
907   _yy = ((double) _nb)*_ds; \
908   _lo = _a + _t - _lo; \
909   (t) = ((_lo + (_hi<<NTL_NBITS)) >> NTL_NBITS) - _hi; \
910   (a) = _lo & NTL_RADIXM; \
911   _lo = _vv; \
912   _hi = (long) _yy; \
913}
914
915/* shift is -1..+3 */
916#define zam_finish(a,t) \
917{ \
918   long _a = (a), _t = (t); \
919   _lo = _lo + _a + _t; \
920   (t) = _hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS); \
921   (a) = _lo & NTL_RADIXM; \
922}
923
924/* shift is -1..+2 */
925#define zsx_finish(a,t) \
926{ \
927   long _t = (t); \
928   _lo = _lo + _t; \
929   (t) = _hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS); \
930   (a) = _lo & NTL_RADIXM; \
931}
932
933/* shift is -3..+1 */
934#define zam_subfinish(a,t) \
935{ \
936   long _a = (a), _t = (t); \
937   _lo = _a + _t - _lo; \
938   (t) = ((_lo + (_hi<<NTL_NBITS)) >> NTL_NBITS) - _hi; \
939   (a) = _lo & NTL_RADIXM; \
940}
941
942#elif (!defined(NTL_CLEAN_INT))
943/* right shift is not arithmetic */
944
945/* shift is 0..4 */
946#define zaddmulp(a, b, d, t) \
947{ \
948   long _a = (a), _b = (b), _d = (d), _t = (t); \
949   long _t1 =  _b*_d + _a + _t; \
950   long _t2 = (long) ( ((double) _b)*(((double) _d)*NTL_FRADIX_INV) ) - 1; \
951   (t) = _t2 + (((unsigned long)(_t1 - (_t2 << NTL_NBITS))) >> NTL_NBITS); \
952   (a) = _t1 & NTL_RADIXM; \
953}
954
955#define zxmulp(a, b, d, t) \
956{ \
957   long _b = (b), _d = (d), _t = (t); \
958   long _t1 =  _b*_d + _t; \
959   long _t2 = (long) ( ((double) _b)*(((double) _d)*NTL_FRADIX_INV) ) - 1; \
960   (t) = _t2 + (((unsigned long)(_t1 - (_t2 << NTL_NBITS))) >> NTL_NBITS); \
961   (a) = _t1 & NTL_RADIXM; \
962}
963
964/* shift is 0..3 */
965#define zaddmulpsq(a, b, t) \
966{ \
967   long _a = (a), _b = (b), _t = (t); \
968   long _t1 = _b*_b + _a; \
969   long _t2 = (long) ( ((double) _b)*(((double) _b)*NTL_FRADIX_INV) ) - 1; \
970   (t) = _t2 + (((unsigned long)(_t1 - (_t2 << NTL_NBITS))) >> NTL_NBITS); \
971   (a) = _t1 & NTL_RADIXM; \
972}
973
974#define zam_decl double _ds; long _hi, _lo, _s;
975
976#define zam_init(b,s) \
977{ \
978   long _b = (b); \
979   _s = (s); \
980   _ds = _s*NTL_FRADIX_INV; \
981   _lo = _b*_s; \
982   _hi = (long) (((double) _b)*_ds); \
983}
984
985/* shift is 0..4 */
986#define zam_loop(a,t,nb) \
987{ \
988   long _a = (a), _t = (t), _nb = (nb); \
989   long _vv; \
990   double _yy; \
991   _vv = _nb*_s; \
992   _yy = ((double) _nb)*_ds; \
993   _hi--; \
994   _lo = _lo + _a + _t; \
995   (t) = _hi + (((unsigned long)(_lo - (_hi<<NTL_NBITS))) >> NTL_NBITS); \
996   (a) = _lo & NTL_RADIXM; \
997   _lo = _vv; \
998   _hi = (long) _yy; \
999}
1000
1001/* shift is 0..3 */
1002#define zsx_loop(a,t,nb) \
1003{ \
1004   long _t = (t), _nb = (nb); \
1005   long _vv; \
1006   double _yy; \
1007   _vv = _nb*_s; \
1008   _yy = ((double) _nb)*_ds; \
1009   _hi--; \
1010   _lo = _lo + _t; \
1011   (t) = _hi + (((unsigned long)(_lo - (_hi<<NTL_NBITS))) >> NTL_NBITS); \
1012   (a) = _lo & NTL_RADIXM; \
1013   _lo = _vv; \
1014   _hi = (long) _yy; \
1015}
1016
1017/* shift is 0..4 */
1018#define zam_subloop(a,t,nb) \
1019{ \
1020   long _a = (a), _t = (t), _nb = (nb); \
1021   long _vv; \
1022   double _yy; \
1023   _vv = _nb*_s; \
1024   _yy = ((double) _nb)*_ds; \
1025   _hi += 3; \
1026   _lo = _a + _t - _lo; \
1027   (t) = (((unsigned long)(_lo + (_hi<<NTL_NBITS))) >> NTL_NBITS) - _hi; \
1028   (a) = _lo & NTL_RADIXM; \
1029   _lo = _vv; \
1030   _hi = (long) _yy; \
1031}
1032
1033/* shift is 0..4 */
1034#define zam_finish(a,t) \
1035{ \
1036   long _a = (a), _t = (t); \
1037   _lo = _lo + _a + _t; \
1038   _hi--; \
1039   (t) = _hi + (((unsigned long)(_lo - (_hi<<NTL_NBITS))) >> NTL_NBITS); \
1040   (a) = _lo & NTL_RADIXM; \
1041}
1042
1043/* shift is 0..3 */
1044#define zsx_finish(a,t) \
1045{ \
1046   long _t = (t); \
1047   _lo = _lo + _t; \
1048   _hi--; \
1049   (t) = _hi + (((unsigned long)(_lo - (_hi<<NTL_NBITS))) >> NTL_NBITS); \
1050   (a) = _lo & NTL_RADIXM; \
1051}
1052
1053/* shift is 0..4 */
1054#define zam_subfinish(a,t) \
1055{ \
1056   long _a = (a), _t = (t); \
1057   _hi += 3; \
1058   _lo = _a + _t - _lo; \
1059   (t) = (((unsigned long)(_lo + (_hi<<NTL_NBITS))) >> NTL_NBITS) - _hi; \
1060   (a) = _lo & NTL_RADIXM; \
1061}
1062#else
1063
1064/* clean int version */
1065
1066/* shift is 0..4 */
1067#define zaddmulp(a, b, d, t) \
1068{ \
1069   long _a = (a), _b = (b), _d = (d), _t = (t); \
1070   unsigned long _t1 =  ((unsigned long) _b)*((unsigned long) _d) + ((unsigned long) _a) + ((unsigned long) _t); \
1071   unsigned long _t2 = (long) ( ((double) _b)*(((double) _d)*NTL_FRADIX_INV) ) - 1; \
1072   (t) = (long) (_t2 + ((_t1 - (_t2 << NTL_NBITS)) >> NTL_NBITS)); \
1073   (a) = (long) (_t1 & NTL_RADIXM); \
1074}
1075
1076#define zxmulp(a, b, d, t) \
1077{ \
1078   long _b = (b), _d = (d), _t = (t); \
1079   unsigned long _t1 =  ((unsigned long) _b)*((unsigned long) _d) + ((unsigned long) _t); \
1080   unsigned long _t2 = (long) ( ((double) _b)*(((double) _d)*NTL_FRADIX_INV) ) - 1; \
1081   (t) = (long) (_t2 + ((_t1 - (_t2 << NTL_NBITS)) >> NTL_NBITS)); \
1082   (a) = (long) (_t1 & NTL_RADIXM); \
1083}
1084
1085/* shift is 0..3 */
1086#define zaddmulpsq(a, b, t) \
1087{ \
1088   long _a = (a), _b = (b), _t = (t); \
1089   unsigned long _t1 = ((unsigned long) _b)*((unsigned long) _b) + ((unsigned long) _a); \
1090   unsigned long _t2 = (long) ( ((double) _b)*(((double) _b)*NTL_FRADIX_INV) ) - 1; \
1091   (t) = (long) (_t2 + ((_t1 - (_t2 << NTL_NBITS)) >> NTL_NBITS)); \
1092   (a) = (long) (_t1 & NTL_RADIXM); \
1093}
1094
1095#define zam_decl double _ds; long _s; unsigned long _hi, _lo;
1096
1097#define zam_init(b,s) \
1098{ \
1099   long _b = (b); \
1100   _s = (s); \
1101   _ds = _s*NTL_FRADIX_INV; \
1102   _lo = ((unsigned long) _b)*((unsigned long) _s); \
1103   _hi = (long) (((double) _b)*_ds); \
1104}
1105
1106/* shift is 0..4 */
1107#define zam_loop(a,t,nb) \
1108{ \
1109   long _a = (a), _t = (t), _nb = (nb); \
1110   unsigned long _vv; \
1111   double _yy; \
1112   _vv = ((unsigned long) _nb)*((unsigned long) _s); \
1113   _yy = ((double) _nb)*_ds; \
1114   _hi--; \
1115   _lo = _lo + ((unsigned long) _a) + ((unsigned long) _t); \
1116   (t) = (long) (_hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS)); \
1117   (a) = (long) (_lo & NTL_RADIXM); \
1118   _lo = _vv; \
1119   _hi = (long) _yy; \
1120}
1121
1122/* shift is 0..3 */
1123#define zsx_loop(a,t,nb) \
1124{ \
1125   long _t = (t), _nb = (nb); \
1126   unsigned long _vv; \
1127   double _yy; \
1128   _vv = ((unsigned long) _nb)*((unsigned long) _s); \
1129   _yy = ((double) _nb)*_ds; \
1130   _hi--; \
1131   _lo = _lo + ((unsigned long) _t); \
1132   (t) = (long) (_hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS)); \
1133   (a) = (long) (_lo & NTL_RADIXM); \
1134   _lo = _vv; \
1135   _hi = (long) _yy; \
1136}
1137
1138/* shift is 0..4 */
1139#define zam_subloop(a,t,nb) \
1140{ \
1141   long _a = (a); unsigned long _t = (t); long _nb = (nb); \
1142   unsigned long _vv; \
1143   double _yy; \
1144   _vv = ((unsigned long) _nb)*((unsigned long) _s); \
1145   _yy = ((double) _nb)*_ds; \
1146   _hi += 3; \
1147   _lo = ((unsigned long) _a) + _t - _lo; \
1148   (t) = ((_lo + (_hi<<NTL_NBITS)) >> NTL_NBITS) - _hi; \
1149   (a) = (long) (_lo & NTL_RADIXM); \
1150   _lo = _vv; \
1151   _hi = (long) _yy; \
1152}
1153
1154/* shift is 0..4 */
1155#define zam_finish(a,t) \
1156{ \
1157   long _a = (a), _t = (t); \
1158   _lo = _lo + ((unsigned long) _a) + ((unsigned long) _t); \
1159   _hi--; \
1160   (t) = (long) (_hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS)); \
1161   (a) = _lo & NTL_RADIXM; \
1162}
1163
1164/* shift is 0..3 */
1165#define zsx_finish(a,t) \
1166{ \
1167   long _t = (t); \
1168   _lo = _lo + ((unsigned long) _t); \
1169   _hi--; \
1170   (t) = (long) (_hi + ((_lo - (_hi<<NTL_NBITS)) >> NTL_NBITS)); \
1171   (a) = (long) (_lo & NTL_RADIXM); \
1172}
1173
1174/* shift is 0..4 */
1175#define zam_subfinish(a,t) \
1176{ \
1177   long _a = (a); unsigned long _t = (t); \
1178   _hi += 3; \
1179   _lo = ((unsigned long) _a) + _t - _lo; \
1180   (t) = ((_lo + (_hi<<NTL_NBITS)) >> NTL_NBITS) - _hi; \
1181   (a) = (long) (_lo & NTL_RADIXM); \
1182}
1183
1184#endif
1185/* end of arithmetic-right-shift if-then-else */
1186
1187#endif
1188/* end of "NTL_BITS_PER_LONG <= NTL_NBITS + 2" if-then-else */
1189
1190#endif
1191/* end of long-integer-implementation if-then-else */
1192
1193
1194
1195
1196
1197
1198static
1199void zaddmulone(long *lama, long *lamb)
1200{ 
1201   long lami; 
1202   long lams = 0; 
1203 
1204   lams = 0; 
1205   for (lami = (*lamb++); lami > 0; lami--) { 
1206      lams += (*lama + *lamb++); 
1207      *lama++ = lams & NTL_RADIXM; 
1208      lams >>= NTL_NBITS; 
1209   } 
1210   *lama += lams; 
1211}
1212
1213#if (NTL_ARITH_RIGHT_SHIFT && !defined(NTL_CLEAN_INT))
1214
1215static
1216void zsubmulone(long *lama, long *lamb)
1217{ 
1218   long lami; 
1219   long lams = 0; 
1220 
1221   lams = 0; 
1222   for (lami = (*lamb++); lami > 0; lami--) { 
1223      lams += (*lama - *lamb++); 
1224      *lama++ = lams & NTL_RADIXM; 
1225      lams >>= NTL_NBITS; 
1226   } 
1227   *lama += lams; 
1228}
1229
1230
1231#else
1232
1233
1234static
1235void zsubmulone(long *lama, long *lamb)
1236{ 
1237   long lami; 
1238   long lams = 0; 
1239 
1240   lams = 0; 
1241   for (lami = (*lamb++); lami > 0; lami--) { 
1242      lams = *lama - *lamb++ - lams; 
1243      *lama++ = lams & NTL_RADIXM; 
1244      lams = (lams < 0);
1245   } 
1246   *lama -= lams; 
1247}
1248
1249#endif
1250
1251
1252/*
1253 * definitions of zaddmul, zsxmul, zaddmulsq for the various
1254 * long integer implementation options.
1255 */
1256
1257
1258#if (defined(NTL_SINGLE_MUL))
1259
1260static
1261void zaddmul(long ams, long *ama, long *amb) 
1262{ 
1263   long carry = 0; 
1264   long i = (*amb++);
1265   double dams = (double) ams;
1266   double xx;
1267   double yy;
1268   unsigned long lo_wd, lo;
1269   unsigned long hi_wd, hi;
1270
1271   xx  =  ((double) (*amb++))*dams + DENORMALIZE;
1272   for (; i > 1; i--) { 
1273      yy =  ((double) (*amb++))*dams +DENORMALIZE;
1274      NTL_FetchHiLo(hi_wd, lo_wd, xx);
1275      lo = lo_wd & 0x3FFFFFF;
1276      hi = ((hi_wd<<6)|(lo_wd>>26)) & 0x3FFFFFF;
1277      lo = lo + (*ama) + carry;
1278      *ama = lo & 0x3FFFFFF;
1279      carry = hi + (lo >> 26);
1280      ama++; 
1281      xx = yy;
1282   } 
1283
1284   NTL_FetchHiLo(hi_wd, lo_wd, xx);
1285   lo = lo_wd & 0x3FFFFFF;
1286   hi = ((hi_wd<<6)|(lo_wd>>26)) & 0x3FFFFFF;
1287   lo = lo + (*ama) + carry;
1288   *ama = lo & 0x3FFFFFF;
1289   carry = hi + (lo >> 26);
1290   ama++; 
1291   *ama += carry; 
1292}
1293
1294static
1295void zsxmul(long ams, long *ama, long *amb) 
1296{ 
1297   long carry = 0; 
1298   long i = (*amb++);
1299   double dams = (double) ams;
1300   double xx;
1301   double yy;
1302   unsigned long lo_wd, lo;
1303   unsigned long hi_wd, hi;
1304
1305   xx  =  ((double) (*amb++))*dams + DENORMALIZE;
1306   for (; i > 1; i--) { 
1307      yy =  ((double) (*amb++))*dams +DENORMALIZE;
1308      NTL_FetchHiLo(hi_wd, lo_wd, xx);
1309      lo = lo_wd & 0x3FFFFFF;
1310      hi = ((hi_wd<<6)|(lo_wd>>26)) & 0x3FFFFFF;
1311      lo = lo + carry;
1312      *ama = lo & 0x3FFFFFF;
1313      carry = hi + (lo >> 26);
1314      ama++; 
1315      xx = yy;
1316   } 
1317
1318   NTL_FetchHiLo(hi_wd, lo_wd, xx);
1319   lo = lo_wd & 0x3FFFFFF;
1320   hi = ((hi_wd<<6)|(lo_wd>>26)) & 0x3FFFFFF;
1321   lo = lo + carry;
1322   *ama = lo & 0x3FFFFFF;
1323   carry = hi + (lo >> 26);
1324   ama++; 
1325   *ama = carry; 
1326}
1327
1328static
1329void zaddmulsq(long ams, long *ama, long *amb) 
1330{ 
1331   long carry = 0; 
1332   long i = ams;
1333   double dams = (double) (*amb++);
1334   double xx;
1335   double yy;
1336   unsigned long lo, lo_wd;
1337   unsigned long hi, hi_wd;
1338
1339   xx =  ((double) (*amb++))*dams + DENORMALIZE;
1340   for (; i > 1; i--) { 
1341      yy =  ((double) (*amb++))*dams + DENORMALIZE;
1342      NTL_FetchHiLo(hi_wd, lo_wd, xx);
1343      lo = lo_wd & 0x3FFFFFF;
1344      hi = ((hi_wd<<6)|(lo_wd>>26)) & 0x3FFFFFF;
1345      lo = lo + (*ama) + carry;
1346      *ama = lo & 0x3FFFFFF;
1347      carry = hi + (lo >> 26);
1348      ama++; 
1349      xx = yy;
1350   } 
1351   if (i==1) {
1352      NTL_FetchHiLo(hi_wd, lo_wd, xx);
1353      lo = lo_wd & 0x3FFFFFF;
1354      hi = ((hi_wd<<6)|(lo_wd>>26)) & 0x3FFFFFF;
1355      lo = lo + (*ama) + carry;
1356      *ama = lo & 0x3FFFFFF;
1357      carry = hi + (lo >> 26);
1358      ama++; 
1359   }
1360   *ama += carry; 
1361}
1362
1363#elif (defined(NTL_AVOID_FLOAT) || defined(NTL_LONG_LONG))
1364
1365static
1366void zaddmul(long lams, long *lama, long *lamb)
1367{
1368        long lami;
1369        long lamcarry = 0;
1370
1371        for (lami = (*lamb++); lami > 0; lami--)
1372        {
1373                zaddmulp(*lama, *lamb, lams, lamcarry);
1374                lama++;
1375                lamb++;
1376        }
1377        *lama += lamcarry;
1378}
1379
1380static
1381void zsxmul(long lams, long *lama, long *lamb)
1382{
1383        long lami;
1384        long lamcarry = 0;
1385
1386        for (lami = (*lamb++); lami > 0; lami--)
1387        {
1388                zxmulp(*lama, *lamb, lams, lamcarry);
1389                lama++;
1390                lamb++;
1391        }
1392        *lama = lamcarry;
1393}
1394
1395static
1396void zaddmulsq(long lsqi, long *lsqa, long *lsqb)
1397{
1398        long lsqs = *(lsqb);
1399        long lsqcarry = 0;
1400
1401        lsqb++;
1402        for (; lsqi > 0; lsqi--)
1403        {
1404                zaddmulp(*lsqa, *lsqb, lsqs, lsqcarry);
1405                lsqa++;
1406                lsqb++;
1407        }
1408        *lsqa += lsqcarry;
1409}
1410
1411
1412#else
1413/* default long integer arithmetic */
1414
1415static
1416void zaddmul(long lams, long *lama, long *lamb)
1417{ 
1418   long lami = (*lamb++)-1; 
1419   long lamcarry = 0; 
1420   zam_decl;
1421
1422   zam_init(*lamb, lams);
1423   lamb++;
1424
1425 
1426   for (; lami > 0; lami--) { 
1427      zam_loop(*lama, lamcarry, *lamb);
1428      lama++; 
1429      lamb++; 
1430   } 
1431   zam_finish(*lama, lamcarry);
1432   lama++;
1433   *lama += lamcarry; 
1434}
1435
1436
1437
1438static
1439void zsxmul(long lams, long *lama, long *lamb)
1440{ 
1441   long lami = (*lamb++)-1; 
1442   long lamcarry = 0; 
1443   zam_decl;
1444
1445   zam_init(*lamb, lams);
1446   lamb++;
1447
1448 
1449   for (; lami > 0; lami--) { 
1450      zsx_loop(*lama, lamcarry, *lamb);
1451      lama++; 
1452      lamb++; 
1453   } 
1454   zsx_finish(*lama, lamcarry);
1455   lama++;
1456   *lama = lamcarry; 
1457}
1458
1459
1460
1461static
1462void zaddmulsq(long lsqi, long *lsqa, long *lsqb)
1463{ 
1464   long lsqs; 
1465   long lsqcarry; 
1466   zam_decl
1467
1468   if (lsqi <= 0) return;
1469
1470   lsqs = *lsqb;
1471   lsqcarry = 0;
1472
1473   lsqb++; 
1474   zam_init(*lsqb, lsqs);
1475   lsqb++;
1476   lsqi--;
1477   for (; lsqi > 0; lsqi--) { 
1478      zam_loop(*lsqa, lsqcarry, *lsqb);
1479      lsqa++; 
1480      lsqb++; 
1481   } 
1482   zam_finish(*lsqa, lsqcarry);
1483   lsqa++;
1484   *lsqa += lsqcarry; 
1485}
1486
1487
1488#endif
1489
1490
1491
1492
1493
1494
1495
1496/*
1497 * definition of zsubmul for the various long integer implementation options.
1498 * Note that zsubmul is only called with a positive first argument.
1499 */
1500
1501
1502
1503#if (defined(NTL_SINGLE_MUL))
1504
1505#if (NTL_ARITH_RIGHT_SHIFT)
1506
1507static
1508void zsubmul(long ams, long *ama, long *amb) 
1509{ 
1510   long carry = 0; 
1511   long i = (*amb++);
1512   double dams = (double) ams;
1513   double xx;
1514   double yy;
1515   unsigned long lo_wd, lo;
1516   unsigned long hi_wd, hi;
1517
1518   xx  =  ((double) (*amb++))*dams + DENORMALIZE;
1519   for (; i > 1; i--) { 
1520      yy =  ((double) (*amb++))*dams +DENORMALIZE;
1521      NTL_FetchHiLo(hi_wd, lo_wd, xx);
1522      lo = lo_wd & 0x3FFFFFF;
1523      hi = ((hi_wd<<6)|(lo_wd>>26)) & 0x3FFFFFF;
1524      lo = (*ama) + carry - lo;
1525      *ama = lo & 0x3FFFFFF;
1526      carry = (((long)lo) >> 26) - hi;
1527      ama++; 
1528      xx = yy;
1529   } 
1530
1531   NTL_FetchHiLo(hi_wd, lo_wd, xx);
1532   lo = lo_wd & 0x3FFFFFF;
1533   hi = ((hi_wd<<6)|(lo_wd>>26)) & 0x3FFFFFF;
1534   lo = (*ama) + carry - lo;
1535   *ama = lo & 0x3FFFFFF;
1536   carry = (((long)lo) >> 26) - hi;
1537   ama++; 
1538   *ama += carry; 
1539}
1540
1541#else
1542
1543static
1544void zsubmul(long ams, long *ama, long *amb) 
1545{ 
1546   long carry = 0; 
1547   long i = (*amb++);
1548   double dams = (double) ams;
1549   double xx;
1550   double yy;
1551   unsigned long lo_wd, lo;
1552   unsigned long hi_wd, hi;
1553
1554   xx  =  ((double) (*amb++))*dams + DENORMALIZE;
1555   for (; i > 1; i--) { 
1556      yy =  ((double) (*amb++))*dams +DENORMALIZE;
1557      NTL_FetchHiLo(hi_wd, lo_wd, xx);
1558      lo = lo_wd & 0x3FFFFFF;
1559      hi = ((hi_wd<<6)|(lo_wd>>26)) & 0x3FFFFFF;
1560      lo = (*ama) + carry - lo;
1561      *ama = lo & 0x3FFFFFF;
1562      carry = ((lo + (1L << 27)) >> 26) - hi - 2;
1563      ama++; 
1564      xx = yy;
1565   } 
1566
1567   NTL_FetchHiLo(hi_wd, lo_wd, xx);
1568   lo = lo_wd & 0x3FFFFFF;
1569   hi = ((hi_wd<<6)|(lo_wd>>26)) & 0x3FFFFFF;
1570   lo = (*ama) + carry - lo;
1571   *ama = lo & 0x3FFFFFF;
1572   carry = ((lo + (1L << 27)) >> 26) - hi - 2;
1573   ama++; 
1574   *ama += carry; 
1575}
1576
1577#endif
1578
1579
1580
1581#elif (defined(NTL_AVOID_FLOAT) || (defined(NTL_LONG_LONG) && defined(NTL_CLEAN_INT)))
1582
1583static void
1584zsubmul(
1585        long r,
1586        _ntl_verylong a,
1587        _ntl_verylong b
1588        )
1589{
1590        long rd = NTL_RADIX - r;
1591        long i;
1592        long carry = NTL_RADIX;
1593
1594        for (i = (*b++); i > 0; i--)
1595        {
1596                zaddmulp(*a, *b, rd, carry);
1597                a++;
1598                carry += NTL_RADIXM - (*b++);
1599        }
1600        *a += carry - NTL_RADIX; /* unnormalized */
1601}
1602
1603#elif (defined(NTL_LONG_LONG))
1604
1605/*
1606 * NOTE: the implementation of zaddmulp for the NTL_LONG_LONG option
1607 * will work on most machines even when the single-precision
1608 * multiplicand is negative;  however, the C language standard does
1609 * not guarantee correct behaviour in this case, which is why the above
1610 * implementation is used when NTL_CLEAN_INT is set.
1611 */
1612
1613static
1614void zsubmul(long lams, long *lama, long *lamb)
1615{
1616        long lami;
1617        long lamcarry = 0;
1618
1619        lams = -lams;
1620
1621        for (lami = (*lamb++); lami > 0; lami--)
1622        {
1623                zaddmulp(*lama, *lamb, lams, lamcarry);
1624                lama++;
1625                lamb++;
1626        }
1627        *lama += lamcarry;
1628}
1629
1630
1631#else
1632/* default long integer arithmetic */
1633
1634static
1635void zsubmul(long lams, long *lama, long *lamb)
1636{ 
1637   long lami = (*lamb++)-1; 
1638   CARRY_TYPE lamcarry = 0; 
1639   zam_decl;
1640
1641   zam_init(*lamb, lams);
1642   lamb++;
1643
1644 
1645   for (; lami > 0; lami--) { 
1646      zam_subloop(*lama, lamcarry, *lamb);
1647      lama++; 
1648      lamb++; 
1649   } 
1650   zam_subfinish(*lama, lamcarry);
1651   lama++;
1652   *lama += CARRY_CONV(lamcarry); 
1653}
1654
1655#endif
1656
1657
1658
1659
1660
1661/*
1662 *
1663 * zdiv21 returns quot, numhigh so
1664 *
1665 * quot = (numhigh*NTL_RADIX + numlow)/denom;
1666 * numhigh  = (numhigh*NTL_RADIX + numlow)%denom;
1667 * Assumes 0 <= numhigh < denom < NTL_RADIX and 0 <= numlow < NTL_RADIX.
1668 */
1669
1670
1671#if (defined(NTL_CLEAN_INT))
1672
1673/*
1674 * This "clean" version relies on the guaranteed semantics of
1675 * unsigned integer arithmetic.
1676 */
1677
1678#define zdiv21(numhigh, numlow, denom, deninv, quot) \
1679{ \
1680   unsigned long udenom = denom; \
1681   unsigned long lq21 = (long) (((NTL_FRADIX * (double) (numhigh)) + \
1682                        (double) (numlow)) * (deninv)); \
1683   unsigned long lr21 = (((unsigned long) numhigh) << NTL_NBITS) + \
1684                        ((unsigned long) numlow)  - udenom*lq21 ; \
1685 \
1686   if (lr21 >> (NTL_BITS_PER_LONG-1)) { \
1687      lq21--; \
1688      lr21 += udenom; \
1689   } \
1690   else if (lr21 >= udenom) { \
1691      lr21 -= udenom; \
1692      lq21++; \
1693   } \
1694   quot = (long) lq21; \
1695   numhigh = (long) lr21; \
1696}
1697
1698
1699#else
1700
1701/*
1702 * This "less clean" version relies on wrap-around semantics for
1703 * signed integer arithmetic.
1704 */
1705
1706#define zdiv21(numhigh, numlow, denom, deninv, quot) \
1707{ \
1708   long lr21; \
1709   long lq21 = (long) (((NTL_FRADIX * (double) (numhigh)) \
1710          + (double) (numlow)) * (deninv)); \
1711   long lp21; \
1712   MulLo(lp21, lq21, denom); \
1713   lr21 = (numhigh << NTL_NBITS) + numlow - lp21; \
1714   if (lr21 < 0) { \
1715      lq21--; \
1716      lr21 += denom; \
1717   } \
1718   else if (lr21 >= denom) { \
1719      lr21 -= denom; \
1720      lq21++; \
1721   } \
1722   quot = lq21; \
1723   numhigh = lr21; \
1724}
1725
1726#endif
1727
1728
1729
1730
1731/*
1732 * zrem21 behaves just like zdiv21, except the only the remainder is computed.
1733 */
1734
1735#if (defined(NTL_CLEAN_INT) || (defined(NTL_AVOID_BRANCHING)  && !NTL_ARITH_RIGHT_SHIFT))
1736#define NTL_CLEAN_SPMM
1737#endif
1738
1739#if (defined(NTL_CLEAN_SPMM)  && !defined(NTL_AVOID_BRANCHING))
1740
1741#define zrem21(numhigh, numlow, denom, deninv) \
1742{ \
1743   unsigned long udenom = denom; \
1744   unsigned long lq21 = (long) (((NTL_FRADIX * (double) (numhigh)) + \
1745                        (double) (numlow)) * (deninv)); \
1746   unsigned long lr21 = (((unsigned long) numhigh) << NTL_NBITS) + \
1747                        ((unsigned long) numlow)  - udenom*lq21 ; \
1748 \
1749   if (lr21 >> (NTL_BITS_PER_LONG-1)) { \
1750      lr21 += udenom; \
1751   } \
1752   else if (lr21 >= udenom) { \
1753      lr21 -= udenom; \
1754   } \
1755   numhigh = (long) lr21; \
1756}
1757
1758#elif (defined(NTL_CLEAN_SPMM)  && defined(NTL_AVOID_BRANCHING))
1759
1760
1761#define zrem21(numhigh, numlow, denom, deninv) \
1762{ \
1763   unsigned long udenom = denom; \
1764   unsigned long lq21 = (long) (((NTL_FRADIX * (double) (numhigh)) + \
1765                        (double) (numlow)) * (deninv)); \
1766   unsigned long lr21 = (((unsigned long) numhigh) << NTL_NBITS) + \
1767                        ((unsigned long) numlow)  - udenom*lq21 ; \
1768   lr21 += (-(lr21 >> (NTL_BITS_PER_LONG-1))) & udenom; \
1769   lr21 -= udenom; \
1770   lr21 += (-(lr21 >> (NTL_BITS_PER_LONG-1))) & udenom; \
1771   numhigh = (long) lr21; \
1772}
1773
1774
1775#elif (NTL_ARITH_RIGHT_SHIFT && defined(NTL_AVOID_BRANCHING))
1776
1777#define zrem21(numhigh, numlow, denom, deninv) \
1778{ \
1779   long lr21; \
1780   long lq21 = (long) (((NTL_FRADIX * (double) (numhigh)) \
1781          + (double) (numlow)) * (deninv)); \
1782   long lp21; \
1783   MulLo(lp21, lq21, denom); \
1784   lr21 = (numhigh << NTL_NBITS) + numlow - lp21; \
1785   lr21 += (lr21 >> (NTL_BITS_PER_LONG-1)) & denom; \
1786   lr21 -= denom; \
1787   lr21 += (lr21 >> (NTL_BITS_PER_LONG-1)) & denom; \
1788   numhigh = lr21; \
1789}
1790
1791#else
1792
1793#define zrem21(numhigh, numlow, denom, deninv) \
1794{ \
1795   long lr21; \
1796   long lq21 = (long) (((NTL_FRADIX * (double) (numhigh)) \
1797      + (double) (numlow)) * (deninv)); \
1798   long lp21; \
1799   MulLo(lp21, lq21, denom); \
1800   lr21 = (numhigh << NTL_NBITS) + numlow - lp21; \
1801   if (lr21 < 0) lr21 += denom; \
1802   else if (lr21 >= denom) lr21 -= denom; \
1803   numhigh = lr21; \
1804}
1805
1806#endif
1807
1808
1809
1810void _ntl_zsetlength(_ntl_verylong *v, long len)
1811{
1812   _ntl_verylong x = *v;
1813
1814   if (len < 0)
1815      zhalt("negative size allocation in _ntl_zsetlength");
1816
1817   if (NTL_OVERFLOW(len, NTL_NBITS, 0))
1818      zhalt("size too big in _ntl_zsetlength");
1819
1820#ifdef L_TO_G_CHECK_LEN
1821   /* this makes sure that numbers don't get too big for GMP */
1822   if (len >= (1L << (NTL_BITS_PER_INT-4)))
1823      zhalt("size too big for GMP");
1824#endif
1825
1826   if (x) {
1827      long oldlen = x[-1];
1828      long fixed = oldlen & 1;
1829
1830      oldlen = oldlen >> 1;
1831
1832      if (fixed) {
1833         if (len > oldlen) 
1834            zhalt("internal error: can't grow this _ntl_verylong");
1835         else
1836            return;
1837      }
1838
1839      if (len <= oldlen) return;
1840
1841      len++;  /* always allocate at least one more than requested */
1842
1843      oldlen = (long) (oldlen * 1.2); /* always increase by at least 20% */
1844      if (len < oldlen)
1845         len = oldlen;
1846
1847      /* round up to multiple of MIN_SETL */
1848      len = ((len+(MIN_SETL-1))/MIN_SETL)*MIN_SETL; 
1849
1850      /* test len again */
1851      if (NTL_OVERFLOW(len, NTL_NBITS, 0))
1852         zhalt("size too big in _ntl_zsetlength");
1853
1854      x[-1] = len << 1;
1855      if (!(x = (_ntl_verylong)NTL_REALLOC(&(x[-1]), 
1856                  len, sizeof(long), 2*sizeof(long)))) {
1857         zhalt("reallocation failed in _ntl_zsetlength");
1858      }
1859   }
1860   else {
1861      len++;
1862      len = ((len+(MIN_SETL-1))/MIN_SETL)*MIN_SETL;
1863
1864      /* test len again */
1865      if (NTL_OVERFLOW(len, NTL_NBITS, 0))
1866         zhalt("size too big in _ntl_zsetlength");
1867
1868
1869      if (!(x = (_ntl_verylong)NTL_MALLOC(len, 
1870                  sizeof(long), 2*sizeof(long)))) {
1871         zhalt("allocation failed in _ntl_zsetlength");
1872      }
1873      x[0] = len << 1;
1874      x[1] = 1;
1875      x[2] = 0;
1876   }
1877
1878   *v = x+1;
1879}
1880
1881void _ntl_zfree(_ntl_verylong *x)
1882{
1883   _ntl_verylong y;
1884
1885   if (!(*x))
1886      return;
1887
1888   if ((*x)[-1] & 1)
1889      zhalt("Internal error: can't free this _ntl_verylong");
1890
1891   y = (*x - 1);
1892   free((void*)y);
1893   *x = 0;
1894}
1895
1896
1897
1898
1899
1900
1901long _ntl_zround_correction(_ntl_verylong a, long k, long residual)
1902{
1903   long direction;
1904   long p;
1905   long sgn;
1906   long bl;
1907   long wh;
1908   long i;
1909
1910   if (a[0] > 0)
1911      sgn = 1;
1912   else
1913      sgn = -1;
1914
1915   p = k - 1;
1916   bl = (p/NTL_NBITS);
1917   wh = 1L << (p - NTL_NBITS*bl);
1918   bl++;
1919
1920   if (a[bl] & wh) {
1921      /* bit is 1...we have to see if lower bits are all 0
1922         in order to implement "round to even" */
1923
1924      if (a[bl] & (wh - 1)) 
1925         direction = 1;
1926      else {
1927         i = bl - 1;
1928         while (i > 0 && a[i] == 0) i--;
1929         if (i > 0)
1930            direction = 1;
1931         else
1932            direction = 0;
1933      }
1934
1935      /* use residual to break ties */
1936
1937      if (direction == 0 && residual != 0) {
1938         if (residual == sgn)
1939            direction = 1;
1940         else 
1941            direction = -1;
1942      }
1943
1944      if (direction == 0) {
1945         /* round to even */
1946
1947         wh = wh << 1;
1948         if (wh == NTL_RADIX) {
1949            wh = 1;
1950            bl++;
1951         }
1952
1953         if (a[bl] & wh)
1954            direction = 1;
1955         else
1956            direction = -1;
1957      }
1958   }
1959   else
1960      direction = -1;
1961
1962   if (direction == 1)
1963      return sgn;
1964
1965   return 0;
1966}
1967
1968
1969
1970double _ntl_zdoub_aux(_ntl_verylong n)
1971{
1972   double res;
1973   long i;
1974
1975   if (!n)
1976      return ((double) 0);
1977   if ((i = n[0]) < 0)
1978      i = -i;
1979   res = (double) (n[i--]);
1980   for (; i; i--)
1981      res = res * NTL_FRADIX + (double) (n[i]);
1982   if (n[0] > 0)
1983      return (res);
1984   return (-res);
1985}
1986
1987
1988
1989double _ntl_zdoub(_ntl_verylong n)
1990{
1991   static _ntl_verylong tmp = 0;
1992
1993   long s;
1994   long shamt;
1995   long correction;
1996   double x;
1997
1998   s = _ntl_z2log(n);
1999   shamt = s - NTL_DOUBLE_PRECISION;
2000
2001   if (shamt <= 0)
2002      return _ntl_zdoub_aux(n);
2003
2004   _ntl_zrshift(n, shamt, &tmp);
2005
2006   correction = _ntl_zround_correction(n, shamt, 0);
2007
2008   if (correction) _ntl_zsadd(tmp, correction, &tmp);
2009
2010   x = _ntl_zdoub_aux(tmp);
2011
2012   x = _ntl_ldexp(x, shamt);
2013
2014   return x;
2015}
2016
2017
2018double _ntl_zlog(_ntl_verylong n)
2019{
2020   static _ntl_verylong tmp = 0;
2021
2022   static double log_2;
2023   static long init = 0;
2024
2025   long s;
2026   long shamt;
2027   long correction;
2028   double x;
2029
2030   if (!init) {
2031      log_2 = log(2.0);
2032      init = 1;
2033   }
2034
2035   if (_ntl_zsign(n) <= 0)
2036      zhalt("log argument <= 0");
2037
2038   s = _ntl_z2log(n);
2039   shamt = s - NTL_DOUBLE_PRECISION;
2040
2041   if (shamt <= 0)
2042      return log(_ntl_zdoub_aux(n));
2043
2044   _ntl_zrshift(n, shamt, &tmp);
2045
2046   correction = _ntl_zround_correction(n, shamt, 0);
2047
2048   if (correction) _ntl_zsadd(tmp, correction, &tmp);
2049
2050   x = _ntl_zdoub_aux(tmp);
2051
2052   return log(x) + shamt*log_2;
2053}
2054
2055
2056
2057void _ntl_zdoubtoz(double a, _ntl_verylong *xx)
2058{
2059   _ntl_verylong x;
2060   long neg, i, t, sz;
2061
2062
2063   a = floor(a);
2064
2065   if (!_ntl_IsFinite(&a))
2066      zhalt("_ntl_zdoubtoz: attempt to convert non-finite value");
2067
2068
2069   if (a < 0) {
2070      a = -a;
2071      neg = 1;
2072   }
2073   else
2074      neg = 0;
2075
2076   if (a == 0) {
2077      _ntl_zzero(xx);
2078      return;
2079   }
2080
2081   sz = 1;
2082   a = a*NTL_FRADIX_INV;
2083
2084   while (a >= 1) {
2085      a = a*NTL_FRADIX_INV;
2086      sz++;
2087   }
2088         
2089   x = *xx;
2090   if (MustAlloc(x, sz)) {
2091      _ntl_zsetlength(&x, sz);
2092      *xx = x;
2093   }
2094
2095   for (i = sz; i > 0; i--) {
2096      a = a*NTL_FRADIX;
2097      t = (long) a;
2098      x[i] = t;
2099      a = a - t;
2100   }
2101
2102   x[0] = (neg ? -sz : sz);
2103}
2104
2105void _ntl_zzero(_ntl_verylong *aa)
2106{
2107   if (!(*aa)) _ntl_zsetlength(aa, 1);
2108   (*aa)[0] =  1;
2109   (*aa)[1] =  0;
2110}
2111
2112/* same as _ntl_zzero, except does not unnecessarily allocate space */
2113
2114void _ntl_zzero1(_ntl_verylong *aa)
2115{
2116   if (!(*aa)) return;
2117   (*aa)[0] =  1;
2118   (*aa)[1] =  0;
2119}
2120
2121void _ntl_zone(_ntl_verylong *aa)
2122{
2123   if (!(*aa)) _ntl_zsetlength(aa, 1);
2124   (*aa)[0] =  1;
2125   (*aa)[1] =  1;
2126}
2127
2128void _ntl_zcopy(_ntl_verylong a, _ntl_verylong *bb)
2129{
2130   long i;
2131   _ntl_verylong b = *bb;
2132
2133   if (!a) {
2134      _ntl_zzero(bb);
2135      return;
2136   }
2137   if (a != b) {
2138      if ((i = *a) < 0)
2139         i = (-i);
2140      if (MustAlloc(b, i)) {
2141         _ntl_zsetlength(&b, i);
2142         *bb = b;
2143      }
2144      for (; i >= 0; i--)
2145         *b++ = *a++;
2146   }
2147}
2148
2149/* same as _ntl_zcopy, but does not unnecessarily allocate space */
2150
2151void _ntl_zcopy1(_ntl_verylong a, _ntl_verylong *bb)
2152{
2153   long i;
2154   _ntl_verylong b = *bb;
2155
2156   if (!a) {
2157      _ntl_zzero1(bb);
2158      return;
2159   }
2160   if (a != b) {
2161      if ((i = *a) < 0)
2162         i = (-i);
2163      if (MustAlloc(b, i)) {
2164         _ntl_zsetlength(&b, i);
2165         *bb = b;
2166      }
2167      for (; i >= 0; i--)
2168         *b++ = *a++;
2169   }
2170}
2171
2172void _ntl_zintoz(long d, _ntl_verylong *aa)
2173{
2174   long i;
2175   long anegative;
2176   unsigned long d1, d2;
2177   _ntl_verylong a = *aa;
2178
2179   anegative = 0;
2180   if (d < 0) {
2181      anegative = 1;
2182      d1 = - ((unsigned long) d);  /* careful: avoid overflow */
2183   }
2184   else
2185      d1 = d;
2186
2187   i = 0;
2188   d2 = d1;
2189   do {
2190      d2 >>= NTL_NBITS;
2191      i++;
2192   }
2193   while (d2 > 0);
2194
2195   if (MustAlloc(a, i)) {
2196      _ntl_zsetlength(&a, i);
2197      *aa = a;
2198   }
2199
2200   i = 0;
2201   a[1] = 0;
2202   while (d1 > 0) {
2203      a[++i] = d1 & NTL_RADIXM;
2204      d1 >>= NTL_NBITS;
2205   }
2206   if (i > 0)
2207      a[0] = i;
2208   else
2209      a[0] = 1;
2210
2211   if (anegative)
2212      a[0] = (-a[0]);
2213}
2214
2215
2216/* same as _ntl_zintoz, but does not unnecessarily allocate space */
2217
2218void _ntl_zintoz1(long d, _ntl_verylong *aa)
2219{
2220   long i;
2221   long anegative;
2222   unsigned long d1, d2;
2223   _ntl_verylong a = *aa;
2224
2225   if (!d && !a) return;
2226
2227   anegative = 0;
2228   if (d < 0) {
2229      anegative = 1;
2230      d1 = - ((unsigned long) d);  /* careful: avoid overlow */
2231   }
2232   else
2233      d1 = d;
2234
2235   i = 0;
2236   d2 = d1;
2237   do {
2238      d2 >>= NTL_NBITS;
2239      i++;
2240   }
2241   while (d2 > 0);
2242
2243   if (MustAlloc(a, i)) {
2244      _ntl_zsetlength(&a, i);
2245      *aa = a;
2246   }
2247
2248   i = 0;
2249   a[1] = 0;
2250   while (d1 > 0) {
2251      a[++i] = d1 & NTL_RADIXM;
2252      d1 >>= NTL_NBITS;
2253   }
2254   if (i > 0)
2255      a[0] = i;
2256   else
2257      a[0] = 1;
2258
2259   if (anegative)
2260      a[0] = (-a[0]);
2261}
2262
2263
2264void _ntl_zuintoz(unsigned long d, _ntl_verylong *aa)
2265{
2266   long i;
2267   unsigned long d1, d2;
2268   _ntl_verylong a = *aa;
2269
2270   d1 = d;
2271   i = 0;
2272   d2 = d1;
2273   do {
2274      d2 >>= NTL_NBITS;
2275      i++;
2276   }
2277   while (d2 > 0);
2278
2279   if (MustAlloc(a, i)) {
2280      _ntl_zsetlength(&a, i);
2281      *aa = a;
2282   }
2283
2284   i = 0;
2285   a[1] = 0;
2286   while (d1 > 0) {
2287      a[++i] = d1 & NTL_RADIXM;
2288      d1 >>= NTL_NBITS;
2289   }
2290   if (i > 0)
2291      a[0] = i;
2292   else
2293      a[0] = 1;
2294}
2295
2296
2297unsigned long _ntl_ztouint(_ntl_verylong a)
2298{
2299   unsigned long d;
2300   long sa;
2301
2302   if (!a)
2303      return (0);
2304
2305   if ((sa = *a) < 0)
2306      sa = -sa;
2307
2308   d = (unsigned long) (*(a += sa));
2309   while (--sa) {
2310      d <<= NTL_NBITS;
2311      d += (unsigned long) (*(--a));
2312   }
2313
2314   if ((*(--a)) < 0)
2315      return (-d);
2316   return (d);
2317}
2318
2319
2320long _ntl_ztoint(_ntl_verylong a)
2321{
2322   unsigned long res = _ntl_ztouint(a);
2323   return NTL_ULONG_TO_LONG(res);
2324}
2325
2326
2327
2328long _ntl_zcompare(_ntl_verylong a, _ntl_verylong b)
2329{
2330   long sa;
2331   long sb;
2332
2333   if (!a) {
2334      if (!b)
2335         return (0);
2336      if (b[0] < 0)
2337         return (1);
2338      if (b[0] > 1)
2339         return (-1);
2340      if (b[1])
2341         return (-1);
2342      return (0);
2343   }
2344   if (!b) {
2345      if (a[0] < 0)
2346         return (-1);
2347      if (a[0] > 1)
2348         return (1);
2349      if (a[1])
2350         return (1);
2351      return (0);
2352   }
2353
2354   if ((sa = *a) > (sb = *b))
2355      return (1);
2356   if (sa < sb)
2357      return (-1);
2358   if (sa < 0)
2359      sa = (-sa);
2360   a += sa;
2361   b += sa;
2362   for (; sa; sa--) {
2363      long diff = *a - *b;
2364
2365      if (diff > 0) {
2366         if (sb < 0)
2367            return (-1);
2368         return (1);
2369      }
2370      if (diff < 0) {
2371         if (sb < 0)
2372            return (1);
2373         return (-1);
2374      }
2375
2376      a--;
2377      b--;
2378   }
2379   return (0);
2380}
2381
2382void _ntl_znegate(_ntl_verylong *aa)
2383{
2384   _ntl_verylong a = *aa;
2385
2386   if (!a)
2387      return;
2388   if (a[1] || a[0] != 1)
2389      a[0] = (-a[0]);
2390}
2391
2392void _ntl_zsadd(_ntl_verylong a, long d, _ntl_verylong *b)
2393{
2394   static _ntl_verylong x = 0;
2395
2396   _ntl_zintoz(d, &x);
2397   _ntl_zadd(a, x, b);
2398}
2399
2400
2401void
2402_ntl_zadd(_ntl_verylong a, _ntl_verylong b, _ntl_verylong *cc)
2403{
2404   long sa;
2405   long sb;
2406   long anegative;
2407   _ntl_verylong c;
2408   long a_alias, b_alias;
2409
2410   if (!a) {
2411      if (b)
2412         _ntl_zcopy(b, cc);
2413      else
2414         _ntl_zzero(cc);
2415      return;
2416   }
2417
2418   if (!b) {
2419      _ntl_zcopy(a, cc);
2420      return;
2421   }
2422
2423   c = *cc;
2424   a_alias = (a == c);
2425   b_alias = (b == c);
2426
2427   if ((anegative = ((sa = a[0]) < 0)) == ((sb = b[0]) < 0)) {
2428      /* signs a and b are the same */
2429      _ntl_verylong pc;
2430      long carry;
2431      long i;
2432      long maxab;
2433
2434      if (anegative) {
2435         sa = -sa;
2436         sb = -sb;
2437      }
2438
2439      if (sa < sb) {
2440         i = sa;
2441         maxab = sb;
2442      }
2443      else {
2444         i = sb;
2445         maxab = sa;
2446      }
2447
2448      if (MustAlloc(c, maxab+1)) {
2449         _ntl_zsetlength(&c, maxab + 1);
2450         if (a_alias) a = c; 
2451         if (b_alias) b = c; 
2452         *cc = c;
2453      }
2454
2455      pc = c;
2456      carry = 0;
2457
2458      do {
2459         long t = (*(++a)) + (*(++b)) + carry;
2460         carry = t >> NTL_NBITS;
2461         *(++pc) = t & NTL_RADIXM;
2462         i--;
2463      } while (i);
2464
2465      i = sa-sb;
2466      if (!i) goto i_exit;
2467
2468      if (i < 0) {
2469         i = -i;
2470         a = b;
2471      }
2472
2473      if (!carry) goto carry_exit;
2474
2475      for (;;) {
2476         long t = (*(++a)) + 1;
2477         carry = t >> NTL_NBITS;
2478         *(++pc) = t & NTL_RADIXM;
2479         i--;
2480         if (!i) goto i_exit;
2481         if (!carry) goto carry_exit;
2482      }
2483
2484      i_exit:
2485      if (carry) {
2486         *(++pc) = 1;
2487         maxab++;
2488      }
2489      *c = anegative ? -maxab : maxab;
2490      return;
2491
2492      carry_exit:
2493      if (pc != a) {
2494         do {
2495            *(++pc) = *(++a);
2496            i--;
2497         } while (i);
2498      }
2499      *c = anegative ? -maxab : maxab;
2500   }
2501   else {
2502      /* signs a and b are different...use _ntl_zsub */
2503
2504      if (anegative) {
2505         a[0] = -sa;
2506         _ntl_zsub(b, a, cc);
2507         if (!a_alias) a[0] = sa;
2508      }
2509      else {
2510         b[0] = -sb;
2511         _ntl_zsub(a, b, cc);
2512         if (!b_alias) b[0] = sb;
2513      }
2514   }
2515}
2516
2517void
2518_ntl_zsub(_ntl_verylong a, _ntl_verylong b, _ntl_verylong *cc)
2519{
2520   long sa;
2521   long sb;
2522   long anegative;
2523   long a_alias, b_alias;
2524   _ntl_verylong c;
2525
2526   if (!b) {
2527      if (a)
2528         _ntl_zcopy(a, cc);
2529      else
2530         _ntl_zzero(cc);
2531      return;
2532   }
2533
2534   if (!a) {
2535      _ntl_zcopy(b, cc);
2536      _ntl_znegate(cc);
2537      return;
2538   }
2539
2540   c = *cc;
2541   a_alias = (a == c);
2542   b_alias = (b == c);
2543
2544   if ((anegative = ((sa = a[0]) < 0)) == ((sb = b[0]) < 0)) {
2545      /* signs agree */
2546
2547      long i, carry, *pc;
2548
2549      if (anegative) {
2550         sa = -sa;
2551         sb = -sb;
2552      }
2553
2554      carry = sa - sb;
2555      if (!carry) {
2556         long *aa = a + sa;
2557         long *bb = b + sa;
2558         
2559         i = sa;
2560         while (i && !(carry = (*aa - *bb))) {
2561            aa--; bb--; i--;
2562         }
2563      }
2564
2565      if (!carry) {
2566         _ntl_zzero(cc);
2567         return;
2568      }
2569
2570      if (carry < 0) {
2571         { long t = sa; sa = sb; sb = t; }
2572         { long t = a_alias; a_alias = b_alias; b_alias = t; }
2573         { long *t = a; a = b; b = t; }
2574         anegative = !anegative;
2575      }
2576
2577      if (MustAlloc(c, sa)) {
2578         _ntl_zsetlength(&c, sa);
2579         /* must have !a_alias */
2580         if (b_alias) b = c;
2581         *cc = c;
2582      }
2583
2584      i = sb;
2585      carry = 0;
2586      pc = c;
2587
2588      do {
2589#if (!NTL_ARITH_RIGHT_SHIFT || defined(NTL_CLEAN_INT))
2590         long t = (*(++a)) - (*(++b)) - carry;
2591         carry = (t < 0);
2592#else
2593         long t = (*(++a)) - (*(++b)) + carry;
2594         carry = t >> NTL_NBITS;
2595#endif
2596         *(++pc) = t & NTL_RADIXM;
2597         i--;
2598      } while (i);
2599
2600      i = sa-sb;
2601      while (carry) {
2602         long t = (*(++a)) - 1;
2603#if (!NTL_ARITH_RIGHT_SHIFT || defined(NTL_CLEAN_INT))
2604         carry = (t < 0);
2605#else
2606         carry = t >> NTL_NBITS;
2607#endif
2608         *(++pc) = t & NTL_RADIXM;
2609         i--;
2610      }
2611
2612      if (i) {
2613         if (pc != a) {
2614            do {
2615               *(++pc) = *(++a);
2616               i--;
2617            } while (i);
2618         }
2619      }
2620      else {
2621         while (sa > 1 && *pc == 0) { sa--; pc--; } 
2622      }
2623
2624      if (anegative) sa = -sa;
2625      *c = sa;
2626   }
2627   else {
2628      /* signs of a and b are different...use _ntl_zadd */
2629
2630      if (anegative) {
2631         a[0] = -sa;
2632         _ntl_zadd(a, b, cc);
2633         if (!a_alias) a[0] = sa;
2634         c = *cc;
2635         c[0] = -c[0];
2636      }
2637      else {
2638         b[0] = -sb;
2639         _ntl_zadd(a, b, cc);
2640         if (!b_alias) b[0] = sb;
2641      }
2642   }
2643}
2644
2645
2646void
2647_ntl_zsmul(_ntl_verylong a, long d, _ntl_verylong *bb)
2648{
2649   long sa;
2650   long anegative, bnegative;
2651   _ntl_verylong b;
2652   long a_alias;
2653
2654
2655   if (d == 2) {
2656      _ntl_z2mul(a, bb);
2657      return;
2658   }
2659
2660
2661   if ((d >= NTL_RADIX) || (d <= -NTL_RADIX)) {
2662      static _ntl_verylong x = 0;
2663      _ntl_zintoz(d,&x);
2664      _ntl_zmul(a, x, bb);
2665      return;
2666   }
2667
2668   if (!a || (a[0] == 1 && a[1] == 0)) {
2669      _ntl_zzero(bb);
2670      return;
2671   }
2672
2673   if (!d) {
2674      _ntl_zzero(bb);
2675      return;
2676   }
2677
2678   /* both inputs non-zero */
2679
2680   anegative = 0;
2681   bnegative = 0;
2682
2683   if ((sa = a[0]) < 0) {
2684      anegative = 1;
2685      a[0] = sa = (-sa);
2686      if (d < 0)
2687         d = (-d);
2688      else
2689         bnegative = 1;
2690   }
2691   else if (bnegative = (d < 0))
2692      d = (-d);
2693
2694   b = *bb;
2695   a_alias = (a == b);
2696
2697   if (MustAlloc(b, sa + 1)) {
2698      _ntl_zsetlength(&b, sa + 1);
2699      if (a_alias) a = b;
2700      *bb = b;
2701   }
2702
2703   zsxmul(d, b+1, a);
2704
2705   sa++;
2706   while ((sa > 1) && (!(b[sa])))
2707      sa--;
2708   b[0] = sa;
2709
2710   if (bnegative)
2711      b[0] = (-b[0]);
2712
2713   if (anegative && !a_alias)
2714      a[0] = -a[0];
2715}
2716
2717void _ntl_zsubpos(_ntl_verylong a, _ntl_verylong b, _ntl_verylong *cc)
2718{
2719   long sa;
2720   long sb;
2721
2722   long *c, *pc;
2723   long i, carry;
2724
2725   long b_alias;
2726
2727   if (!b) {
2728      if (a)
2729         _ntl_zcopy(a, cc);
2730      else
2731         _ntl_zzero(cc);
2732      return;
2733   }
2734
2735   if (!a) {
2736      _ntl_zzero(cc);
2737      return;
2738   }
2739
2740   sa = a[0];
2741   sb = b[0];
2742
2743   c = *cc;
2744   b_alias = (b == c);
2745
2746   if (MustAlloc(c, sa)) {
2747      _ntl_zsetlength(&c, sa);
2748      if (b_alias) b = c;
2749      *cc = c;
2750   }
2751
2752   i = sb;
2753   carry = 0;
2754   pc = c;
2755
2756   while (i) {
2757#if (!NTL_ARITH_RIGHT_SHIFT || defined(NTL_CLEAN_INT))
2758      long t = (*(++a)) - (*(++b)) - carry;
2759      carry = (t < 0);
2760#else
2761      long t = (*(++a)) - (*(++b)) + carry;
2762      carry = t >> NTL_NBITS;
2763#endif
2764      *(++pc) = t & NTL_RADIXM;
2765      i--;
2766   }
2767
2768   i = sa-sb;
2769   while (carry) {
2770      long t = (*(++a)) - 1;
2771#if (!NTL_ARITH_RIGHT_SHIFT || defined(NTL_CLEAN_INT))
2772      carry = (t < 0);
2773#else
2774      carry = t >> NTL_NBITS;
2775#endif
2776      *(++pc) = t & NTL_RADIXM;
2777      i--;
2778   }
2779
2780   if (i) {
2781      if (pc != a) {
2782         do {
2783            *(++pc) = *(++a);
2784            i--;
2785         } while (i);
2786      }
2787   }
2788   else {
2789      while (sa > 1 && *pc == 0) { sa--; pc--; } 
2790   }
2791
2792   *c = sa;
2793}
2794
2795
2796
2797
2798
2799static long *kmem = 0;     /* globals for Karatsuba */
2800static long max_kmem = 0;
2801
2802
2803/* These cross-over points were estimated using
2804   a Sparc-10, a Sparc-20, and a Pentium-90. */
2805
2806#if (defined(NTL_SINGLE_MUL))
2807#define KARX (18)
2808#else
2809#define KARX (16)
2810#endif
2811
2812/* Auxilliary routines for Karatsuba */
2813
2814
2815static
2816void kar_fold(long *T, long *b, long hsa)
2817{
2818   long sb, *p2, *p3, i, carry;
2819
2820   sb = *b;
2821   p2 = b + hsa;
2822   p3 = T;
2823   carry = 0;
2824
2825   for (i = sb-hsa; i>0; i--) {
2826      long t = (*(++b)) + (*(++p2)) + carry;
2827      carry = t >> NTL_NBITS;
2828      *(++p3) = t & NTL_RADIXM;
2829   }
2830
2831   for (i = (hsa << 1) - sb; i>0; i--) {
2832      long t = (*(++b)) + carry;
2833      carry = t >> NTL_NBITS;
2834      *(++p3) = t & NTL_RADIXM;
2835   }
2836
2837   if (carry) {
2838      *(++p3) = carry;
2839      *T = hsa + 1;
2840   }
2841   else
2842      *T = hsa;
2843}
2844
2845static
2846void kar_sub(long *T, long *c)
2847{
2848   long i, carry;
2849
2850   i = *c;
2851   carry = 0;
2852
2853   while (i>0) {
2854#if (!NTL_ARITH_RIGHT_SHIFT || defined(NTL_CLEAN_INT))
2855      long t = (*(++T)) - (*(++c)) - carry;
2856      carry = (t < 0);
2857#else
2858      long t = (*(++T)) - (*(++c)) + carry;
2859      carry = t >> NTL_NBITS;
2860#endif
2861      *T = t & NTL_RADIXM;
2862      i--;
2863   }
2864
2865   while (carry) {
2866      long t = (*(++T)) - 1;
2867#if (!NTL_ARITH_RIGHT_SHIFT || defined(NTL_CLEAN_INT))
2868      carry = (t < 0);
2869#else
2870      carry = t >> NTL_NBITS;
2871#endif
2872      *T = t & NTL_RADIXM;
2873   }
2874}
2875
2876
2877static
2878void kar_add(long *c, long *T, long hsa)
2879{
2880   long i, carry;
2881
2882   c += hsa;
2883   i = *T;
2884   while (T[i] == 0 && i > 0) i--;
2885   carry = 0;
2886
2887   while (i>0) {
2888      long t = (*(++c)) + (*(++T)) + carry;
2889      carry = t >> NTL_NBITS;
2890      *c = t & NTL_RADIXM;
2891      i--;
2892   }
2893
2894   while (carry) {
2895      long t = (*(++c)) + 1;
2896      carry = t >> NTL_NBITS;
2897      *c = t & NTL_RADIXM;
2898   }
2899}
2900
2901static
2902void kar_fix(long *c, long *T, long hsa)
2903{
2904   long i, carry, s;
2905
2906   s = *T;
2907
2908   i = hsa;
2909   while (i>0) {
2910      *(++c) = *(++T);
2911      i--;
2912   }
2913
2914
2915   i = s - hsa;
2916   carry = 0;
2917
2918   while (i > 0) {
2919      long t = (*(++c)) + (*(++T)) + carry;
2920      carry = t >> NTL_NBITS;
2921      *c = t & NTL_RADIXM;
2922      i--;
2923   }
2924
2925   while (carry) {
2926      long t = (*(++c)) + 1;
2927      carry = t >> NTL_NBITS;
2928      *c = t & NTL_RADIXM;
2929   }
2930}
2931     
2932   
2933
2934static
2935void kar_mul(long *c, long *a, long *b, long *stk)
2936{
2937   long sa, sb, sc;
2938
2939   if (*a < *b) { long *t = a; a = b; b = t; }
2940
2941   sa = *a;
2942   sb = *b;
2943   sc = sa + sb;
2944
2945   if (sb < KARX) {
2946      /* classic algorithm */
2947
2948      long *pc, i, *pb;
2949
2950      pc = c;
2951      for (i = sc; i; i--) {
2952         pc++;
2953         *pc = 0;
2954      }
2955   
2956      pc = c;
2957      pb = b;
2958      for (i = sb; i; i--) {
2959         pb++;
2960         pc++;
2961         zaddmul(*pb, pc, a);
2962      }
2963   }
2964   else {
2965      long hsa = (sa + 1) >> 1;
2966
2967      if (hsa < sb) {
2968         /* normal case */
2969
2970         long *T1, *T2, *T3;
2971
2972         /* allocate space */
2973
2974         T1 = stk;  stk += hsa + 2;
2975         T2 = stk;  stk += hsa + 2;
2976         T3 = stk;  stk += (hsa << 1) + 3;
2977
2978         if (stk-kmem > max_kmem) zhalt("internal error: kmem overflow");
2979
2980         /* compute T1 = a_lo + a_hi */
2981
2982         kar_fold(T1, a, hsa);
2983
2984         /* compute T2 = b_lo + b_hi */
2985
2986         kar_fold(T2, b, hsa);
2987         
2988         /* recursively compute T3 = T1 * T2 */
2989
2990         kar_mul(T3, T1, T2, stk);
2991
2992         /* recursively compute a_hi * b_hi into high part of c */
2993         /* and subtract from T3 */
2994
2995         {
2996            long olda, oldb;
2997
2998            olda = a[hsa];  a[hsa] = sa-hsa;
2999            oldb = b[hsa];  b[hsa] = sb-hsa;
3000
3001            kar_mul(c + (hsa << 1), a + hsa, b + hsa, stk);
3002            kar_sub(T3, c + (hsa << 1));
3003
3004            a[hsa] = olda;
3005            b[hsa] = oldb;
3006         }
3007
3008         /* recursively compute a_lo*b_lo into low part of c */
3009         /* and subtract from T3 */
3010
3011         *a = hsa;
3012         *b = hsa;
3013
3014         kar_mul(c, a, b, stk);
3015         kar_sub(T3, c);
3016
3017         *a = sa;
3018         *b = sb;
3019
3020         /* finally, add T3 * NTL_RADIX^{hsa} to c */
3021
3022         kar_add(c, T3, hsa);
3023      }
3024      else {
3025         /* degenerate case */
3026
3027         long *T;
3028         
3029         T = stk;  stk += sb + hsa + 1;
3030
3031         if (stk-kmem > max_kmem) zhalt("internal error: kmem overflow");
3032
3033         /* recursively compute b*a_hi into high part of c */
3034         {
3035            long olda;
3036
3037            olda = a[hsa];  a[hsa] = sa-hsa;
3038            kar_mul(c + hsa, a + hsa, b, stk);
3039            a[hsa] = olda;
3040         }
3041
3042         /* recursively compute b*a_lo into T */
3043
3044         *a = hsa;
3045         kar_mul(T, a, b, stk);
3046         *a = sa;
3047
3048         /* fix-up result */
3049
3050         kar_fix(c, T, hsa);
3051      }
3052   }
3053
3054   /* normalize result */
3055
3056   while (c[sc] == 0 && sc > 1) sc--;
3057   *c = sc;
3058}
3059
3060
3061
3062#if (defined(NTL_SINGLE_MUL))
3063#define KARSX (36)
3064#else
3065#define KARSX (32)
3066#endif
3067
3068static
3069void kar_sq(long *c, long *a, long *stk)
3070{
3071   long sa, sc;
3072
3073   sa = *a;
3074   sc = sa << 1;
3075
3076   if (sa < KARSX) {
3077      /* classic algorithm */
3078
3079      long carry, i, j, *pc;
3080
3081      pc = c;
3082      for (i = sc; i; i--) {
3083         pc++;
3084         *pc = 0;
3085      }
3086
3087      carry = 0;
3088      i = 0;
3089      for (j = 1; j <= sa; j++) {
3090         unsigned long uncar;
3091         long t;
3092
3093         i += 2;
3094         uncar = ((unsigned long) carry) + (((unsigned long) c[i-1]) << 1);
3095         t = uncar & NTL_RADIXM;
3096         zaddmulpsq(t, a[j], carry);
3097         c[i-1] = t;
3098         zaddmulsq(sa-j, c+i, a+j);
3099         uncar =  (uncar >> NTL_NBITS) + (((unsigned long) c[i]) << 1);
3100         uncar += ((unsigned long) carry);
3101         carry = uncar >> NTL_NBITS;
3102         c[i] = uncar & NTL_RADIXM;
3103      }
3104   }
3105   else {
3106      long hsa = (sa + 1) >> 1;
3107      long *T1, *T2, olda;
3108
3109      T1 = stk;  stk += hsa + 2;
3110      T2 = stk;  stk += (hsa << 1) + 3;
3111
3112      if (stk-kmem > max_kmem) zhalt("internal error: kmem overflow");
3113
3114      kar_fold(T1, a, hsa);
3115      kar_sq(T2, T1, stk);
3116
3117      olda = a[hsa];  a[hsa] = sa - hsa;
3118      kar_sq(c + (hsa << 1), a + hsa, stk);
3119      kar_sub(T2, c + (hsa << 1));
3120      a[hsa] = olda;
3121
3122      *a = hsa;
3123      kar_sq(c, a, stk);
3124      kar_sub(T2, c);
3125      *a = sa;
3126
3127      kar_add(c, T2, hsa);
3128   }
3129
3130   while (c[sc] == 0 && sc > 1) sc--;
3131   *c = sc;
3132}
3133
3134
3135void _ntl_zmul(_ntl_verylong a, _ntl_verylong b, _ntl_verylong *cc)
3136{
3137   static _ntl_verylong mem = 0;
3138   _ntl_verylong c = *cc;
3139
3140   if (!a || (a[0] == 1 && a[1] == 0) || !b || (b[0] == 1 && b[1] == 0)) {
3141      _ntl_zzero(cc);
3142      return;
3143   }
3144
3145   if (a == b) {
3146      if (a == c) {
3147         _ntl_zcopy(a, &mem);
3148         a = mem;
3149      }
3150
3151      _ntl_zsq(a, cc);
3152   }
3153   else {
3154      long aneg, bneg, sa, sb, sc;
3155
3156      if (a == c) {
3157         _ntl_zcopy(a, &mem);
3158         a = mem;
3159      }
3160      else if (b == c) {
3161         _ntl_zcopy(b, &mem);
3162         b = mem;
3163      }
3164
3165      sa = *a;
3166      if (sa < 0) {
3167         *a = sa = -sa;
3168         aneg = 1;
3169      }
3170      else
3171         aneg = 0;
3172
3173      sb = *b;
3174      if (*b < 0) {
3175         *b = sb =  -sb;
3176         bneg = 1;
3177      }
3178      else
3179         bneg = 0;
3180
3181      sc = sa + sb;
3182      if (MustAlloc(c, sc)) {
3183         _ntl_zsetlength(&c, sc);
3184         *cc = c;
3185      }
3186
3187      /* we optimize for *very* small numbers,
3188       * avoiding all function calls and loops */
3189
3190      if (sa <= 3 && sb <= 3) {
3191         long carry, d;
3192
3193         switch (sa) {
3194         case 1:
3195            switch (sb) {
3196            case 1:
3197               carry = 0;
3198               zxmulp(c[1], a[1], b[1], carry);
3199               c[2] = carry;
3200               break;
3201            case 2:
3202               carry = 0;
3203               d = a[1];
3204               zxmulp(c[1], b[1], d, carry);
3205               zxmulp(c[2], b[2], d, carry);
3206               c[3] = carry;
3207               break;
3208            case 3:
3209               carry = 0;
3210               d = a[1];
3211               zxmulp(c[1], b[1], d, carry);
3212               zxmulp(c[2], b[2], d, carry);
3213               zxmulp(c[3], b[3], d, carry);
3214               c[4] = carry;
3215               break;
3216            }
3217            break;
3218
3219         case 2:
3220            switch (sb) {
3221            case 1:
3222               carry = 0;
3223               d = b[1];
3224               zxmulp(c[1], a[1], d, carry);
3225               zxmulp(c[2], a[2], d, carry);
3226               c[3] = carry;
3227               break;
3228            case 2:
3229               carry = 0;
3230               d = b[1];
3231               zxmulp(c[1], a[1], d, carry);
3232               zxmulp(c[2], a[2], d, carry);
3233               c[3] = carry;
3234               carry = 0;
3235               d = b[2];
3236               zaddmulp(c[2], a[1], d, carry);
3237               zaddmulp(c[3], a[2], d, carry);
3238               c[4] = carry;
3239               break;
3240             case 3:
3241               carry = 0;
3242               d = a[1];
3243               zxmulp(c[1], b[1], d, carry);
3244               zxmulp(c[2], b[2], d, carry);
3245               zxmulp(c[3], b[3], d, carry);
3246               c[4] = carry;
3247               carry = 0;
3248               d = a[2];
3249               zaddmulp(c[2], b[1], d, carry);
3250               zaddmulp(c[3], b[2], d, carry);
3251               zaddmulp(c[4], b[3], d, carry);
3252               c[5] = carry;
3253               break;
3254            }
3255            break;
3256
3257         case 3:
3258            switch (sb) {
3259            case 1:
3260               carry = 0;
3261               d = b[1];
3262               zxmulp(c[1], a[1], d, carry);
3263               zxmulp(c[2], a[2], d, carry);
3264               zxmulp(c[3], a[3], d, carry);
3265               c[4] = carry;
3266               break;
3267            case 2:
3268               carry = 0;
3269               d = b[1];
3270               zxmulp(c[1], a[1], d, carry);
3271               zxmulp(c[2], a[2], d, carry);
3272               zxmulp(c[3], a[3], d, carry);
3273               c[4] = carry;
3274               carry = 0;
3275               d = b[2];
3276               zaddmulp(c[2], a[1], d, carry);
3277               zaddmulp(c[3], a[2], d, carry);
3278               zaddmulp(c[4], a[3], d, carry);
3279               c[5] = carry;
3280               break;
3281            case 3:
3282               carry = 0;
3283               d = b[1];
3284               zxmulp(c[1], a[1], d, carry);
3285               zxmulp(c[2], a[2], d, carry);
3286               zxmulp(c[3], a[3], d, carry);
3287               c[4] = carry;
3288               carry = 0;
3289               d = b[2];
3290               zaddmulp(c[2], a[1], d, carry);
3291               zaddmulp(c[3], a[2], d, carry);
3292               zaddmulp(c[4], a[3], d, carry);
3293               c[5] = carry;
3294               carry = 0;
3295               d = b[3];
3296               zaddmulp(c[3], a[1], d, carry);
3297               zaddmulp(c[4], a[2], d, carry);
3298               zaddmulp(c[5], a[3], d, carry);
3299               c[6] = carry;
3300               break;
3301            }
3302         }
3303
3304         if (c[sc] == 0) sc--;
3305         if (aneg != bneg) sc = -sc;
3306         *c = sc;
3307         if (aneg) *a = -sa;
3308         if (bneg) *b = -sb;
3309
3310         return;
3311         
3312      }
3313
3314
3315#ifdef NTL_GMP_HACK
3316
3317      if (_ntl_gmp_hack && sa >= NTL_GMP_MUL_CROSS && sb >= NTL_GMP_MUL_CROSS) {
3318         long gsa = L_TO_G(sa); 
3319         long gsb = L_TO_G(sb);
3320
3321         mp_limb_t *a_p, *b_p, *c_p, *end_p;
3322
3323         NTL_GSPACE((gsa + gsb) << 1);
3324         a_p = gspace_data;
3325         b_p = a_p + gsa;
3326         c_p = b_p + gsb;
3327         end_p = c_p + (gsa + gsb);
3328
3329         lip_to_gmp(a+1, a_p, sa);
3330         lip_to_gmp(b+1, b_p, sb); 
3331
3332         if (!a_p[gsa-1]) gsa--;
3333         if (!b_p[gsb-1]) gsb--;
3334         end_p[-1] = 0;
3335         end_p[-2] = 0;
3336
3337         if (gsa >= gsb)
3338            mpn_mul(c_p, a_p, gsa, b_p, gsb);
3339         else
3340            mpn_mul(c_p, b_p, gsb, a_p, gsa);
3341
3342         gmp_to_lip(c+1, c_p, sc);
3343
3344         if (!c[sc]) sc--; 
3345         if (aneg != bneg) sc = -sc;
3346         c[0] = sc;
3347         if (aneg) *a = - *a;
3348         if (bneg) *b = - *b;
3349         return;
3350      }
3351
3352
3353
3354#endif
3355
3356      if (*a < KARX || *b < KARX) {
3357         /* classic algorithm */
3358
3359         long i, *pc;
3360
3361         pc = c;
3362         for (i = sc; i; i--) {
3363            pc++;
3364            *pc = 0;
3365         }
3366   
3367         pc = c;
3368   
3369         if (*a >= *b) {
3370            long *pb = b;
3371            for (i = *pb; i; i--) {
3372               pb++;
3373               pc++;
3374               zaddmul(*pb, pc, a);
3375            }
3376         }
3377         else {
3378            long *pa = a;
3379            for (i = *pa; i; i--) {
3380               pa++; 
3381               pc++;
3382               zaddmul(*pa, pc, b);
3383            }
3384         }
3385
3386         while (c[sc] == 0 && sc > 1) sc--;
3387         if (aneg != bneg) sc = -sc;
3388         c[0] = sc;
3389         if (aneg) *a = - *a;
3390         if (bneg) *b = - *b;
3391      }
3392      else {
3393         /* karatsuba */
3394
3395         long n, hn, sp;
3396
3397         if (*a < *b)
3398            n = *b;
3399         else
3400            n = *a;
3401
3402         sp = 0;
3403         do {
3404            hn = (n + 1) >> 1;
3405            sp += (hn << 2) + 7;
3406            n = hn+1;
3407         } while (n >= KARX);
3408
3409         if (sp > max_kmem) {
3410            if (max_kmem == 0) 
3411               kmem = (long *) NTL_MALLOC(sp, sizeof(long), 0);
3412            else
3413               kmem = (long *) NTL_REALLOC(kmem, sp, sizeof(long), 0);
3414
3415            max_kmem = sp;
3416            if (!kmem) zhalt("out of memory in karatsuba");
3417         }
3418
3419         kar_mul(c, a, b, kmem);
3420         if (aneg != bneg) *c = - *c;
3421         if (aneg) *a = - *a;
3422         if (bneg) *b = - *b;
3423      }
3424   }
3425}
3426
3427
3428void _ntl_zsq(_ntl_verylong a, _ntl_verylong *cc)
3429{
3430   static _ntl_verylong mem = 0;
3431   _ntl_verylong c = *cc;
3432   long sa, aneg, sc;
3433
3434   if (!a || (a[0] == 1 && a[1] == 0)) {
3435      _ntl_zzero(cc);
3436      return;
3437   }
3438
3439   if (a == c) {
3440      _ntl_zcopy(a, &mem);
3441      a = mem;
3442   }
3443
3444   sa = *a;
3445
3446   if (*a < 0) {
3447      *a = sa = -sa;
3448      aneg = 1;
3449   }
3450   else
3451      aneg = 0;
3452
3453   sc = (sa) << 1;
3454   if (MustAlloc(c, sc)) {
3455      _ntl_zsetlength(&c, sc);
3456      *cc = c;
3457   }
3458
3459   if (sa <= 3) {
3460      long carry, d;
3461
3462      switch (sa) {
3463      case 1:
3464         carry = 0;
3465         zxmulp(c[1], a[1], a[1], carry);
3466         c[2] = carry;
3467         break;
3468
3469      case 2:
3470         carry = 0;
3471         d = a[1];
3472         zxmulp(c[1], a[1], d, carry);
3473         zxmulp(c[2], a[2], d, carry);
3474         c[3] = carry;
3475         carry = 0;
3476         d = a[2];
3477         zaddmulp(c[2], a[1], d, carry);
3478         zaddmulp(c[3], a[2], d, carry);
3479         c[4] = carry;
3480         break;
3481
3482      case 3:
3483         carry = 0;
3484         d = a[1];
3485         zxmulp(c[1], a[1], d, carry);
3486         zxmulp(c[2], a[2], d, carry);
3487         zxmulp(c[3], a[3], d, carry);
3488         c[4] = carry;
3489         carry = 0;
3490         d = a[2];
3491         zaddmulp(c[2], a[1], d, carry);
3492         zaddmulp(c[3], a[2], d, carry);
3493         zaddmulp(c[4], a[3], d, carry);
3494         c[5] = carry;
3495         carry = 0;
3496         d = a[3];
3497         zaddmulp(c[3], a[1], d, carry);
3498         zaddmulp(c[4], a[2], d, carry);
3499         zaddmulp(c[5], a[3], d, carry);
3500         c[6] = carry;
3501         break;
3502      }
3503
3504      if (c[sc] == 0) sc--;
3505      *c = sc;
3506      if (aneg) *a = -sa;
3507
3508      return;
3509   }
3510
3511#ifdef NTL_GMP_HACK
3512
3513      if (_ntl_gmp_hack && sa >= NTL_GMP_SQR_CROSS) {
3514         long gsa = L_TO_G(sa); 
3515
3516         mp_limb_t *a_p, *c_p, *end_p;;
3517
3518         NTL_GSPACE(gsa + gsa + gsa);
3519         a_p = gspace_data;
3520         c_p = a_p + gsa;
3521         end_p = c_p + (gsa + gsa);
3522
3523         lip_to_gmp(a+1, a_p, sa);
3524
3525         if (!a_p[gsa-1]) gsa--;
3526         end_p[-1] = 0;
3527         end_p[-2] = 0;
3528
3529         mpn_mul(c_p, a_p, gsa, a_p, gsa);
3530
3531         gmp_to_lip(c+1, c_p, sc);
3532
3533         if (!c[sc]) sc--; 
3534         c[0] = sc;
3535         if (aneg) *a = - *a;
3536         return;
3537      }
3538
3539
3540#endif
3541
3542   if (sa < KARSX) {
3543      /* classic algorithm */
3544
3545      long carry, i, j, *pc;
3546
3547      pc = c;
3548      for (i = sc; i; i--) {
3549         pc++;
3550         *pc = 0;
3551      }
3552
3553      carry = 0;
3554      i = 0;
3555      for (j = 1; j <= sa; j++) {
3556         unsigned long uncar;
3557         long t;
3558
3559         i += 2;
3560         uncar = ((unsigned long) carry) + (((unsigned long) c[i-1]) << 1);
3561         t = uncar & NTL_RADIXM;
3562         zaddmulpsq(t, a[j], carry);
3563         c[i-1] = t;
3564         zaddmulsq(sa-j, c+i, a+j);
3565         uncar =  (uncar >> NTL_NBITS) + (((unsigned long) c[i]) << 1);
3566         uncar += ((unsigned long) carry);
3567         carry = uncar >> NTL_NBITS;
3568         c[i] = uncar & NTL_RADIXM;
3569      }
3570
3571
3572      while (c[sc] == 0 && sc > 1) sc--;
3573      c[0] = sc;
3574      if (aneg) *a = - *a;
3575   }
3576   else {
3577      /* karatsuba */
3578
3579      long n, hn, sp;
3580
3581      n = *a;
3582
3583      sp = 0;
3584      do {
3585         hn = (n + 1) >> 1;
3586         sp += hn + hn + hn + 5;
3587         n = hn+1;
3588      } while (n >= KARSX);
3589
3590      if (sp > max_kmem) {
3591         if (max_kmem == 0) 
3592            kmem = (long *) NTL_MALLOC(sp, sizeof(long), 0);
3593         else
3594            kmem = (long *) NTL_REALLOC(kmem, sp, sizeof(long), 0);
3595
3596         max_kmem = sp;
3597         if (!kmem) zhalt("out of memory in karatsuba");
3598      }
3599
3600      kar_sq(c, a, kmem);
3601      if (aneg) *a = - *a;
3602   }
3603}
3604
3605
3606
3607
3608long _ntl_zsdiv(_ntl_verylong a, long d, _ntl_verylong *bb)
3609{
3610   long sa;
3611   _ntl_verylong b = *bb;
3612
3613   if (!d) {
3614      zhalt("division by zero in _ntl_zsdiv");
3615   }
3616
3617   if (!a) {
3618      _ntl_zzero(bb);
3619      return (0);
3620   }
3621
3622
3623   if (d == 2) {
3624      long is_odd = a[1] & 1;
3625      long fix = (a[0] < 0) & is_odd;
3626      _ntl_zrshift(a, 1, bb);
3627      if (fix) _ntl_zsadd(*bb, -1, bb);
3628      return is_odd;
3629   } 
3630
3631
3632   if ((sa = a[0]) < 0)
3633      sa = (-sa);
3634
3635   /* if b aliases a, then b won't move */
3636   _ntl_zsetlength(&b, sa);
3637   *bb = b;
3638
3639   if ((d >= NTL_RADIX) || (d <= -NTL_RADIX)) {
3640      static _ntl_verylong zd = 0;
3641      static _ntl_verylong zb = 0;
3642
3643      _ntl_zintoz(d, &zb);
3644      _ntl_zdiv(a, zb, &b, &zd);
3645      *bb = b;
3646      return (_ntl_ztoint(zd));
3647   }
3648   else {
3649      long den = d;
3650      double deninv;
3651      long carry = 0;
3652      long i;
3653      long flag = (*a < 0 ? 2 : 0) | (den < 0 ? 1 : 0);
3654
3655      if (den < 0)
3656         den = -den;
3657      deninv = 1.0 / ((double) den);
3658
3659      if (a[sa] < den && sa > 1)
3660         carry = a[sa--];
3661
3662      for (i = sa; i; i--) {
3663         zdiv21(carry, a[i], den, deninv, b[i]);
3664      }
3665
3666      while ((sa > 1) && (!(b[sa])))
3667         sa--;
3668      b[0] = sa;
3669
3670      if (flag) {
3671         if (flag <= 2) {
3672            if (!carry)
3673               _ntl_znegate(&b);
3674            else {
3675               _ntl_zsadd(b, 1, &b);
3676               b[0] = -b[0];
3677               if (flag == 1)
3678                  carry = carry - den;
3679               else
3680                  carry = den - carry;
3681               *bb = b;
3682            }
3683         }
3684         else
3685            carry = -carry;
3686      }
3687
3688      return (carry);
3689   }
3690}
3691
3692long _ntl_zsmod(_ntl_verylong a, long d)
3693{
3694   long sa;
3695
3696   if (!a) {
3697      return (0);
3698   }
3699
3700   if (d == 2) return (a[1] & 1);
3701
3702   if (!d) {
3703      zhalt("division by zero in _ntl_zsdiv");
3704   }
3705
3706   if ((sa = a[0]) < 0)
3707      sa = (-sa);
3708
3709   if ((d >= NTL_RADIX) || (d <= -NTL_RADIX)) {
3710      static _ntl_verylong zd = 0;
3711      static _ntl_verylong zb = 0;
3712
3713      _ntl_zintoz(d, &zb);
3714      _ntl_zmod(a, zb, &zd);
3715      return (_ntl_ztoint(zd));
3716   }
3717   else {
3718      long den = d;
3719      double deninv;
3720      long carry = 0;
3721      long i;
3722      long flag = (*a < 0 ? 2 : 0) | (den < 0 ? 1 : 0);
3723
3724      if (den < 0)
3725         den = -den;
3726      deninv = 1.0 / ((double) den);
3727
3728      if (a[sa] < den && sa > 1)
3729         carry = a[sa--];
3730
3731      for (i = sa; i; i--) {
3732         zrem21(carry, a[i], den, deninv);
3733      }
3734
3735      if (flag) {
3736         if (flag <= 2) {
3737            if (carry) {
3738               if (flag == 1)
3739                  carry = carry - den;
3740               else
3741                  carry = den - carry;
3742            }
3743         }
3744         else
3745            carry = -carry;
3746      }
3747
3748      return (carry);
3749   }
3750}
3751
3752void _ntl_zmultirem(_ntl_verylong a, long n, long* dd, long *rr)
3753{
3754   long j;
3755   long sa;
3756
3757   if (!a || (a[0] == 1 && a[1] == 0)) {
3758      for (j = 0; j < n; j++) rr[j] = 0;
3759      return;
3760   }
3761
3762   sa = a[0];
3763
3764   for (j = 0; j < n; j++) {
3765      long den = dd[j];
3766      double deninv;
3767      long carry = 0;
3768      long i;
3769      long lsa = sa;
3770
3771      deninv = 1.0 / ((double) den);
3772
3773      if (a[lsa] < den && lsa > 1)
3774         carry = a[lsa--];
3775
3776      for (i = lsa; i; i--) {
3777         zrem21(carry, a[i], den, deninv);
3778      }
3779
3780      rr[j] = carry;
3781   }
3782}
3783
3784
3785
3786
3787#if (defined(NTL_SINGLE_MUL))
3788
3789#define REDUCE_CROSS 8
3790
3791void _ntl_zmultirem2(_ntl_verylong a, long n, long* dd, double **ttbl, long *rr)
3792
3793{
3794   long d; 
3795   double *tbl;
3796   long ac0, ac1, ac2;
3797   long *ap; 
3798   double *tp;
3799   long sa, i, j, k;
3800   unsigned long pc0, pc1, lo_wd, hi_wd;
3801   long carry;
3802   double xx, yy, dinv;
3803
3804   if (!a ||  a[0] < REDUCE_CROSS || a[0] >= NTL_RADIX) {
3805      _ntl_zmultirem(a, n, dd, rr);
3806      return;
3807   }
3808
3809   sa = a[0];
3810
3811   for (i = 0; i < n; i++) {
3812      d = dd[i];
3813      tbl = ttbl[i];
3814
3815      ac0 = a[1];
3816      ac1 = 0;
3817      ac2 = 0;
3818
3819      ap = &a[2];
3820      tp = &tbl[1];
3821
3822      k = sa-1;
3823      while (k) {
3824         j = k;
3825         if (j > 64) j = 64;
3826         k -= j;
3827
3828         pc0 = 0;
3829         pc1 = 0;
3830
3831         xx =  ((double) (*ap++))* (*tp++) + DENORMALIZE;
3832         for (; j > 1; j--) {
3833            yy =  ((double) (*ap++))*(*tp++) 
3834                  + DENORMALIZE;
3835            NTL_FetchHiLo(hi_wd, lo_wd, xx);
3836            pc0 +=  lo_wd & 0x3FFFFFF;
3837            pc1 += ((hi_wd<<6)|(lo_wd>>26)) & 0x3FFFFFF;
3838            xx = yy;
3839         }
3840         NTL_FetchHiLo(hi_wd, lo_wd, xx);
3841         pc0 +=  lo_wd & 0x3FFFFFF;
3842         pc1 += ((hi_wd<<6)|(lo_wd>>26)) & 0x3FFFFFF;
3843         pc1 += (pc0 >> 26);
3844
3845         ac0 += (pc0 & 0x3FFFFFF);
3846         if (ac0 > NTL_RADIX) {
3847            ac0 -= NTL_RADIX;
3848            carry = 1;
3849         }
3850         else
3851            carry = 0;
3852
3853         ac1 += carry + (pc1 & 0x3FFFFFF);
3854         if (ac1 > NTL_RADIX) {
3855            ac1 -= NTL_RADIX;
3856            carry = 1;
3857         }
3858         else
3859            carry = 0;
3860
3861         ac2 += carry + (pc1 >> 26);
3862      }
3863
3864      carry = 0;
3865      dinv = ((double) 1)/((double) d);
3866      if (ac2 >= d) {
3867         zrem21(carry, ac2, d, dinv);
3868      }
3869      else
3870         carry = ac2;
3871
3872      zrem21(carry, ac1, d, dinv);
3873      zrem21(carry, ac0, d, dinv);
3874
3875      rr[i] = carry;
3876   }
3877}
3878
3879
3880#elif (defined(NTL_TBL_REM))
3881
3882#if (defined(NTL_LONG_LONG))
3883
3884/* This version uses the double-word long type directly.
3885 * It's a little faster that the other one.
3886 * It accumlates 8 double-word products before stepping
3887 * a higher-level accumulator.
3888 */
3889
3890
3891
3892void _ntl_zmultirem3(_ntl_verylong a, long n, long* dd, long **ttbl, long *rr)
3893{
3894   long sa, i, j, d, *tbl, ac0, ac1, ac2, *ap, *tp, k, carry;
3895   double dinv;
3896   NTL_LL_TYPE acc;
3897
3898   if (!a || a[0] < 8 || a[0] >= NTL_RADIX) {
3899      _ntl_zmultirem(a, n, dd, rr);
3900      return;
3901   }
3902
3903   sa = a[0];
3904 
3905   for (i = 0; i < n; i++) {
3906      d = dd[i];
3907      tbl = ttbl[i];
3908      acc = a[1];
3909      ac2 = 0;
3910      ap = &a[2];
3911      tp = &tbl[1];
3912
3913      k = sa - 7;
3914
3915      for (j = 0; j < k; j += 7) {
3916         acc += ((NTL_LL_TYPE) ap[j+0]) * ((NTL_LL_TYPE) tp[j+0]);
3917         acc += ((NTL_LL_TYPE) ap[j+1]) * ((NTL_LL_TYPE) tp[j+1]);
3918         acc += ((NTL_LL_TYPE) ap[j+2]) * ((NTL_LL_TYPE) tp[j+2]);
3919         acc += ((NTL_LL_TYPE) ap[j+3]) * ((NTL_LL_TYPE) tp[j+3]);
3920         acc += ((NTL_LL_TYPE) ap[j+4]) * ((NTL_LL_TYPE) tp[j+4]);
3921         acc += ((NTL_LL_TYPE) ap[j+5]) * ((NTL_LL_TYPE) tp[j+5]);
3922         acc += ((NTL_LL_TYPE) ap[j+6]) * ((NTL_LL_TYPE) tp[j+6]);
3923         ac2 += (long) (acc >> (2*NTL_NBITS));
3924         acc &= (((NTL_LL_TYPE) 1) << (2*NTL_NBITS)) - ((NTL_LL_TYPE) 1);
3925      }
3926
3927      k = sa - 1;
3928
3929      for (; j < k; j++)
3930         acc += ((NTL_LL_TYPE) ap[j+0]) * ((NTL_LL_TYPE) tp[j+0]);
3931
3932      ac2 += (long) (acc >> (2*NTL_NBITS));
3933      acc &= (((NTL_LL_TYPE) 1) << (2*NTL_NBITS)) - ((NTL_LL_TYPE) 1);
3934
3935      ac0 = (long) (acc & ( (((NTL_LL_TYPE) 1) << (NTL_NBITS)) - ((NTL_LL_TYPE) 1) ));
3936      ac1 = (long) (acc >> NTL_NBITS);
3937     
3938
3939      carry = 0;
3940      dinv = ((double) 1)/((double) d);
3941      if (ac2 >= d) {
3942         zrem21(carry, ac2, d, dinv);
3943      }
3944      else
3945         carry = ac2;
3946
3947      zrem21(carry, ac1, d, dinv);
3948      zrem21(carry, ac0, d, dinv);
3949
3950      rr[i] = carry;
3951   }
3952}
3953
3954#else
3955
3956void _ntl_zmultirem3(_ntl_verylong a, long n, long* dd, long **ttbl, long *rr)
3957{
3958   long sa, i, d, *tbl, ac0, ac1, ac2, *ap, *tp, k, t, carry;
3959   double dinv;
3960
3961   if (!a || a[0] < 8 || a[0] >= NTL_RADIX) {
3962      _ntl_zmultirem(a, n, dd, rr);
3963      return;
3964   }
3965
3966   sa = a[0];
3967 
3968   for (i = 0; i < n; i++) {
3969      d = dd[i];
3970      tbl = ttbl[i];
3971      ac0 = a[1];
3972      ac1 = 0;
3973      ac2 = 0;
3974      ap = &a[2];
3975      tp = &tbl[1];
3976      k = sa-1;
3977     
3978      while (k) {
3979         zxmulp(t, *ap, *tp, ac0);
3980         ac1 += ac0;
3981         ac2 += ac1 >> NTL_NBITS;
3982         ac1 &= NTL_RADIXM;
3983         ac0 = t;
3984         k--;
3985         ap++;
3986         tp++;
3987      }
3988
3989      carry = 0;
3990      dinv = ((double) 1)/((double) d);
3991      if (ac2 >= d) {
3992         zrem21(carry, ac2, d, dinv);
3993      }
3994      else
3995         carry = ac2;
3996
3997      zrem21(carry, ac1, d, dinv);
3998      zrem21(carry, ac0, d, dinv);
3999
4000      rr[i] = carry;
4001   }
4002}
4003
4004
4005
4006
4007#endif
4008
4009
4010
4011#endif
4012
4013
4014
4015
4016long _ntl_zsfastrem(_ntl_verylong a, long d)
4017/* assumes a >= 0, and 0 < d < NTL_RADIX */
4018/* computes a % d */
4019
4020{
4021   long sa;
4022
4023   if (!a || (a[0] == 1 && a[1] == 0)) {
4024      return 0;
4025   }
4026
4027   sa = a[0];
4028
4029   {
4030      long den = d;
4031      double deninv = ((double)1)/((double)den);
4032      long carry = 0;
4033      long i;
4034      long lsa = sa;
4035
4036      if (a[lsa] < den && lsa > 1)
4037         carry = a[lsa--];
4038      for (i = lsa; i; i--) {
4039         zrem21(carry, a[i], den, deninv);
4040      }
4041      return carry;
4042   }
4043}
4044
4045
4046
4047void _ntl_zdiv(_ntl_verylong a, _ntl_verylong b, _ntl_verylong *qq, _ntl_verylong *rr)
4048{
4049   long sa, sb, sq, i;
4050   long sign;
4051   long q1;
4052   long *rp;
4053   double btopinv, aux;
4054   static _ntl_verylong q=0, r=0;
4055
4056   if (!b || (((sb=b[0]) == 1) && (!b[1]))) {
4057      zhalt("division by zero in _ntl_zdiv");
4058   }
4059
4060   if (!a || (((sa=a[0]) == 1) && (!a[1]))) {
4061      _ntl_zzero(qq);
4062      if (rr) _ntl_zzero(rr);
4063      return;
4064   }
4065
4066
4067   if (sb == 1) {
4068      long t1 = _ntl_zsdiv(a, b[1], qq);
4069      if (rr) _ntl_zintoz(t1, rr);
4070      return;
4071   }
4072
4073   if (sb == -1) {
4074      long t1 = _ntl_zsdiv(a, -b[1], qq);
4075      if (rr) _ntl_zintoz(t1, rr);
4076      return;
4077   }
4078
4079   sign = 0;
4080   if (sa < 0) {
4081      a[0] = sa = -sa;
4082      sign = 2;
4083   }
4084
4085   if (sb < 0) {
4086      b[0] = sb = -sb;
4087      sign |= 1;
4088   }
4089
4090
4091   sq = sa-sb+1;
4092
4093   if (sq <= 0) {
4094      _ntl_zcopy(a, &r);
4095      _ntl_zzero(&q);
4096      goto done;
4097   }
4098
4099#ifdef NTL_GMP_HACK
4100   if (_ntl_gmp_hack && sb >= NTL_GMP_DIV_CROSS && sq >= NTL_GMP_DIV_CROSS) {
4101      GT_INIT
4102
4103      lip_to_mpz(a, gt_1);
4104      lip_to_mpz(b, gt_2);
4105      mpz_fdiv_qr(gt_3, gt_4, gt_1, gt_2);
4106      mpz_to_lip(&q, gt_3);
4107      mpz_to_lip(&r, gt_4);
4108
4109      goto done;
4110   }
4111#endif
4112
4113   _ntl_zsetlength(&q, sq);
4114   _ntl_zsetlength(&r, sa+1);
4115 
4116   _ntl_zcopy(a, &r);
4117   rp = &r[sa+1];
4118   *rp = 0;
4119
4120   r[0] = 0; /* this streamlines the last evaluation of aux */
4121
4122   btopinv = b[sb]*NTL_FRADIX + b[sb-1];
4123   if (sb > 2) 
4124      btopinv = NTL_FRADIX / (btopinv*NTL_FRADIX + b[sb-2]);
4125   else
4126      btopinv = 1.0 / btopinv;
4127
4128   
4129   aux = btopinv*(rp[-1]*NTL_FRADIX + rp[-2]);
4130   if (aux >= NTL_FRADIX)
4131      aux = NTL_FRADIX-1;
4132
4133   for (i = sq; i >= 1; i--, rp--) {
4134      q1 = (long) aux;
4135      if (q1) {
4136         zsubmul(q1, &r[i], b);
4137      }
4138
4139      while (rp[0] < 0) {
4140         zaddmulone(&r[i], b);
4141         q1--;
4142      }
4143
4144      while (rp[0] > 0) {
4145         zsubmulone(&r[i], b);
4146         q1++;
4147      }
4148
4149      aux = btopinv*((rp[-1]*NTL_FRADIX + rp[-2])*NTL_FRADIX + rp[-3]);
4150      while (aux > NTL_FRADIX - 16) {
4151         /* q1 might be too small */
4152         if (aux >= NTL_FRADIX)
4153            aux = NTL_FRADIX-1;
4154
4155
4156         zsubmulone(&r[i], b);
4157         if (rp[0] < 0) {
4158            /* oops...false alarm! */
4159            zaddmulone(&r[i], b);
4160            break;
4161         }
4162         else {
4163            q1++;
4164            aux = btopinv*((rp[-1]*NTL_FRADIX + rp[-2])*NTL_FRADIX + rp[-3]);
4165         }
4166      }
4167
4168      q[i] = q1;
4169   }
4170
4171   while (sq > 1 && q[sq] == 0) sq--;
4172   q[0] = sq;
4173
4174   i = sb;
4175   while (i > 1 && r[i] == 0) i--;
4176   r[0] = i;
4177
4178done:
4179   if (sign)
4180   {
4181      if (sign <= 2)
4182      {
4183         if (!(r[1]) && (r[0] == 1))
4184            _ntl_znegate(&q);
4185         else
4186         {
4187            _ntl_zsadd(q, 1, &q);
4188            _ntl_znegate(&q);
4189            if (sign == 1)
4190               _ntl_zsub(r, b, &r);
4191            else
4192               _ntl_zsub(b, r, &r);
4193         }
4194      }
4195      else
4196         _ntl_znegate(&r);
4197
4198      if (sign & 2)
4199         a[0] = -sa;
4200
4201      if (sign & 1)
4202         b[0] = -sb;
4203   }
4204
4205   _ntl_zcopy(q, qq);
4206   if (rr) _ntl_zcopy(r, rr);
4207}
4208
4209void
4210_ntl_zmod(_ntl_verylong a, _ntl_verylong b, _ntl_verylong *rr)
4211{
4212   long sa, sb, sq, i;
4213   long sign;
4214   long q1;
4215   long *rp;
4216   double btopinv, aux;
4217   static _ntl_verylong r=0;
4218
4219   if (!b || (((sb=b[0]) == 1) && (!b[1]))) {
4220      zhalt("division by zero in _ntl_zdiv");
4221   }
4222
4223   if (!a || (((sa=a[0]) == 1) && (!a[1]))) {
4224      _ntl_zzero(rr);
4225      return;
4226   }
4227
4228
4229   if (sb == 1) {
4230      _ntl_zintoz(_ntl_zsmod(a, b[1]), rr);
4231      return;
4232   }
4233
4234   if (sb == -1) {
4235      _ntl_zintoz(_ntl_zsmod(a, -b[1]), rr);
4236      return;
4237   }
4238
4239   sign = 0;
4240   if (sa < 0) {
4241      a[0] = sa = -sa;
4242      sign = 2;
4243   }
4244
4245   if (sb < 0) {
4246      b[0] = sb = -sb;
4247      sign |= 1;
4248   }
4249
4250
4251   sq = sa-sb+1;
4252
4253   if (sq <= 0) {
4254      _ntl_zcopy(a, &r);
4255      goto done;
4256   }
4257
4258#ifdef NTL_GMP_HACK
4259   if (_ntl_gmp_hack && sb >= NTL_GMP_REM_CROSS && sq >= NTL_GMP_REM_CROSS) {
4260      GT_INIT
4261
4262      lip_to_mpz(a, gt_1);
4263      lip_to_mpz(b, gt_2);
4264      mpz_fdiv_r(gt_4, gt_1, gt_2);
4265      mpz_to_lip(&r, gt_4);
4266
4267      goto done;
4268   }
4269#endif
4270
4271   _ntl_zsetlength(&r, sa+1);
4272 
4273   _ntl_zcopy(a, &r);
4274   rp = &r[sa+1];
4275   *rp = 0;
4276
4277   r[0] = 0; /* this streamlines the last evaluation of aux */
4278
4279   btopinv = b[sb]*NTL_FRADIX + b[sb-1];
4280   if (sb > 2) 
4281      btopinv = NTL_FRADIX / (btopinv*NTL_FRADIX + b[sb-2]);
4282   else
4283      btopinv = 1.0 / btopinv;
4284
4285   
4286   aux = btopinv*(rp[-1]*NTL_FRADIX + rp[-2]);
4287   if (aux >= NTL_FRADIX)
4288      aux = NTL_FRADIX-1;
4289
4290   for (i = sq; i >= 1; i--, rp--) {
4291      q1 = (long) aux;
4292      if (q1) {
4293         zsubmul(q1, &r[i], b);
4294      }
4295
4296      while (rp[0] < 0) {
4297         zaddmulone(&r[i], b);
4298      }
4299
4300      while (rp[0] > 0) {
4301         zsubmulone(&r[i], b);
4302      }
4303
4304      aux = btopinv*((rp[-1]*NTL_FRADIX + rp[-2])*NTL_FRADIX + rp[-3]);
4305      while (aux > NTL_FRADIX - 16) {
4306         /* q1 might be too small */
4307         if (aux >= NTL_FRADIX)
4308            aux = NTL_FRADIX-1;
4309
4310
4311         zsubmulone(&r[i], b);
4312         if (rp[0] < 0) {
4313            /* oops...false alarm! */
4314            zaddmulone(&r[i], b);
4315            break;
4316         }
4317         else {
4318            aux = btopinv*((rp[-1]*NTL_FRADIX + rp[-2])*NTL_FRADIX + rp[-3]);
4319         }
4320      }
4321   }
4322
4323   i = sb;
4324   while (i > 1 && r[i] == 0) i--;
4325   r[0] = i;
4326
4327done:
4328   if (sign)
4329   {
4330      if (sign <= 2)
4331      {
4332         if (!(r[1]) && (r[0] == 1))
4333            /* no op */;
4334         else
4335         {
4336            if (sign == 1)
4337               _ntl_zsub(r, b, &r);
4338            else
4339               _ntl_zsub(b, r, &r);
4340         }
4341      }
4342      else
4343         _ntl_znegate(&r);
4344
4345      if (sign & 2)
4346         a[0] = -sa;
4347
4348      if (sign & 1)
4349         b[0] = -sb;
4350   }
4351
4352   _ntl_zcopy(r, rr);
4353}
4354
4355void
4356_ntl_zquickmod(_ntl_verylong *rr, _ntl_verylong b)
4357{
4358   long sa, sb, sq, i;
4359   long q1;
4360   long *rp;
4361   double btopinv, aux;
4362   _ntl_verylong r;
4363
4364   sb = b[0];
4365
4366   r = *rr;
4367
4368   if (!r || (((sa=r[0]) == 1) && (!r[1]))) {
4369      _ntl_zzero(rr);
4370      return;
4371   }
4372
4373
4374   if (sb == 1) {
4375      _ntl_zintoz(_ntl_zsmod(r, b[1]), rr);
4376      return;
4377   }
4378
4379   sq = sa-sb+1;
4380
4381   if (sq <= 0) {
4382      return;
4383   } 
4384
4385#ifdef NTL_GMP_HACK
4386   if (_ntl_gmp_hack && sb >= NTL_GMP_QREM_CROSS && sq >= NTL_GMP_QREM_CROSS) {
4387      GT_INIT
4388
4389      lip_to_mpz(r, gt_1);
4390      lip_to_mpz(b, gt_2);
4391      mpz_fdiv_r(gt_4, gt_1, gt_2);
4392      mpz_to_lip(rr, gt_4);
4393      return;
4394   }
4395#endif
4396
4397   _ntl_zsetlength(rr, sa+1);
4398   r = *rr;
4399 
4400   rp = &r[sa+1];
4401   *rp = 0;
4402
4403   r[0] = 0; /* this streamlines the last evaluation of aux */
4404
4405   btopinv = b[sb]*NTL_FRADIX + b[sb-1];
4406   if (sb > 2) 
4407      btopinv = NTL_FRADIX / (btopinv*NTL_FRADIX + b[sb-2]);
4408   else
4409      btopinv = 1.0 / btopinv;
4410
4411   
4412   aux = btopinv*(rp[-1]*NTL_FRADIX + rp[-2]);
4413   if (aux >= NTL_FRADIX)
4414      aux = NTL_FRADIX-1;
4415
4416   for (i = sq; i >= 1; i--, rp--) {
4417      q1 = (long) aux;
4418      if (q1) {
4419         zsubmul(q1, &r[i], b);
4420      }
4421
4422      while (rp[0] < 0) {
4423         zaddmulone(&r[i], b);
4424      }
4425
4426      while (rp[0] > 0) {
4427         zsubmulone(&r[i], b);
4428      }
4429
4430      aux = btopinv*((rp[-1]*NTL_FRADIX + rp[-2])*NTL_FRADIX + rp[-3]);
4431      while (aux > NTL_FRADIX - 16) {
4432         /* q1 might be too small */
4433         if (aux >= NTL_FRADIX)
4434            aux = NTL_FRADIX-1;
4435
4436
4437         zsubmulone(&r[i], b);
4438         if (rp[0] < 0) {
4439            /* oops...false alarm! */
4440            zaddmulone(&r[i], b);
4441            break;
4442         }
4443         else {
4444            aux = btopinv*((rp[-1]*NTL_FRADIX + rp[-2])*NTL_FRADIX + rp[-3]);
4445         }
4446      }
4447   }
4448
4449   i = sb;
4450   while (i > 1 && r[i] == 0) i--;
4451   r[0] = i;
4452}
4453
4454
4455void
4456_ntl_zaddmod(
4457        _ntl_verylong a,
4458        _ntl_verylong b,
4459        _ntl_verylong n,
4460        _ntl_verylong *c
4461        )
4462{
4463        if (*c != n) {
4464                _ntl_zadd(a, b, c);
4465                if (_ntl_zcompare(*c, n) >= 0)
4466                        _ntl_zsubpos(*c, n, c);
4467        }
4468        else {
4469                static _ntl_verylong mem = 0;
4470
4471                _ntl_zadd(a, b, &mem);
4472                if (_ntl_zcompare(mem, n) >= 0)
4473                        _ntl_zsubpos(mem, n, c);
4474                else
4475                        _ntl_zcopy(mem, c);
4476        }
4477}
4478
4479void
4480_ntl_zsubmod(
4481        _ntl_verylong a,
4482        _ntl_verylong b,
4483        _ntl_verylong n,
4484        _ntl_verylong *c
4485        )
4486{
4487        static _ntl_verylong mem = 0;
4488        long cmp;
4489
4490        if ((cmp=_ntl_zcompare(a, b)) < 0) {
4491                _ntl_zadd(n, a, &mem);
4492                _ntl_zsubpos(mem, b, c);
4493        } else if (!cmp) 
4494                _ntl_zzero(c);
4495        else 
4496                _ntl_zsubpos(a, b, c);
4497}
4498
4499void
4500_ntl_zsmulmod(
4501        _ntl_verylong a,
4502        long d,
4503        _ntl_verylong n,
4504        _ntl_verylong *c
4505        )
4506{
4507        static _ntl_verylong mem = 0;
4508
4509        _ntl_zsmul(a, d, &mem);
4510        _ntl_zquickmod(&mem, n);
4511        _ntl_zcopy(mem, c);
4512}
4513
4514
4515
4516
4517void
4518_ntl_zmulmod(
4519        _ntl_verylong a,
4520        _ntl_verylong b,
4521        _ntl_verylong n,
4522        _ntl_verylong *c
4523        )
4524{
4525        static _ntl_verylong mem = 0;
4526
4527        _ntl_zmul(a, b, &mem);
4528        _ntl_zquickmod(&mem, n);
4529        _ntl_zcopy(mem, c);
4530}
4531
4532void
4533_ntl_zsqmod(
4534        _ntl_verylong a,
4535        _ntl_verylong n,
4536        _ntl_verylong *c
4537        )
4538{
4539        static _ntl_verylong mem = 0;
4540
4541        _ntl_zsq(a, &mem);
4542        _ntl_zquickmod(&mem, n);
4543        _ntl_zcopy(mem, c);
4544}
4545
4546
4547void
4548_ntl_zinvmod(
4549        _ntl_verylong a,
4550        _ntl_verylong n,
4551        _ntl_verylong *c
4552        )
4553{
4554        if (_ntl_zinv(a, n, c))
4555                zhalt("undefined inverse in _ntl_zinvmod");
4556}
4557
4558
4559static long 
4560zxxeucl(
4561   _ntl_verylong ain,
4562   _ntl_verylong nin,
4563   _ntl_verylong *invv,
4564   _ntl_verylong *uu
4565   )
4566{
4567   static _ntl_verylong a = 0;
4568   static _ntl_verylong n = 0;
4569   static _ntl_verylong q = 0;
4570   static _ntl_verylong w = 0;
4571   static _ntl_verylong x = 0;
4572   static _ntl_verylong y = 0;
4573   static _ntl_verylong z = 0;
4574   _ntl_verylong inv = *invv;
4575   _ntl_verylong u = *uu;
4576   long diff;
4577   long ilo;
4578   long sa;
4579   long sn;
4580   long temp;
4581   long e;
4582   long fast;
4583   long parity;
4584   long gotthem;
4585   _ntl_verylong pin;
4586   _ntl_verylong p;
4587   long i;
4588   long try11;
4589   long try12;
4590   long try21;
4591   long try22;
4592   long got11;
4593   long got12;
4594   long got21;
4595   long got22;
4596   double hi;
4597   double lo;
4598   double dt;
4599   double fhi, fhi1;
4600   double flo, flo1;
4601   double num;
4602   double den;
4603   double dirt;
4604
4605
4606   _ntl_zsetlength(&a, (e = (ain[0] > nin[0] ? ain[0] : nin[0])));
4607   _ntl_zsetlength(&n, e);
4608   _ntl_zsetlength(&q, e);
4609   _ntl_zsetlength(&w, e);
4610   _ntl_zsetlength(&x, e);
4611   _ntl_zsetlength(&y, e);
4612   _ntl_zsetlength(&z, e);
4613   _ntl_zsetlength(&inv, e);
4614   *invv = inv;
4615   _ntl_zsetlength(&u, e);
4616   *uu = u;
4617
4618   fhi1 = 1.0 + ((double) 32.0)/NTL_FDOUBLE_PRECISION;
4619   flo1 = 1.0 - ((double) 32.0)/NTL_FDOUBLE_PRECISION;
4620
4621   fhi = 1.0 + ((double) 8.0)/NTL_FDOUBLE_PRECISION;
4622   flo = 1.0 - ((double) 8.0)/NTL_FDOUBLE_PRECISION;
4623
4624   pin = &ain[0];
4625   p = &a[0];
4626   for (i = (*pin); i >= 0; i--)
4627      *p++ = *pin++;
4628   pin = &nin[0];
4629   p = &n[0];
4630   for (i = (*pin); i >= 0; i--)
4631      *p++ = *pin++;
4632   inv[0] = 1;
4633   inv[1] = 1;
4634   w[0] = 1;
4635   w[1] = 0;
4636   while (n[0] > 1 || n[1] > 0)
4637   {
4638      gotthem = 0;
4639      sa = a[0];
4640      sn = n[0];
4641      diff = sa - sn;
4642      if (!diff || diff == 1)
4643      {
4644         sa = a[0];
4645         p = &a[sa];
4646         num = ((double) (*p)) * NTL_FRADIX;
4647         if (sa > 1)
4648            num += (*(--p));
4649         num *= NTL_FRADIX;
4650         if (sa > 2)
4651            num += (*(p - 1));
4652         sn = n[0];
4653         p = &n[sn];
4654         den = (double) (*p) * NTL_FRADIX;
4655         if (sn > 1)
4656            den += (*(--p));
4657         den *= NTL_FRADIX;
4658         if (sn > 2)
4659            den += (*(p - 1));
4660         hi = fhi1 * (num + 1.0) / den;
4661         lo = flo1 * num / (den + 1.0);
4662         if (diff > 0)
4663         {
4664            hi *= NTL_FRADIX;
4665            lo *= NTL_FRADIX;
4666         }
4667         try11 = 1;
4668         try12 = 0;
4669         try21 = 0;
4670         try22 = 1;
4671         parity = 1;
4672         fast = 1; 
4673         while (fast > 0)
4674         {
4675            parity = 1 - parity;
4676            if (hi >= NTL_FRADIX)
4677               fast = 0;
4678            else
4679            {
4680               ilo = (long)lo;
4681               dirt = hi - ilo;
4682               if (dirt < 1.0/NTL_FDOUBLE_PRECISION || !ilo || ilo < (long)hi)
4683                  fast = 0;
4684               else
4685               {
4686                  dt = lo-ilo;
4687                  lo = flo / dirt;
4688                  if (dt > 1.0/NTL_FDOUBLE_PRECISION)
4689                     hi = fhi / dt;
4690                  else
4691                     hi = NTL_FRADIX;
4692                  temp = try11;
4693                  try11 = try21;
4694                  if ((NTL_RADIX - temp) / ilo < try21)
4695                     fast = 0;
4696                  else
4697                     try21 = temp + ilo * try21;
4698                  temp = try12;
4699                  try12 = try22;
4700                  if ((NTL_RADIX - temp) / ilo < try22)
4701                     fast = 0;
4702                  else
4703                     try22 = temp + ilo * try22;
4704                  if ((fast > 0) && (parity > 0))
4705                  {
4706                     gotthem = 1;
4707                     got11 = try11;
4708                     got12 = try12;
4709                     got21 = try21;
4710                     got22 = try22;
4711                  }
4712               }
4713            }
4714         }
4715      }
4716      if (gotthem)
4717      {
4718         _ntl_zsmul(inv, got11, &x);
4719         _ntl_zsmul(w, got12, &y);
4720         _ntl_zsmul(inv, got21, &z);
4721         _ntl_zsmul(w, got22, &w);
4722         _ntl_zadd(x, y, &inv);
4723         _ntl_zadd(z, w, &w);
4724         _ntl_zsmul(a, got11, &x);
4725         _ntl_zsmul(n, got12, &y);
4726         _ntl_zsmul(a, got21, &z);
4727         _ntl_zsmul(n, got22, &n);
4728         _ntl_zsub(x, y, &a);
4729         _ntl_zsub(n, z, &n);
4730      }
4731      else
4732      {
4733         _ntl_zdiv(a, n, &q, &a);
4734         _ntl_zmul(q, w, &x);
4735         _ntl_zadd(inv, x, &inv);
4736         if (a[0] > 1 || a[1] > 0)
4737         {
4738            _ntl_zdiv(n, a, &q, &n);
4739            _ntl_zmul(q, inv, &x);
4740            _ntl_zadd(w, x, &w);
4741         }
4742         else
4743         {
4744            p = &a[0];
4745            pin = &n[0];
4746            for (i = (*pin); i >= 0; i--)
4747               *p++ = *pin++;
4748            n[0] = 1;
4749            n[1] = 0;
4750            _ntl_zcopy(w, &inv);
4751            _ntl_znegate(&inv);
4752         }
4753      }
4754   }
4755
4756   if ((a[0] == 1) && (a[1] == 1))
4757      e = 0;
4758   else 
4759      e = 1;
4760
4761   p = &u[0];
4762   pin = &a[0];
4763   for (i = (*pin); i >= 0; i--)
4764      *p++ = *pin++;
4765   *invv = inv;
4766   *uu = u;
4767
4768   return (e);
4769}
4770
4771long 
4772_ntl_zinv(
4773        _ntl_verylong ain,
4774        _ntl_verylong nin,
4775        _ntl_verylong *invv
4776        )
4777{
4778        static _ntl_verylong u = 0;
4779        static _ntl_verylong v = 0;
4780        long sgn;
4781
4782
4783        if (_ntl_zscompare(nin, 1) <= 0) {
4784                zhalt("InvMod: second input <= 1");
4785        }
4786
4787        sgn = _ntl_zsign(ain);
4788        if (sgn < 0) {
4789                zhalt("InvMod: first input negative");
4790        }
4791
4792        if (_ntl_zcompare(ain, nin) >= 0) {
4793                zhalt("InvMod: first input too big");
4794        }
4795
4796
4797        if (sgn == 0) {
4798                _ntl_zcopy(nin, invv);
4799                return 1;
4800        }
4801
4802#ifdef NTL_GMP_HACK
4803#if (__GNU_MP_VERSION >= 3)
4804/* versions of gmp prior to version 3 have really bad xgcd */
4805        if (_ntl_gmp_hack && nin[0] >= NTL_GMP_INVMOD_CROSS) {
4806                GT_INIT
4807
4808                lip_to_mpz(ain, gt_1);
4809                lip_to_mpz(nin, gt_2);
4810                mpz_gcdext(gt_3, gt_4, 0, gt_1, gt_2);
4811                mpz_to_lip(&u, gt_3);
4812                mpz_to_lip(&v, gt_4);
4813
4814                if (u && u[0] == 1 && u[1] == 1) {
4815
4816                        /*
4817                         * We make sure v is in range 0..n-1,
4818                         * just in case GMP is sloppy.
4819                         */
4820
4821                        _ntl_zmod(v, nin, &v);
4822                        _ntl_zcopy(v, invv);
4823                        return 0;
4824                }
4825                else {
4826                        _ntl_zcopy(u, invv);
4827                        return 1;
4828                }
4829        }
4830#endif
4831#endif
4832
4833        if (!(zxxeucl(ain, nin, &v, &u))) {
4834                if (_ntl_zsign(v) < 0) _ntl_zadd(v, nin, &v);
4835                _ntl_zcopy(v, invv);
4836                return 0;
4837        }
4838
4839        _ntl_zcopy(u, invv);
4840        return 1;
4841}
4842
4843void
4844_ntl_zexteucl(
4845        _ntl_verylong aa,
4846        _ntl_verylong *xa,
4847        _ntl_verylong bb,
4848        _ntl_verylong *xb,
4849        _ntl_verylong *d
4850        )
4851{
4852        static _ntl_verylong modcon = 0;
4853        static _ntl_verylong a=0, b=0;
4854        long anegative = 0;
4855        long bnegative = 0;
4856
4857        _ntl_zcopy(aa, &a);
4858        _ntl_zcopy(bb, &b);
4859
4860        if (anegative = (a[0] < 0))
4861                a[0] = -a[0];
4862        if (bnegative = (b[0] < 0))
4863                b[0] = -b[0];
4864
4865        if (!b[1] && (b[0] == 1))
4866        {
4867                _ntl_zone(xa);
4868                _ntl_zzero(xb);
4869                _ntl_zcopy(a, d);
4870                goto done;
4871        }
4872
4873        if (!a[1] && (a[0] == 1))
4874        {
4875                _ntl_zzero(xa);
4876                _ntl_zone(xb);
4877                _ntl_zcopy(b, d);
4878                goto done;
4879        }
4880
4881#ifdef NTL_GMP_HACK
4882#if (__GNU_MP_VERSION >= 3)
4883/* versions of gmp prior to version 3 have really bad xgcd */
4884   if (_ntl_gmp_hack && 
4885       a[0] >= NTL_GMP_XGCD_CROSS && b[0] >= NTL_GMP_XGCD_CROSS) {
4886
4887      static _ntl_verylong xa1 = 0, xb1 = 0, d1 = 0, b_red = 0;
4888      static _ntl_verylong tmp1 = 0, tmp2 = 0, tmp3 = 0;
4889
4890      GT_INIT
4891
4892     
4893
4894      lip_to_mpz(aa, gt_1);
4895      lip_to_mpz(bb, gt_2);
4896      mpz_gcdext(gt_3, gt_4, gt_5, gt_1, gt_2);
4897      mpz_to_lip(&d1, gt_3);
4898      mpz_to_lip(&xa1, gt_4);
4899      mpz_to_lip(&xb1, gt_5);
4900
4901      /* normalize...this ensures results agree with
4902         classical Euclid...not very efficient... */
4903
4904      if (_ntl_zcompare(a, b) >= 0) {
4905         _ntl_zdiv(a, d1, &a, 0);
4906         _ntl_zdiv(b, d1, &b, 0);
4907         _ntl_zdiv(xa1, b, &tmp1, &xa1);
4908         _ntl_zlshift(xa1, 1, &tmp2);
4909         if (anegative) _ntl_zsadd(tmp2, 1, &tmp2);
4910         if (_ntl_zcompare(tmp2, b) > 0) {
4911            _ntl_zsub(xa1, b, &xa1);
4912            _ntl_zsadd(tmp1, 1, &tmp1);
4913         }
4914         _ntl_zmul(tmp1, a, &tmp2);
4915         if (anegative != bnegative) 
4916            _ntl_zsub(xb1, tmp2, &xb1);
4917         else
4918            _ntl_zadd(xb1, tmp2, &xb1);
4919      }
4920      else {
4921         _ntl_zdiv(a, d1, &a, 0);
4922         _ntl_zdiv(b, d1, &b, 0);
4923         _ntl_zdiv(xb1, a, &tmp1, &xb1);
4924         _ntl_zlshift(xb1, 1, &tmp2);
4925         if (bnegative) _ntl_zsadd(tmp2, 1, &tmp2);
4926         if (_ntl_zcompare(tmp2, a) > 0) {
4927            _ntl_zsub(xb1, a, &xb1);
4928            _ntl_zsadd(tmp1, 1, &tmp1);
4929         }
4930         _ntl_zmul(tmp1, b, &tmp2);
4931         if (anegative != bnegative) 
4932            _ntl_zsub(xa1, tmp2, &xa1);
4933         else
4934            _ntl_zadd(xa1, tmp2, &xa1);
4935      }
4936
4937
4938      /* end normalize */
4939
4940      _ntl_zcopy(d1, d);
4941      _ntl_zcopy(xa1, xa);
4942      _ntl_zcopy(xb1, xb);
4943      return;
4944   }
4945#endif
4946#endif
4947
4948
4949        zxxeucl(a, b, xa, d);
4950        _ntl_zmul(a, *xa, xb);
4951        _ntl_zsub(*d, *xb, xb);
4952        _ntl_zdiv(*xb, b, xb, &modcon);
4953
4954        if ((modcon[1]) || (modcon[0] != 1))
4955        {
4956                zhalt("non-zero remainder in _ntl_zexteucl   BUG");
4957        }
4958done:
4959        if (anegative)
4960        {
4961                _ntl_znegate(xa);
4962        }
4963        if (bnegative)
4964        {
4965                _ntl_znegate(xb);
4966        }
4967}
4968
4969
4970
4971/* I've adapted LIP's extended euclidean algorithm to
4972 * do rational reconstruction.  -- VJS.
4973 */
4974
4975
4976long 
4977_ntl_zxxratrecon(
4978   _ntl_verylong ain,
4979   _ntl_verylong nin,
4980   _ntl_verylong num_bound,
4981   _ntl_verylong den_bound,
4982   _ntl_verylong *num_out,
4983   _ntl_verylong *den_out
4984   )
4985{
4986   static _ntl_verylong a = 0;
4987   static _ntl_verylong n = 0;
4988   static _ntl_verylong q = 0;
4989   static _ntl_verylong w = 0;
4990   static _ntl_verylong x = 0;
4991   static _ntl_verylong y = 0;
4992   static _ntl_verylong z = 0;
4993   static _ntl_verylong inv = 0;
4994   static _ntl_verylong u = 0;
4995   static _ntl_verylong a_bak = 0;
4996   static _ntl_verylong n_bak = 0;
4997   static _ntl_verylong inv_bak = 0;
4998   static _ntl_verylong w_bak = 0;
4999
5000   _ntl_verylong p;
5001
5002   long diff;
5003   long ilo;
5004   long sa;
5005   long sn;
5006   long snum;
5007   long sden;
5008   long e;
5009   long fast;
5010   long temp;
5011   long parity;
5012   long gotthem;
5013   long try11;
5014   long try12;
5015   long try21;
5016   long try22;
5017   long got11;
5018   long got12;
5019   long got21;
5020   long got22;
5021
5022   double hi;
5023   double lo;
5024   double dt;
5025   double fhi, fhi1;
5026   double flo, flo1;
5027   double num;
5028   double den;
5029   double dirt;
5030
5031   if (_ntl_zsign(num_bound) < 0)
5032      zhalt("rational reconstruction: bad numerator bound");
5033
5034   if (!num_bound)
5035      snum = 1;
5036   else
5037      snum = num_bound[0];
5038
5039   if (_ntl_zsign(den_bound) <= 0)
5040      zhalt("rational reconstruction: bad denominator bound");
5041
5042   sden = den_bound[0];
5043
5044   if (_ntl_zsign(nin) <= 0)
5045      zhalt("rational reconstruction: bad modulus");
5046
5047   if (_ntl_zsign(ain) < 0 || _ntl_zcompare(ain, nin) >= 0)
5048      zhalt("rational reconstruction: bad residue");
5049
5050     
5051   e = nin[0];
5052   _ntl_zsetlength(&a, e);
5053   _ntl_zsetlength(&n, e);
5054   _ntl_zsetlength(&q, e);
5055   _ntl_zsetlength(&w, e);
5056   _ntl_zsetlength(&x, e);
5057   _ntl_zsetlength(&y, e);
5058   _ntl_zsetlength(&z, e);
5059   _ntl_zsetlength(&inv, e);
5060   _ntl_zsetlength(&u, e);
5061   _ntl_zsetlength(&a_bak, e);
5062   _ntl_zsetlength(&n_bak, e);
5063   _ntl_zsetlength(&inv_bak, e);
5064   _ntl_zsetlength(&w_bak, e);
5065
5066   fhi1 = 1.0 + ((double) 32.0)/NTL_FDOUBLE_PRECISION;
5067   flo1 = 1.0 - ((double) 32.0)/NTL_FDOUBLE_PRECISION;
5068
5069   fhi = 1.0 + ((double) 8.0)/NTL_FDOUBLE_PRECISION;
5070   flo = 1.0 - ((double) 8.0)/NTL_FDOUBLE_PRECISION;
5071
5072   _ntl_zcopy(ain, &a);
5073   _ntl_zcopy(nin, &n);
5074
5075   _ntl_zone(&inv);
5076   _ntl_zzero(&w);
5077
5078   while (1)
5079   {
5080      if (w[0] >= sden && _ntl_zcompare(w, den_bound) > 0) break;
5081      if (n[0] <= snum && _ntl_zcompare(n, num_bound) <= 0) break;
5082
5083      _ntl_zcopy(a, &a_bak);
5084      _ntl_zcopy(n, &n_bak);
5085      _ntl_zcopy(w, &w_bak);
5086      _ntl_zcopy(inv, &inv_bak);
5087
5088      gotthem = 0;
5089      sa = a[0];
5090      sn = n[0];
5091      diff = sa - sn;
5092      if (!diff || diff == 1)
5093      {
5094         sa = a[0];
5095         p = &a[sa];
5096         num = (double) (*p) * NTL_FRADIX;
5097         if (sa > 1)
5098            num += (*(--p));
5099         num *= NTL_FRADIX;
5100         if (sa > 2)
5101            num += (*(p - 1));
5102         sn = n[0];
5103         p = &n[sn];
5104         den = (double) (*p) * NTL_FRADIX;
5105         if (sn > 1)
5106            den += (*(--p));
5107         den *= NTL_FRADIX;
5108         if (sn > 2)
5109            den += (*(p - 1));
5110         hi = fhi1 * (num + 1.0) / den;
5111         lo = flo1 * num / (den + 1.0);
5112         if (diff > 0)
5113         {
5114            hi *= NTL_FRADIX;
5115            lo *= NTL_FRADIX;
5116         }
5117         try11 = 1;
5118         try12 = 0;
5119         try21 = 0;
5120         try22 = 1;
5121         parity = 1;
5122         fast = 1; 
5123         while (fast > 0)
5124         {
5125            parity = 1 - parity;
5126            if (hi >= NTL_FRADIX)
5127               fast = 0;
5128            else
5129            {
5130               ilo = (long)lo;
5131               dirt = hi - ilo;
5132               if (dirt < 1.0/NTL_FDOUBLE_PRECISION || !ilo || ilo < (long)hi)
5133                  fast = 0;
5134               else
5135               {
5136                  dt = lo-ilo;
5137                  lo = flo / dirt;
5138                  if (dt > 1.0/NTL_FDOUBLE_PRECISION)
5139                     hi = fhi / dt;
5140                  else
5141                     hi = NTL_FRADIX;
5142                  temp = try11;
5143                  try11 = try21;
5144                  if ((NTL_RADIX - temp) / ilo < try21)
5145                     fast = 0;
5146                  else
5147                     try21 = temp + ilo * try21;
5148                  temp = try12;
5149                  try12 = try22;
5150                  if ((NTL_RADIX - temp) / ilo < try22)
5151                     fast = 0;
5152                  else
5153                     try22 = temp + ilo * try22;
5154                  if ((fast > 0) && (parity > 0))
5155                  {
5156                     gotthem = 1;
5157                     got11 = try11;
5158                     got12 = try12;
5159                     got21 = try21;
5160                     got22 = try22;
5161                  }
5162               }
5163            }
5164         }
5165      }
5166      if (gotthem)
5167      {
5168         _ntl_zsmul(inv, got11, &x);
5169         _ntl_zsmul(w, got12, &y);
5170         _ntl_zsmul(inv, got21, &z);
5171         _ntl_zsmul(w, got22, &w);
5172         _ntl_zadd(x, y, &inv);
5173         _ntl_zadd(z, w, &w);
5174         _ntl_zsmul(a, got11, &x);
5175         _ntl_zsmul(n, got12, &y);
5176         _ntl_zsmul(a, got21, &z);
5177         _ntl_zsmul(n, got22, &n);
5178         _ntl_zsub(x, y, &a);
5179         _ntl_zsub(n, z, &n);
5180      }
5181      else
5182      {
5183         _ntl_zdiv(a, n, &q, &a);
5184         _ntl_zmul(q, w, &x);
5185         _ntl_zadd(inv, x, &inv);
5186         if (a[0] > 1 || a[1] > 0)
5187         {
5188            _ntl_zdiv(n, a, &q, &n);
5189            _ntl_zmul(q, inv, &x);
5190            _ntl_zadd(w, x, &w);
5191         }
5192         else
5193         {
5194            break;
5195         }
5196      }
5197   }
5198
5199   _ntl_zcopy(a_bak, &a);
5200   _ntl_zcopy(n_bak, &n);
5201   _ntl_zcopy(w_bak, &w);
5202   _ntl_zcopy(inv_bak, &inv);
5203
5204   _ntl_znegate(&w);
5205
5206   while (1)
5207   {
5208      sa = w[0];
5209      if (sa < 0) w[0] = -sa;
5210      if (w[0] >= sden && _ntl_zcompare(w, den_bound) > 0) return 0;
5211      w[0] = sa;
5212
5213      if (n[0] <= snum && _ntl_zcompare(n, num_bound) <= 0) break;
5214     
5215      fast = 0;
5216      sa = a[0];
5217      sn = n[0];
5218      diff = sa - sn;
5219      if (!diff || diff == 1)
5220      {
5221         sa = a[0];
5222         p = &a[sa];
5223         num = (double) (*p) * NTL_FRADIX;
5224         if (sa > 1)
5225            num += (*(--p));
5226         num *= NTL_FRADIX;
5227         if (sa > 2)
5228            num += (*(p - 1));
5229         sn = n[0];
5230         p = &n[sn];
5231         den = (double) (*p) * NTL_FRADIX;
5232         if (sn > 1)
5233            den += (*(--p));
5234         den *= NTL_FRADIX;
5235         if (sn > 2)
5236            den += (*(p - 1));
5237         hi = fhi1 * (num + 1.0) / den;
5238         lo = flo1 * num / (den + 1.0);
5239         if (diff > 0)
5240         {
5241            hi *= NTL_FRADIX;
5242            lo *= NTL_FRADIX;
5243         }
5244         if (hi < NTL_FRADIX)
5245         {
5246            ilo = (long)lo;
5247            if (ilo == (long)hi)
5248               fast = 1;
5249         }
5250      }
5251
5252      if (fast) 
5253      {
5254         if (ilo != 0) {
5255            if (ilo == 1) {
5256               _ntl_zsub(inv, w, &inv);
5257               _ntl_zsubpos(a, n, &a);
5258            }
5259            else if (ilo == 2) {
5260               _ntl_z2mul(w, &x);
5261               _ntl_zsub(inv, x, &inv);
5262               _ntl_z2mul(n, &x);
5263               _ntl_zsubpos(a, x, &a);
5264            }
5265            else if (ilo ==3) {
5266               _ntl_z2mul(w, &x);
5267               _ntl_zadd(w, x, &x);
5268               _ntl_zsub(inv, x, &inv);
5269               _ntl_z2mul(n, &x);
5270               _ntl_zadd(n, x, &x);
5271               _ntl_zsubpos(a, x, &a);
5272            }
5273            else if (ilo == 4) {
5274               _ntl_zlshift(w, 2, &x);
5275               _ntl_zsub(inv, x, &inv);
5276               _ntl_zlshift(n, 2, &x);
5277               _ntl_zsubpos(a, x, &a);
5278            }
5279            else {
5280               _ntl_zsmul(w, ilo, &x);
5281               _ntl_zsub(inv, x, &inv);
5282               _ntl_zsmul(n, ilo, &x);
5283               _ntl_zsubpos(a, x, &a);
5284            }
5285         }
5286      }
5287      else {
5288         _ntl_zdiv(a, n, &q, &a);
5289         _ntl_zmul(q, w, &x);
5290         _ntl_zsub(inv, x, &inv);
5291      }
5292
5293      _ntl_zswap(&a, &n);
5294      _ntl_zswap(&inv, &w);
5295   }
5296
5297   if (_ntl_zsign(w) < 0) {
5298      _ntl_znegate(&w);
5299      _ntl_znegate(&n);
5300   }
5301
5302   _ntl_zcopy(n, num_out);
5303   _ntl_zcopy(w, den_out);
5304
5305   return 1;
5306}
5307
5308
5309
5310static
5311long OptWinSize(long n)
5312/* finds k that minimizes n/(k+1) + 2^{k-1} */
5313
5314{
5315   long k;
5316   double v, v_new;
5317
5318
5319   v = n/2.0 + 1.0;
5320   k = 1;
5321
5322   for (;;) {
5323      v_new = n/((double)(k+2)) + ((double)(1L << k));
5324      if (v_new >= v) break;
5325      v = v_new;
5326      k++;
5327   }
5328
5329   return k;
5330}
5331
5332     
5333
5334static
5335void _ntl_zsppowermod(long a, _ntl_verylong e, _ntl_verylong n, 
5336                      _ntl_verylong *x)
5337{
5338   _ntl_verylong res;
5339   long i, k;
5340
5341   if (_ntl_ziszero(e)) {
5342      _ntl_zone(x);
5343      return;
5344   }
5345
5346   res = 0;
5347   _ntl_zsetlength(&res, n[0]);
5348   _ntl_zone(&res);
5349
5350   k = _ntl_z2log(e);
5351
5352   for (i = k - 1; i >= 0; i--) {
5353      _ntl_zsqmod(res, n, &res);
5354      if (_ntl_zbit(e, i))
5355         _ntl_zsmulmod(res, a, n, &res);
5356   }
5357
5358   if (_ntl_zsign(e) < 0) _ntl_zinvmod(res, n, &res);
5359
5360   _ntl_zcopy(res, x);
5361   _ntl_zfree(&res);
5362}
5363
5364
5365
5366static
5367void _ntl_ztwopowermod( _ntl_verylong e, _ntl_verylong n, 
5368                      _ntl_verylong *x)
5369{
5370   _ntl_verylong res;
5371   long i, k;
5372
5373   if (_ntl_ziszero(e)) {
5374      _ntl_zone(x);
5375      return;
5376   }
5377
5378   res = 0;
5379   _ntl_zsetlength(&res, n[0]);
5380   _ntl_zone(&res);
5381
5382   k = _ntl_z2log(e);
5383
5384   for (i = k - 1; i >= 0; i--) {
5385      _ntl_zsqmod(res, n, &res);
5386      if (_ntl_zbit(e, i))
5387         _ntl_zaddmod(res, res, n, &res);
5388   }
5389
5390   if (_ntl_zsign(e) < 0) _ntl_zinvmod(res, n, &res);
5391
5392   _ntl_zcopy(res, x);
5393   _ntl_zfree(&res);
5394}
5395
5396
5397void _ntl_zpowermod(_ntl_verylong g, _ntl_verylong e, _ntl_verylong F,
5398                    _ntl_verylong *h)
5399
5400/* h = g^e mod f using "sliding window" algorithm
5401
5402   remark: the notation (h, g, e, F) is strange, because I
5403   copied the code from BB.c.
5404*/
5405
5406{
5407   _ntl_verylong res, *v, t;
5408   long n, i, k, val, cnt, m;
5409
5410   if (_ntl_zsign(g) < 0 || _ntl_zcompare(g, F) >= 0 || 
5411       _ntl_zscompare(F, 1) <= 0) 
5412      zhalt("PowerMod: bad args");
5413
5414#ifdef NTL_GMP_HACK
5415
5416   if (_ntl_gmp_hack) {
5417      res = 0;
5418      _ntl_gmp_powermod(&res, g, e, F);
5419
5420      /* careful...don't compute directly into h, as it could lead
5421       * to an allocation error in some cases.
5422       */
5423
5424      _ntl_zcopy(res, h);
5425      _ntl_zfree(&res);
5426      return;
5427   }
5428
5429#endif
5430
5431   if (!g || g[0] == 1 || g[0] == -1) {
5432      long gg = _ntl_ztoint(g);
5433      if (gg == 2)
5434         _ntl_ztwopowermod(e, F, h);
5435      else
5436         _ntl_zsppowermod(gg, e, F, h);
5437      return;
5438   }
5439
5440   if (_ntl_zscompare(e, 0) == 0) {
5441      _ntl_zone(h);
5442      return;
5443   }
5444
5445   if (_ntl_zscompare(e, 1) == 0) {
5446      _ntl_zcopy(g, h);
5447      return;
5448   }
5449
5450   if (_ntl_zscompare(e, -1) == 0) {
5451      _ntl_zinvmod(g, F, h);
5452      return;
5453   }
5454
5455   if (_ntl_zscompare(e, 2) == 0) {
5456      _ntl_zsqmod(g, F, h);
5457      return;
5458   }
5459
5460   if (_ntl_zscompare(e, -2) == 0) {
5461      res = 0;
5462      _ntl_zsqmod(g, F, &res);
5463      _ntl_zinvmod(res, F, h);
5464      _ntl_zfree(&res);
5465      return;
5466   }
5467
5468   n = _ntl_z2log(e);
5469
5470   res = 0;
5471   _ntl_zone(&res);
5472
5473   if (n < 16) {
5474      /* plain square-and-multiply algorithm */
5475
5476      for (i = n - 1; i >= 0; i--) {
5477         _ntl_zsqmod(res, F, &res);
5478         if (_ntl_zbit(e, i))
5479            _ntl_zmulmod(res, g, F, &res);
5480      }
5481
5482      if (_ntl_zsign(e) < 0) _ntl_zinvmod(res, F, &res);
5483
5484      _ntl_zcopy(res, h);
5485      _ntl_zfree(&res);
5486      return;
5487   }
5488
5489   k = OptWinSize(n);
5490
5491   if (k > 5) k = 5;
5492
5493   v = (_ntl_verylong *) NTL_MALLOC(1L << (k-1), sizeof(_ntl_verylong), 0);
5494   if (!v) zhalt("out of memory");
5495   for (i = 0; i < (1L << (k-1)); i++)
5496      v[i] = 0; 
5497
5498   _ntl_zcopy(g, &v[0]);
5499 
5500   if (k > 1) {
5501      t = 0;
5502      _ntl_zsqmod(g, F, &t);
5503
5504      for (i = 1; i < (1L << (k-1)); i++)
5505         _ntl_zmulmod(v[i-1], t, F, &v[i]);
5506
5507      _ntl_zfree(&t);
5508   }
5509
5510
5511   val = 0;
5512   for (i = n-1; i >= 0; i--) {
5513      val = (val << 1) | _ntl_zbit(e, i); 
5514      if (val == 0)
5515         _ntl_zsqmod(res, F, &res);
5516      else if (val >= (1L << (k-1)) || i == 0) {
5517         cnt = 0;
5518         while ((val & 1) == 0) {
5519            val = val >> 1;
5520            cnt++;
5521         }
5522
5523         m = val;
5524         while (m > 0) {
5525            _ntl_zsqmod(res, F, &res);
5526            m = m >> 1;
5527         }
5528
5529         _ntl_zmulmod(res, v[val >> 1], F, &res);
5530
5531         while (cnt > 0) {
5532            _ntl_zsqmod(res, F, &res);
5533            cnt--;
5534         }
5535
5536         val = 0;
5537      }
5538   }
5539
5540   if (_ntl_zsign(e) < 0) _ntl_zinvmod(res, F, &res);
5541
5542   _ntl_zcopy(res, h);
5543
5544   _ntl_zfree(&res);
5545   for (i = 0; i < (1L << (k-1)); i++)
5546      _ntl_zfree(&v[i]);
5547   free(v);
5548}
5549
5550
5551
5552
5553
5554
5555void
5556_ntl_zexp(
5557        _ntl_verylong a,
5558        long e,
5559        _ntl_verylong *bb
5560        )
5561{
5562        long k;
5563        long len_a;
5564        long sa;
5565        static _ntl_verylong res = 0;
5566
5567        if (!a)
5568                sa = 0;
5569        else {
5570                sa = a[0];
5571                if (sa < 0) sa = -sa;
5572        }
5573
5574        if (sa <= 1) {
5575                _ntl_zexps(_ntl_ztoint(a), e, bb);
5576                return;
5577        }
5578
5579
5580        if (!e)
5581        {
5582                _ntl_zone(bb);
5583                return;
5584        }
5585
5586        if (e < 0)
5587                zhalt("negative exponent in _ntl_zexp");
5588
5589        if (_ntl_ziszero(a))
5590        {
5591                _ntl_zzero(bb);
5592                return;
5593        }
5594
5595        len_a = _ntl_z2log(a);
5596        if (len_a > (NTL_MAX_LONG-(NTL_NBITS-1))/e)
5597                zhalt("overflow in _ntl_zexp");
5598
5599        _ntl_zsetlength(&res, (len_a*e+NTL_NBITS-1)/NTL_NBITS);
5600
5601        _ntl_zcopy(a, &res);
5602        k = 1;
5603        while ((k << 1) <= e)
5604                k <<= 1;
5605        while (k >>= 1) {
5606                _ntl_zsq(res, &res);
5607                if (e & k)
5608                        _ntl_zmul(a, res, &res);
5609        }
5610
5611        _ntl_zcopy(res, bb);
5612}
5613
5614void
5615_ntl_zexps(
5616        long a,
5617        long e,
5618        _ntl_verylong *bb
5619        )
5620{
5621        long k;
5622        long len_a;
5623        static _ntl_verylong res = 0;
5624
5625        if (!e)
5626        {
5627                _ntl_zone(bb);
5628                return;
5629        }
5630
5631        if (e < 0)
5632                zhalt("negative exponent in _ntl_zexps");
5633
5634        if (!a)
5635        {
5636                _ntl_zzero(bb);
5637                return;
5638        }
5639
5640        if (a >= NTL_RADIX || a <= -NTL_RADIX) {
5641                _ntl_zintoz(a, &res);
5642                _ntl_zexp(res, e, &res);
5643                return;
5644        }
5645
5646        len_a = _ntl_z2logs(a);
5647        if (len_a > (NTL_MAX_LONG-(NTL_NBITS-1))/e)
5648                zhalt("overflow in _ntl_zexps");
5649
5650        _ntl_zsetlength(&res, (len_a*e+NTL_NBITS-1)/NTL_NBITS);
5651
5652        _ntl_zintoz(a, &res);
5653        k = 1;
5654        while ((k << 1) <= e)
5655                k <<= 1;
5656        while (k >>= 1) {
5657                _ntl_zsq(res, &res);
5658                if (e & k)
5659                        _ntl_zsmul(res, a, &res);
5660        }
5661
5662        _ntl_zcopy(res, bb);
5663}
5664
5665
5666void
5667_ntl_z2mul(
5668        _ntl_verylong n,
5669        _ntl_verylong *rres
5670        )
5671{
5672        long sn;
5673        long i;
5674        long n_alias;
5675        long carry;
5676        _ntl_verylong res;
5677
5678        if (!n)
5679        {
5680                _ntl_zzero(rres);
5681                return;
5682        }
5683
5684
5685        if ((!n[1]) && (n[0] == 1))
5686        {
5687                _ntl_zzero(rres);
5688                return;
5689        }
5690
5691        if ((sn = n[0]) < 0)
5692                sn = -sn;
5693
5694        res = *rres;
5695        n_alias = (n == res);
5696
5697        _ntl_zsetlength(&res, sn + 1);
5698        if (n_alias) n = res;
5699        *rres = res;
5700
5701        carry = 0;
5702
5703        for (i = 1; i <= sn; i++)
5704        {
5705                if ((res[i] = (n[i] << 1) + carry) >= NTL_RADIX)
5706                {
5707                        res[i] -= NTL_RADIX;
5708                        carry = 1;
5709                }
5710                else
5711                        carry = 0;
5712        }
5713
5714        if (carry)
5715                res[++sn] = 1;
5716
5717        if (n[0] < 0)
5718                res[0] = -sn;
5719        else
5720                res[0] = sn;
5721}
5722
5723
5724long 
5725_ntl_z2div(
5726        _ntl_verylong n,
5727        _ntl_verylong *rres
5728        )
5729{
5730        long sn;
5731        long i;
5732        long result;
5733        _ntl_verylong res = *rres;
5734
5735        if ((!n) || ((!n[1]) && (n[0] == 1)))
5736        {
5737                _ntl_zzero(rres);
5738                return (0);
5739        }
5740
5741        if ((sn = n[0]) < 0)
5742                sn = -sn;
5743
5744        /* n won't move if res aliases n */
5745        _ntl_zsetlength(&res, sn);
5746        *rres = res;
5747
5748        result = n[1] & 1;
5749        for (i = 1; i < sn; i++)
5750        {
5751                res[i] = (n[i] >> 1);
5752                if (n[i + 1] & 1)
5753                        res[i] += (NTL_RADIX >> 1);
5754        }
5755
5756        if (res[sn] = (n[sn] >> 1))
5757                res[0] = n[0];
5758        else if (sn == 1)
5759        {
5760                res[0] = 1;
5761        }
5762        else if (n[0] < 0)
5763                res[0] = -sn + 1;
5764        else
5765                res[0] = sn - 1;
5766
5767        return (result);
5768}
5769
5770
5771void
5772_ntl_zlshift(
5773        _ntl_verylong n,
5774        long k,
5775        _ntl_verylong *rres
5776        )
5777{
5778        long big;
5779        long small;
5780        long sn;
5781        long i;
5782        long cosmall;
5783        long n_alias;
5784        _ntl_verylong res;
5785
5786
5787        if (!n)
5788        {
5789                _ntl_zzero(rres);
5790                return;
5791        }
5792
5793        if ((!n[1]) && (n[0] == 1))
5794        {
5795                _ntl_zzero(rres);
5796                return;
5797        }
5798
5799        res = *rres;
5800        n_alias = (n == res);
5801       
5802
5803        if (!k)
5804        {
5805                if (!n_alias)
5806                        _ntl_zcopy(n, rres);
5807                return;
5808        }
5809
5810        if (k < 0)
5811        {
5812                if (k < -NTL_MAX_LONG) 
5813                        _ntl_zzero(rres); 
5814                else
5815                        _ntl_zrshift(n, -k, rres);
5816                return;
5817        }
5818        if (k == 1)
5819        {
5820                _ntl_z2mul(n, rres);
5821                return;
5822        }
5823
5824        if ((sn = n[0]) < 0)
5825                sn = -sn;
5826
5827        i = sn + (big = k / NTL_NBITS);
5828        if (small = k - big * NTL_NBITS)
5829        {
5830                _ntl_zsetlength(&res, i + 1);
5831                if (n_alias) n = res;
5832                *rres = res;
5833
5834                res[i + 1] = n[sn] >> (cosmall = NTL_NBITS - small);
5835                for (i = sn; i > 1; i--)
5836                        res[i + big] = ((((unsigned long) n[i]) << small) & NTL_RADIXM) + (n[i - 1] >> cosmall);
5837                res[big + 1] = (((unsigned long) n[1]) << small) & NTL_RADIXM;
5838                for (i = big; i; i--)
5839                        res[i] = 0;
5840                if (res[sn + big + 1])
5841                        big++;
5842        }
5843        else
5844        {
5845                _ntl_zsetlength(&res, i);
5846                if (n_alias) n = res;
5847                *rres = res;
5848
5849                for (i = sn; i; i--)
5850                        res[i + big] = n[i];
5851                for (i = big; i; i--)
5852                        res[i] = 0;
5853        }
5854        if (n[0] > 0)
5855                res[0] = n[0] + big;
5856        else
5857                res[0] = n[0] - big;
5858}
5859
5860
5861void
5862_ntl_zrshift(
5863        _ntl_verylong n,
5864        long k,
5865        _ntl_verylong *rres
5866        )
5867{
5868        long big;
5869        long small;
5870        long sn;
5871        long i;
5872        long cosmall;
5873        _ntl_verylong res;
5874
5875        if (!n)
5876        {
5877                _ntl_zzero(rres);
5878                return;
5879        }
5880
5881        if ((!n[1]) && (n[0] == 1))
5882        {
5883                _ntl_zzero(rres);
5884                return;
5885        }
5886
5887        res = *rres;
5888
5889        if (!k)
5890        {
5891                if (n != res)
5892                        _ntl_zcopy(n, rres);
5893                return;
5894        }
5895
5896        if (k < 0)
5897        {
5898                if (k < -NTL_MAX_LONG) zhalt("overflow in _ntl_zrshift");
5899                _ntl_zlshift(n, -k, rres);
5900                return;
5901        }
5902
5903        if (k == 1)
5904        {
5905                _ntl_z2div(n, rres);
5906                return;
5907        }
5908
5909        big = k / NTL_NBITS;
5910        small = k - big * NTL_NBITS;
5911
5912        if ((sn = n[0]) < 0)
5913                sn = -sn;
5914
5915        if ((big >= sn) || 
5916            ((big == sn - 1) && small && (!(n[sn] >> small))))
5917        /* The microsoft optimizer generates bad code without
5918           the above test for small != 0 */
5919        {
5920                _ntl_zzero(rres);
5921                return;
5922        }
5923
5924        sn -= big;
5925
5926        /* n won't move if res aliases n */
5927        _ntl_zsetlength(&res, sn);
5928        *rres = res;
5929
5930        if (small)
5931        {
5932                cosmall = NTL_NBITS - small;
5933                for (i = 1; i < sn; i++)
5934                        res[i] = (n[i + big] >> small) +
5935                                ((((unsigned long) n[i + big + 1]) << cosmall) & NTL_RADIXM);
5936                if (!(res[sn] = (n[sn + big] >> small)))
5937                        sn--;
5938        }
5939        else
5940                for (i = 1; i <= sn; i++)
5941                        res[i] = n[i + big];
5942        if (n[0] > 0)
5943                res[0] = sn;
5944        else
5945                res[0] = -sn;
5946}
5947
5948
5949long 
5950_ntl_zmakeodd(
5951        _ntl_verylong *nn
5952        )
5953{
5954        _ntl_verylong n = *nn;
5955        long i;
5956        long shift = 1;
5957
5958        if (!n || (!n[1] && (n[0] == 1)))
5959                return (0);
5960        while (!(n[shift]))
5961                shift++;
5962        i = n[shift];
5963        shift = NTL_NBITS * (shift - 1);
5964        while (!(i & 1))
5965        {
5966                shift++;
5967                i >>= 1;
5968        }
5969        _ntl_zrshift(n, shift, &n);
5970        return (shift);
5971}
5972
5973
5974long 
5975_ntl_znumtwos(
5976        _ntl_verylong n
5977        )
5978{
5979        long i;
5980        long shift = 1;
5981
5982        if (!n || (!n[1] && (n[0] == 1)))
5983                return (0);
5984        while (!(n[shift]))
5985                shift++;
5986        i = n[shift];
5987        shift = NTL_NBITS * (shift - 1);
5988        while (!(i & 1))
5989        {
5990                shift++;
5991                i >>= 1;
5992        }
5993        return (shift);
5994}
5995
5996
5997long 
5998_ntl_zsqrts(
5999        long n
6000        )
6001{
6002        long a;
6003        long ndiva;
6004        long newa;
6005        static _ntl_verylong ln=0;
6006        static _ntl_verylong rr=0;
6007
6008        if (n < 0) 
6009                zhalt("_ntl_zsqrts: negative argument");
6010
6011        if (n <= 0)
6012                return (0);
6013        if (n <= 3)
6014                return (1);
6015        if (n <= 8)
6016                return (2);
6017        if (n >= NTL_RADIX)
6018        {
6019                _ntl_zintoz(n,&ln);
6020                _ntl_zsqrt(ln,&rr);
6021                return(_ntl_ztoint(rr));
6022        }
6023        newa = 3L << (2 * (NTL_NBITSH - 1));
6024        a = 1L << NTL_NBITSH;
6025        while (!(n & newa))
6026        {
6027                newa >>= 2;
6028                a >>= 1;
6029        }
6030        while (1)
6031        {
6032                newa = ((ndiva = n / a) + a) / 2;
6033                if (newa - ndiva <= 1)
6034                {
6035                        if (newa * newa <= n)
6036                                return (newa);
6037                        else
6038                                return (ndiva);
6039                }
6040                a = newa;
6041        }
6042}
6043
6044
6045void _ntl_zsqrt(_ntl_verylong n, _ntl_verylong *rr)
6046{
6047        static _ntl_verylong a = 0;
6048        static _ntl_verylong ndiva = 0;
6049        static _ntl_verylong diff = 0;
6050        static _ntl_verylong r = 0;
6051        long i;
6052
6053        if (!n) {
6054                _ntl_zzero(rr);
6055                return;
6056        }
6057
6058        if ((i = n[0]) < 0)
6059                zhalt("negative argument in _ntl_zsqrt");
6060
6061        if (i == 1) {
6062                _ntl_zintoz(_ntl_zsqrts(n[1]), rr);
6063                return;
6064        }
6065
6066#ifdef NTL_GMP_HACK
6067   if (_ntl_gmp_hack && i >= NTL_GMP_SQRT_CROSS) {
6068      GT_INIT
6069
6070      lip_to_mpz(n, gt_1);
6071      mpz_sqrt(gt_2, gt_1);
6072      mpz_to_lip(&r, gt_2);
6073      _ntl_zcopy(r, rr);
6074      return;
6075   }
6076#endif
6077
6078        _ntl_zsetlength(&a, i);
6079        _ntl_zsetlength(&ndiva, i);
6080        _ntl_zsetlength(&diff, i);
6081
6082        a[(a[0] = (i + 1) / 2)] = _ntl_zsqrts(n[i]) + 1;
6083        if (!(i & 1))
6084                a[a[0]] <<= NTL_NBITSH;
6085
6086        if (a[a[0]] & NTL_RADIX) {
6087                a[a[0]] = 0;
6088                a[0]++;
6089                a[a[0]] = 1;
6090        }
6091
6092        for (i = a[0] - 1; i; i--)
6093                a[i] = 0;
6094
6095        while (1) {
6096                _ntl_zdiv(n, a, &ndiva, &r);
6097                _ntl_zadd(a, ndiva, &r);
6098                _ntl_zrshift(r, 1, &r);
6099                if (_ntl_zcompare(r, ndiva) <= 0) 
6100                        goto done;
6101
6102                _ntl_zsubpos(r, ndiva, &diff);
6103                if ((diff[0] == 1) && (diff[1] <= 1)) {
6104                        _ntl_zsq(r, &diff);
6105                        if (_ntl_zcompare(diff, n) > 0)
6106                                _ntl_zcopy(ndiva, &r);
6107
6108                        goto done;
6109                }
6110                _ntl_zcopy(r, &a);
6111        }
6112done:
6113        _ntl_zcopy(r, rr);
6114}
6115
6116
6117
6118void
6119_ntl_zgcd(
6120        _ntl_verylong mm1,
6121        _ntl_verylong mm2,
6122        _ntl_verylong *rres
6123        )
6124{
6125        long agrb;
6126        long shibl;
6127        static _ntl_verylong aa = 0;
6128        static _ntl_verylong bb = 0;
6129        static _ntl_verylong cc = 0;
6130        _ntl_verylong a;
6131        _ntl_verylong b;
6132        _ntl_verylong c;
6133        _ntl_verylong d;
6134        long m1negative;
6135        long m2negative;
6136
6137        /* _ntl_ziszero is necessary here and below to fix an
6138           an aliasing bug in LIP */
6139
6140        if (_ntl_ziszero(mm1))
6141        {
6142                if (mm2 != *rres)
6143                        _ntl_zcopy(mm2,rres);
6144                _ntl_zabs(rres);
6145                return;
6146        }
6147
6148        if (_ntl_ziszero(mm2))
6149        {
6150                if (mm1 != *rres)
6151                        _ntl_zcopy(mm1,rres);
6152                _ntl_zabs(rres);
6153                return;
6154        }
6155
6156        if (mm1 == mm2)
6157        {
6158                if (mm1 != *rres)
6159                        _ntl_zcopy(mm1, rres);
6160                _ntl_zabs(rres);
6161                return;
6162        }
6163
6164#ifdef NTL_GMP_HACK
6165   {
6166      long s1 = mm1[0];
6167      long s2 = mm2[0];
6168
6169      if (s1 < 0) s1 = -s1;
6170      if (s2 < 0) s2 = -s2;
6171
6172      if (_ntl_gmp_hack && s1 >= NTL_GMP_GCD_CROSS && s2 >= NTL_GMP_GCD_CROSS) {
6173         GT_INIT
6174
6175         lip_to_mpz(mm1, gt_1);
6176         lip_to_mpz(mm2, gt_2);
6177         mpz_gcd(gt_3, gt_1, gt_2);
6178         mpz_to_lip(&aa, gt_3);
6179         _ntl_zcopy(aa, rres);
6180         return;
6181      }
6182   }
6183#endif
6184
6185        if (m1negative = (mm1[0] < 0))
6186                mm1[0] = -mm1[0];
6187        if (m2negative = (mm2[0] < 0))
6188                mm2[0] = -mm2[0];
6189
6190        if ((agrb = mm1[0]) < mm2[0])
6191                agrb = mm2[0];
6192
6193        _ntl_zsetlength(&aa, agrb+1); 
6194        _ntl_zsetlength(&bb, agrb+1);
6195        _ntl_zsetlength(&cc, agrb+1);
6196
6197        if (mm1[0] != mm2[0])
6198        {
6199                if (mm1[0] > mm2[0])
6200                {
6201                        _ntl_zcopy(mm2, &aa);
6202                        _ntl_zmod(mm1, aa, &bb);
6203                }
6204                else
6205                {
6206                        _ntl_zcopy(mm1, &aa);
6207                        _ntl_zmod(mm2, aa, &bb);
6208                }
6209                if (!(bb[1]) && (bb[0] == 1))
6210                {
6211                        a = aa;
6212                        goto done;
6213                }
6214        }
6215        else
6216        {
6217                _ntl_zcopy(mm1, &aa);
6218                _ntl_zcopy(mm2, &bb);
6219        }
6220        if ((agrb = _ntl_zmakeodd(&aa)) < (shibl = _ntl_zmakeodd(&bb)))
6221                shibl = agrb;
6222        if (!(agrb = _ntl_zcompare(aa, bb)))
6223        {
6224                a = aa;
6225                goto endshift;
6226        }
6227        else if (agrb < 0)
6228        {
6229                a = bb;
6230                b = aa;
6231        }
6232        else
6233        {
6234                a = aa;
6235                b = bb;
6236        }
6237        c = cc;
6238        _ntl_zsubpos(a, b, &c);
6239        do
6240        {
6241                _ntl_zmakeodd(&c);
6242                if (!(agrb = _ntl_zcompare(b, c)))
6243                {
6244                        a = b;
6245                        goto endshift;
6246                }
6247                else if (agrb > 0)
6248                {
6249                        a = b;
6250                        b = c;
6251                        c = a;
6252                }
6253                else
6254                {
6255                        d = a;
6256                        a = c;
6257                        c = d;
6258                }
6259                _ntl_zsubpos(a, b, &c);
6260        } while (c[1] || c[0] != 1);
6261endshift:
6262        _ntl_zlshift(a, shibl, &a);
6263done:
6264        if (m1negative)
6265                mm1[0] = -mm1[0];
6266        if (m2negative)
6267                mm2[0] = -mm2[0];
6268        _ntl_zcopy(a, rres);
6269}
6270
6271
6272long _ntl_zsign(_ntl_verylong a)
6273{
6274        if (!a)
6275        {
6276                return (0);
6277        }
6278        if (a[0] < 0)
6279                return (-1);
6280        if (a[0] > 1)
6281                return (1);
6282        if (a[1])
6283                return (1);
6284        return (0);
6285}
6286
6287void _ntl_zabs(_ntl_verylong *pa)
6288{
6289        _ntl_verylong a = *pa;
6290
6291        if (!a)
6292                return;
6293        if (a[0] < 0)
6294                a[0] = (-a[0]);
6295}
6296
6297long 
6298_ntl_z2logs(
6299        long aa
6300        )
6301{
6302        long i = 0;
6303        unsigned long a;
6304
6305        if (aa < 0)
6306                a = - ((unsigned long) aa);
6307        else
6308                a = aa;
6309
6310        while (a>=256)
6311                i += 8, a >>= 8;
6312        if (a >=16)
6313                i += 4, a >>= 4;
6314        if (a >= 4)
6315                i += 2, a >>= 2;
6316        if (a >= 2)
6317                i += 2;
6318        else if (a >= 1)
6319                i++;
6320        return (i);
6321}
6322
6323long 
6324_ntl_z2log(
6325        _ntl_verylong a
6326        )
6327{
6328        long la;
6329
6330        if (!a)
6331                return (0);
6332        la = (a[0] > 0 ? a[0] : -a[0]);
6333        return ( NTL_NBITS * (la - 1) + _ntl_z2logs(a[la]) );
6334}
6335
6336
6337
6338long
6339_ntl_zscompare(
6340        _ntl_verylong a,
6341        long b
6342        )
6343{
6344        if (!b) 
6345                return _ntl_zsign(a);
6346        else {
6347                static _ntl_verylong c = 0;
6348                _ntl_zintoz(b, &c);
6349                return (_ntl_zcompare(a, c));
6350        }
6351}
6352
6353void
6354_ntl_zswap(
6355        _ntl_verylong *a,
6356        _ntl_verylong *b
6357        )
6358{
6359        _ntl_verylong c;
6360
6361        if ((*a && ((*a)[-1] & 1)) || (*b && ((*b)[-1] & 1))) {
6362                static _ntl_verylong t = 0; 
6363                _ntl_zcopy(*a, &t);
6364                _ntl_zcopy(*b, a);
6365                _ntl_zcopy(t, b);
6366                return;
6367        }
6368
6369        c = *a;
6370        *a = *b;
6371        *b = c;
6372}
6373
6374long
6375_ntl_ziszero(
6376        _ntl_verylong a
6377        )
6378{
6379        if (!a) return (1);
6380        if (a[1]) return (0);
6381        if (a[0]==1) return (1);
6382        return (0);
6383}
6384
6385long
6386_ntl_zodd(
6387        _ntl_verylong a
6388        )
6389{
6390        if (!a) return (0);
6391        return (a[1]&1);
6392}
6393
6394
6395long
6396_ntl_zbit(
6397        _ntl_verylong a,
6398        long p
6399        )
6400{
6401        long bl;
6402        long wh;
6403        long sa;
6404
6405        if (p < 0 || !a) return 0;
6406        bl = (p/NTL_NBITS);
6407        wh = 1L << (p - NTL_NBITS*bl);
6408        bl ++;
6409        sa = a[0];
6410        if (sa < 0) sa = -sa;
6411        if (sa < bl) return (0);
6412        if (a[bl] & wh) return (1);
6413        return (0);
6414}
6415
6416
6417void
6418_ntl_zlowbits(
6419        _ntl_verylong a,
6420        long b,
6421        _ntl_verylong *cc
6422        )
6423{
6424        _ntl_verylong c;
6425        long bl;
6426        long wh;
6427        long sa;
6428
6429        if (_ntl_ziszero(a) || (b<=0)) {
6430                _ntl_zzero(cc);
6431                return;
6432        }
6433
6434
6435        bl = b/NTL_NBITS;
6436        wh = b - NTL_NBITS*bl;
6437        if (wh != 0) 
6438                bl++;
6439        else
6440                wh = NTL_NBITS;
6441
6442        sa = a[0];
6443        if (sa < 0) sa = -sa;
6444
6445        if (sa < bl) {
6446                _ntl_zcopy(a,cc);
6447                _ntl_zabs(cc);
6448                return;
6449        }
6450
6451        c = *cc;
6452
6453        /* a won't move if c aliases a */
6454        _ntl_zsetlength(&c, bl);
6455        *cc = c;
6456
6457        for (sa=1; sa<bl; sa++)
6458                c[sa] = a[sa];
6459        c[bl] = a[bl]&((1L<<wh)-1);
6460        while ((bl>1) && (!c[bl]))
6461                bl --;
6462        c[0] = bl;
6463}
6464
6465
6466long _ntl_zslowbits(_ntl_verylong a, long p)
6467{
6468   static _ntl_verylong x = 0;
6469
6470   if (p > NTL_BITS_PER_LONG)
6471      p = NTL_BITS_PER_LONG;
6472
6473   _ntl_zlowbits(a, p, &x);
6474
6475   return _ntl_ztoint(x);
6476}
6477
6478
6479
6480
6481long
6482_ntl_zweights(
6483        long aa
6484        )
6485{
6486        unsigned long a;
6487        long res = 0;
6488
6489        if (aa < 0) 
6490                a = - ((unsigned long) aa);
6491        else
6492                a = aa;
6493   
6494        while (a) {
6495                if (a & 1) res ++;
6496                a >>= 1;
6497        }
6498        return (res);
6499}
6500
6501long
6502_ntl_zweight(
6503        _ntl_verylong a
6504        )
6505{
6506        long i;
6507        long res = 0;
6508
6509        if (!a) return (0);
6510        i = a[0];
6511        if (i<0) i = -i;
6512        for (;i;i--)
6513                res += _ntl_zweights(a[i]);
6514        return (res);
6515}
6516
6517
6518
6519void
6520_ntl_zand(
6521        _ntl_verylong a,
6522        _ntl_verylong b,
6523        _ntl_verylong *cc
6524        )
6525
6526{
6527        _ntl_verylong c;
6528        long sa;
6529        long sb;
6530        long sm;
6531        long a_alias;
6532        long b_alias;
6533
6534        if (_ntl_ziszero(a) || _ntl_ziszero(b)) {
6535                _ntl_zzero(cc);
6536                return;
6537        }
6538
6539        c = *cc;
6540        a_alias = (a == c);
6541        b_alias = (b == c);
6542
6543        sa = a[0];
6544        if (sa < 0) sa = -sa;
6545
6546        sb = b[0];
6547        if (sb < 0) sb = -sb;
6548
6549        sm = (sa > sb ? sb : sa );
6550
6551        _ntl_zsetlength(&c, sm);
6552        if (a_alias) a = c;
6553        if (b_alias) b = c;
6554        *cc = c;
6555
6556        for (sa = 1; sa <= sm; sa ++) 
6557                c[sa] = a[sa] & b[sa];
6558
6559        while ((sm > 1) && (!(c[sm])))
6560                sm --;
6561        c[0] = sm;
6562}
6563
6564void
6565_ntl_zxor(
6566        _ntl_verylong a,
6567        _ntl_verylong b,
6568        _ntl_verylong *cc
6569        )
6570{
6571        _ntl_verylong c;
6572        long sa;
6573        long sb;
6574        long sm;
6575        long la;
6576        long i;
6577        long a_alias;
6578        long b_alias;
6579
6580        if (_ntl_ziszero(a)) {
6581                _ntl_zcopy(b,cc);
6582                _ntl_zabs(cc);
6583                return;
6584        }
6585
6586        if (_ntl_ziszero(b)) {
6587                _ntl_zcopy(a,cc);
6588                _ntl_zabs(cc);
6589                return;
6590        }
6591
6592        c = *cc;
6593        a_alias = (a == c);
6594        b_alias = (b == c);
6595
6596        sa = a[0];
6597        if (sa < 0) sa = -sa;
6598
6599        sb = b[0];
6600        if (sb < 0) sb = -sb;
6601
6602        if (sa > sb) {
6603                la = sa;
6604                sm = sb;
6605        } else {
6606                la = sb;
6607                sm = sa;
6608        }
6609
6610        _ntl_zsetlength(&c, la);
6611        if (a_alias) a = c;
6612        if (b_alias) b = c;
6613        *cc = c;
6614
6615        for (i = 1; i <= sm; i ++)
6616                c[i] = a[i] ^ b[i];
6617
6618        if (sa > sb)
6619                for (;i <= la; i++) c[i] = a[i];
6620        else
6621                for (;i <= la; i++) c[i] = b[i];
6622
6623        while ((la > 1) && (!(c[la])))
6624                la --;
6625        c[0] = la;
6626}
6627
6628void
6629_ntl_zor(
6630        _ntl_verylong a,
6631        _ntl_verylong b,
6632        _ntl_verylong *cc
6633        )
6634{
6635        _ntl_verylong c;
6636        long sa;
6637        long sb;
6638        long sm;
6639        long la;
6640        long i;
6641        long a_alias;
6642        long b_alias;
6643
6644        if (_ntl_ziszero(a)) {
6645                _ntl_zcopy(b,cc);
6646                _ntl_zabs(cc);
6647                return;
6648        }
6649
6650        if (_ntl_ziszero(b)) {
6651                _ntl_zcopy(a,cc);
6652                _ntl_zabs(cc);
6653                return;
6654        }
6655
6656        c = *cc;
6657        a_alias = (a == c);
6658        b_alias = (b == c);
6659
6660        sa = a[0];
6661        if (sa < 0) sa = -sa;
6662
6663        sb = b[0];
6664        if (sb < 0) sb = -sb;
6665
6666        if (sa > sb) {
6667                la = sa;
6668                sm = sb;
6669        } else {
6670                la = sb;
6671                sm = sa;
6672        }
6673
6674        _ntl_zsetlength(&c, la);
6675        if (a_alias) a = c;
6676        if (b_alias) b = c;
6677        *cc = c;
6678
6679        for (i = 1; i <= sm; i ++)
6680                c[i] = a[i] | b[i];
6681
6682        if (sa > sb)
6683                for (;i <= la; i++) c[i] = a[i];
6684        else
6685                for (;i <= la; i++) c[i] = b[i];
6686
6687        c[0] = la;
6688}
6689
6690long
6691_ntl_zsetbit(
6692        _ntl_verylong *a,
6693        long b
6694        )
6695{
6696        long bl;
6697        long wh;
6698        long sa;
6699
6700        if (b<0) zhalt("_ntl_zsetbit: negative index");
6701
6702        if (_ntl_ziszero(*a)) {
6703                _ntl_zintoz(1,a);
6704                _ntl_zlshift(*a,b,a);
6705                return (0);
6706        }
6707
6708        bl = (b/NTL_NBITS);
6709        wh = 1L << (b - NTL_NBITS*bl);
6710        bl ++;
6711        sa = (*a)[0];
6712        if (sa<0) sa = -sa;
6713        if (sa >= bl) {
6714                sa = (*a)[bl] & wh;
6715                (*a)[bl] |= wh;
6716                if (sa) return (1);
6717                return (0);
6718        } else {
6719                _ntl_zsetlength(a,bl);
6720                sa ++;
6721                for (;sa<=bl;sa++) (*a)[sa]=0;
6722                if ((*a)[0] < 0)
6723                        (*a)[0] = -bl;
6724                else (*a)[0] = bl;
6725                (*a)[bl] |= wh;
6726                return (0);
6727        }
6728}
6729
6730long
6731_ntl_zswitchbit(
6732        _ntl_verylong *a,
6733        long p
6734        )
6735{
6736        long bl;
6737        long wh;
6738        long sa;
6739
6740        if (p < 0) zhalt("_ntl_zswitchbit: negative index");
6741
6742        if (_ntl_ziszero(*a)) {
6743                _ntl_zintoz(1,a);
6744                _ntl_zlshift(*a,p,a);
6745                return (0);
6746        }
6747
6748        bl = (p/NTL_NBITS);
6749        wh = 1L << (p - NTL_NBITS*bl);
6750        bl ++;
6751        sa = (*a)[0];
6752        if (sa < 0) sa = -sa;
6753        if ((sa < bl) || (!((*a)[bl] & wh))) {
6754                _ntl_zsetbit(a,p);
6755                return (0);
6756        }
6757        (*a)[bl] ^= wh;
6758        while ((sa>1) && (!(*a)[sa]))
6759                sa --;
6760        if ((*a)[0] > 0) (*a)[0] = sa;
6761        else (*a)[0] = -sa;
6762        return (1);
6763}
6764
6765
6766long _ntl_zsize(_ntl_verylong rep)
6767{
6768   if (!rep || (rep[0] == 1 && rep[1] == 0))
6769      return 0;
6770   else if (rep[0] < 0)
6771      return -rep[0];
6772   else
6773      return rep[0];
6774}
6775
6776
6777long _ntl_zdigit(_ntl_verylong rep, long i) 
6778{
6779   long sa;
6780   if (i < 0 || !rep) return 0;
6781
6782   sa = rep[0];
6783   if (sa < 0) sa = -sa;
6784   if (i >= sa) return 0;
6785   return rep[i+1];
6786}
6787
6788long _ntl_zisone(_ntl_verylong rep)