source: git/ntl/src/g_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: 97.1 KB
Line 
1
2/*
3 * This is a "wrapper" layer that builds on top of the "mpn" layer of gmp.
4 * This layer provides much of the same functionality of the "mpz"
5 * layer of gmp, but the interface it provides is much more like
6 * the interface provided by lip.
7 *
8 * This layer was written under the following assumptions about gmp:
9 *  1) mp_limb_t is an unsigned integral type
10 *  2) sizeof(mp_limb_t) == sizeof(long) or sizeof(mp_limb_t) == 2*sizeof(long)
11 *  3) the number of bits of an mp_limb_t is equal to that of a long,
12 *     or twice that of a long
13 *  4) the number of bits of a gmp radix is equal to the number of bits
14 *     of an mp_limb_t
15 *
16 * Except for assumption (1), these assumptions are verified in the
17 * installation script, and they should be universally satisfied in practice,
18 * except when gmp is built using the proposed, new "nail" fetaure
19 * (in which some bits of an mp_limb_t are unused).
20 * The code here will not work properly with the "nail" feature;
21 * however, I have (attempted to) identify all such problem spots,
22 * and any other places where assumptions (2-4) are made,
23 * with a comment labeled "DIRT".
24 */
25
26
27
28#include <NTL/lip.h>
29
30#include <NTL/ctools.h>
31
32
33#include <stdlib.h>
34#include <stdio.h>
35#include <math.h>
36
37
38#include <gmp.h>
39
40typedef mp_limb_t *_ntl_limb_t_ptr;
41
42int _ntl_gmp_hack = 0;
43
44#if (__GNU_MP_VERSION < 3)
45
46#error "You have to use GNP version >= 3.1"
47
48#endif
49
50#if ((__GNU_MP_VERSION == 3) && (__GNU_MP_VERSION_MINOR < 1))
51
52#error "You have to use GNP version >= 3.1"
53
54#endif
55
56
57
58/* v 3.1 is supposed  mpn_tdiv_qr defined, but it doesn't.
59   Here's a workaround */
60
61#if ((__GNU_MP_VERSION == 3) && (__GNU_MP_VERSION_MINOR == 1) && (__GNU_MP_VERSION_PATCHLEVEL == 0))
62
63#define mpn_tdiv_qr __MPN(tdiv_qr)
64
65
66#ifdef __cplusplus
67extern "C" 
68#endif
69void mpn_tdiv_qr(mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, 
70                 mp_srcptr, mp_size_t);
71
72#endif
73
74
75#if (defined(NTL_CXX_ONLY) && !defined(__cplusplus))
76#error "CXX_ONLY flag set...must use C++ compiler"
77#endif
78
79
80union gbigint_header {
81
82   long info[2];
83   mp_limb_t alignment;
84
85};
86
87/* A bigint is represented as two long's, ALLOC and SIZE, followed by a
88 * vector DATA of mp_limb_t's. 
89 *
90 * ALLOC is of the form
91 *    (alloc << 2) | continue_flag | frozen_flag
92 * where
93 *    - alloc is the number of allocated mp_limb_t's,
94 *    - continue flag is either 2 or 0,
95 *    - frozen_flag is either 1 or 0.
96 * If frozen_flag is set, then the space for this bigint is *not*
97 * managed by the _ntl_gsetlength and _ntl_gfree routines,
98 * but are instead managed by the vec_ZZ_p and ZZVec routines.
99 * The continue_flag is only set when the frozen_flag is set.
100 *
101 * SIZE is the number of mp_limb_t's actually
102 * used by the bigint, with the sign of SIZE having
103 * the sign of the bigint.
104 * Note that the zero bigint is represented as SIZE=0.
105 *
106 * Bigint's are accessed through a handle, which is pointer to void.
107 * A null handle logically represents the bigint zero.
108 * This is done so that the interface presented to higher level
109 * routines is essentially the same as that of NTL's traditional
110 * long integer package.
111 *
112 * The components ALLOC, SIZE, and DATA are all accessed through
113 * macros using pointer casts.  While all of may seem a bit dirty,
114 * it should be quite portable: objects are never referenced
115 * through pointers of different types, and no alignmement
116 * problems should arise.
117 *
118 * Actually, mp_limb_t is usually the type unsigned long.
119 * However, on some 64-bit platforms, the type long is only 32 bits,
120 * and gmp makes mp_limb_t unsigned long long in this case.
121 * This is fairly rare, as the industry standard for Unix is to
122 * have 64-bit longs on 64-bit machines.
123 */ 
124
125#if 1
126
127#define ALLOC(p) (((long *) (p))[0])
128#define SIZE(p) (((long *) (p))[1])
129#define DATA(p) ((mp_limb_t *) (((long *) (p)) + 2))
130
131#define STORAGE(len) ((long)(2*sizeof(long) + (len)*sizeof(mp_limb_t)))
132
133/* DIRT: STORAGE computes the number of bytes to allocate for a bigint
134 * of maximal SIZE len.  This should be computed so that one
135 * can store several such bigints in a contiguous array
136 * of memory without breaking any alignment requirements.
137 * Currently, it is assumed (and explicitly checked in the NTL installation
138 * script) that sizeof(mp_limb_t) is either sizeof(long) or
139 * 2*sizeof(long), and therfore, nothing special needs to
140 * be done to enfoce alignment requirements.  If this assumption
141 * should change, then the storage layout for bigints must be
142 * re-designed.   
143 */
144
145#define MustAlloc(c, len)  (!(c) || (ALLOC(c) >> 2) < (len))
146
147
148
149#define GET_SIZE_NEG(sz, neg, p)  \
150do  \
151{   \
152   long _s;   \
153   _s = SIZE(p);   \
154   if (_s < 0) {  \
155      sz = -_s;  \
156      neg = 1;  \
157   }  \
158   else {  \
159      sz = _s;  \
160      neg = 0;  \
161   }  \
162}  \
163while (0)
164
165#define STRIP(sz, p)  \
166do  \
167{  \
168   long _i;  \
169   _i = sz - 1;  \
170   while (_i >= 0 && p[_i] == 0) _i--;  \
171   sz = _i + 1;  \
172}  \
173while (0)
174
175#define ZEROP(p) (!p || !SIZE(p))
176
177#define ONEP(p) (p && SIZE(p) == 1 && DATA(p)[0] == 1)
178
179#define SWAP_BIGINT(a, b)  \
180do  \
181{  \
182   _ntl_gbigint _t;  \
183   _t = a;  \
184   a = b;  \
185   b = _t;  \
186}  \
187while (0)
188
189#define SWAP_LONG(a, b)  \
190do  \
191{  \
192   long _t;  \
193   _t = a;  \
194   a = b;  \
195   b = _t;  \
196}  \
197while (0)
198
199#define SWAP_LIMB_PTR(a, b)  \
200do  \
201{  \
202   _ntl_limb_t_ptr _t;  \
203   _t = a;  \
204   a = b;  \
205   b = _t;  \
206}  \
207while (0)
208
209#define COUNT_BITS(cnt, a)  \
210do  \
211{  \
212   long _i = 0;  \
213   mp_limb_t _a = (a);  \
214  \
215   while (_a>=256)  \
216      _i += 8, _a >>= 8;  \
217   if (_a >=16)  \
218      _i += 4, _a >>= 4;  \
219   if (_a >= 4)  \
220      _i += 2, _a >>= 2;  \
221   if (_a >= 2)  \
222      _i += 2;  \
223   else if (_a >= 1)  \
224      _i++;  \
225  \
226   cnt = _i;  \
227}  \
228while (0)
229
230#else
231
232/* These are C++ inline functions that are equivalent to the above
233 * macros.  They are mainly intended as a debugging aid.
234 */
235
236
237inline long& ALLOC(_ntl_gbigint p) 
238   { return (((long *) p)[0]); }
239
240inline long& SIZE(_ntl_gbigint p) 
241   { return (((long *) p)[1]); }
242
243inline mp_limb_t * DATA(_ntl_gbigint p) 
244   { return ((mp_limb_t *) (((long *) (p)) + 2)); }
245
246inline long STORAGE(long len)
247   { return ((long)(2*sizeof(long) + (len)*sizeof(mp_limb_t))); }
248
249inline long MustAlloc(_ntl_gbigint c, long len) 
250   { return (!(c) || (ALLOC(c) >> 2) < (len)); }
251
252
253inline void GET_SIZE_NEG(long& sz, long& neg, _ntl_gbigint p)
254{ 
255   long s; 
256   s = SIZE(p); 
257   if (s < 0) {
258      sz = -s;
259      neg = 1;
260   }
261   else {
262      sz = s;
263      neg = 0;
264   }
265}
266
267inline void STRIP(long& sz, mp_limb_t *p)
268{
269   long i;
270   i = sz - 1;
271   while (i >= 0 && p[i] == 0) i--;
272   sz = i + 1;
273}
274
275inline long ZEROP(_ntl_gbigint p)
276{
277   return !p || !SIZE(p);
278}
279
280inline long ONEP(_ntl_gbigint p)
281{
282   return p && SIZE(p) == 1 && DATA(p)[0] == 1;
283}
284
285inline void SWAP_BIGINT(_ntl_gbigint& a, _ntl_gbigint& b)
286{
287   _ntl_gbigint t;
288   t = a;
289   a = b;
290   b = t;
291}
292
293inline void SWAP_LONG(long& a, long& b)
294{
295   long t;
296   t = a;
297   a = b;
298   b = t;
299}
300
301inline void SWAP_LIMB_PTR(_ntl_limb_t_ptr& a, _ntl_limb_t_ptr& b)
302{
303   _ntl_limb_t_ptr t;
304   t = a;
305   a = b;
306   b = t;
307}
308
309
310inline void COUNT_BITS(long& cnt, mp_limb_t a)
311{
312   long i = 0;
313
314   while (a>=256)
315      i += 8, a >>= 8;
316   if (a >=16)
317      i += 4, a >>= 4;
318   if (a >= 4)
319      i += 2, a >>= 2;
320   if (a >= 2)
321      i += 2;
322   else if (a >= 1)
323      i++;
324
325   cnt = i;
326}
327
328#endif
329
330#define STORAGE_OVF(len) NTL_OVERFLOW(len, sizeof(mp_limb_t), 2*sizeof(long))
331
332
333/* ForceNormal ensures a normalized bigint */
334
335static 
336void ForceNormal(_ntl_gbigint x)
337{
338   long sx, xneg;
339   mp_limb_t *xdata;
340
341   if (!x) return;
342   GET_SIZE_NEG(sx, xneg, x);
343   xdata = DATA(x);
344   STRIP(sx, xdata);
345   if (xneg) sx = -sx;
346   SIZE(x) = sx;
347}
348
349
350static 
351void ghalt(char *c)
352{
353   fprintf(stderr,"fatal error:\n   %s\nexit...\n",c);
354   fflush(stderr);
355   _ntl_abort();
356}
357
358
359#define MIN_SETL        (4)
360   /* _ntl_gsetlength allocates a multiple of MIN_SETL digits */
361
362
363
364void _ntl_gsetlength(_ntl_gbigint *v, long len)
365{
366   _ntl_gbigint x = *v;
367
368   if (len < 0)
369      ghalt("negative size allocation in _ntl_zgetlength");
370
371   if (NTL_OVERFLOW(len, NTL_ZZ_NBITS, 0))
372      ghalt("size too big in _ntl_gsetlength");
373
374#ifdef NTL_SMALL_MP_SIZE_T
375   /* this makes sure that numbers don't get too big for GMP */
376   if (len >= (1L << (NTL_BITS_PER_INT-4)))
377      ghalt("size too big for GMP");
378#endif
379
380
381   if (x) {
382      long oldlen = ALLOC(x);
383      long fixed = oldlen & 1;
384      oldlen = oldlen >> 2;
385
386      if (fixed) {
387         if (len > oldlen) 
388            ghalt("internal error: can't grow this _ntl_gbigint");
389         else
390            return;
391      }
392
393      if (len <= oldlen) return;
394
395      len++;  /* always allocate at least one more than requested */
396
397      oldlen = (long) (oldlen * 1.2); /* always increase by at least 20% */
398      if (len < oldlen)
399         len = oldlen;
400
401      /* round up to multiple of MIN_SETL */
402      len = ((len+(MIN_SETL-1))/MIN_SETL)*MIN_SETL; 
403
404      /* test len again */
405      if (NTL_OVERFLOW(len, NTL_ZZ_NBITS, 0))
406         ghalt("size too big in _ntl_gsetlength");
407
408      if (STORAGE_OVF(len))
409         ghalt("reallocation failed in _ntl_gsetlength");
410
411      ALLOC(x) = len << 2;
412      if (!(x = (_ntl_gbigint)NTL_REALLOC((void *) x, 1, STORAGE(len), 0))) {
413         ghalt("reallocation failed in _ntl_gsetlength");
414      }
415   }
416   else {
417      len++;
418      len = ((len+(MIN_SETL-1))/MIN_SETL)*MIN_SETL;
419
420      /* test len again */
421      if (NTL_OVERFLOW(len, NTL_ZZ_NBITS, 0))
422         ghalt("size too big in _ntl_gsetlength");
423
424      if (STORAGE_OVF(len))
425         ghalt("reallocation failed in _ntl_gsetlength");
426
427      if (!(x = (_ntl_gbigint)NTL_MALLOC(1, STORAGE(len), 0))) {
428         ghalt("allocation failed in _ntl_gsetlength");
429      }
430      ALLOC(x) = len << 2;
431      SIZE(x) = 0;
432   }
433
434   *v = x;
435}
436
437void _ntl_gfree(_ntl_gbigint *xx)
438{
439   _ntl_gbigint x = *xx;
440
441   if (!x)
442      return;
443
444   if (ALLOC(x) & 1)
445      ghalt("Internal error: can't free this _ntl_gbigint");
446
447   free((void*) x);
448   *xx = 0;
449   return;
450}
451
452void
453_ntl_gswap(_ntl_gbigint *a, _ntl_gbigint *b)
454{
455   _ntl_gbigint c;
456
457   if ((*a && (ALLOC(*a) & 1)) || (*b && (ALLOC(*b) & 1))) {
458      static _ntl_gbigint t = 0; 
459      _ntl_gcopy(*a, &t);
460      _ntl_gcopy(*b, a);
461      _ntl_gcopy(t, b);
462      return;
463   }
464
465   c = *a;
466   *a = *b;
467   *b = c;
468}
469
470
471void _ntl_gcopy(_ntl_gbigint a, _ntl_gbigint *bb)
472{
473   _ntl_gbigint b;
474   long sa, abs_sa, i;
475   mp_limb_t *adata, *bdata;
476
477   b = *bb;
478
479   if (!a || (sa = SIZE(a)) == 0) {
480      if (b) SIZE(b) = 0;
481   }
482   else {
483      if (a != b) {
484         if (sa >= 0)
485            abs_sa = sa;
486         else
487            abs_sa = -sa;
488
489         if (MustAlloc(b, abs_sa)) {
490            _ntl_gsetlength(&b, abs_sa);
491            *bb = b;
492         }
493
494         adata = DATA(a);
495         bdata = DATA(b);
496
497         for (i = 0; i < abs_sa; i++)
498            bdata[i] = adata[i];
499
500         SIZE(b) = sa;
501      }
502   }
503}
504
505
506void _ntl_gzero(_ntl_gbigint *aa) 
507{
508   _ntl_gbigint a = *aa;
509
510   if (a) SIZE(a) = 0;
511}
512
513void _ntl_gone(_ntl_gbigint *aa)
514{
515   _ntl_gbigint a = *aa;
516   if (!a) {
517      _ntl_gsetlength(&a, 1);
518      *aa = a;
519   }
520
521   SIZE(a) = 1;
522   DATA(a)[0] = 1;
523}
524
525long _ntl_giszero(_ntl_gbigint a)
526{
527   return ZEROP(a);
528}
529
530long _ntl_godd(_ntl_gbigint a)
531{
532   if (ZEROP(a)) 
533      return 0;
534   else
535      return DATA(a)[0]&1;
536}
537
538long _ntl_gbit(_ntl_gbigint a, long p)
539{
540   long bl;
541   long sa;
542   mp_limb_t wh;
543
544   if (p < 0 || !a) return 0;
545
546   bl = p/NTL_ZZ_NBITS;
547   wh = ((mp_limb_t) 1) << (p - NTL_ZZ_NBITS*bl);
548
549   sa = SIZE(a);
550   if (sa < 0) sa = -sa;
551
552   if (sa <= bl) return 0;
553   if (DATA(a)[bl] & wh) return 1;
554   return 0;
555}
556
557void _ntl_glowbits(_ntl_gbigint a, long b, _ntl_gbigint *cc)
558{
559   _ntl_gbigint c;
560
561   long bl;
562   long wh;
563   long sa;
564   long i;
565   mp_limb_t *adata, *cdata;
566
567   if (ZEROP(a) || (b<=0)) {
568      _ntl_gzero(cc);
569      return;
570   }
571
572   bl = b/NTL_ZZ_NBITS;
573   wh = b - NTL_ZZ_NBITS*bl;
574   if (wh != 0) 
575      bl++;
576   else
577      wh = NTL_ZZ_NBITS;
578
579   sa = SIZE(a);
580   if (sa < 0) sa = -sa;
581
582   if (sa < bl) {
583      _ntl_gcopy(a,cc);
584      _ntl_gabs(cc);
585      return;
586   }
587
588   c = *cc;
589
590   /* a won't move if c aliases a */
591   _ntl_gsetlength(&c, bl);
592   *cc = c;
593
594   adata = DATA(a);
595   cdata = DATA(c);
596
597   for (i = 0; i < bl-1; i++)
598      cdata[i] = adata[i];
599
600   if (wh == NTL_ZZ_NBITS)
601      cdata[bl-1] = adata[bl-1];
602   else
603      cdata[bl-1] = adata[bl-1] & ((((mp_limb_t) 1) << wh) - ((mp_limb_t) 1));
604
605   STRIP(bl, cdata);
606   SIZE(c) = bl; 
607}
608
609long _ntl_gslowbits(_ntl_gbigint a, long p)
610{
611   static _ntl_gbigint x = 0;
612
613   if (p > NTL_BITS_PER_LONG)
614      p = NTL_BITS_PER_LONG;
615
616   _ntl_glowbits(a, p, &x);
617
618   return _ntl_gtoint(x);
619}
620
621long _ntl_gsetbit(_ntl_gbigint *a, long b)
622{
623   long bl;
624   long sa, aneg;
625   long i;
626   mp_limb_t wh, *adata, tmp;
627
628   if (b<0) ghalt("_ntl_gsetbit: negative index");
629
630   if (ZEROP(*a)) {
631      _ntl_gintoz(1, a);
632      _ntl_glshift(*a, b, a);
633      return 0;
634   }
635
636   bl = (b/NTL_ZZ_NBITS);
637   wh = ((mp_limb_t) 1) << (b - NTL_ZZ_NBITS*bl);
638
639   GET_SIZE_NEG(sa, aneg, *a);
640
641   if (sa > bl) {
642      adata = DATA(*a);
643      tmp = adata[bl] & wh;
644      adata[bl] |= wh;
645      if (tmp) return 1;
646      return 0;
647   } 
648   else {
649      _ntl_gsetlength(a, bl+1);
650      adata = DATA(*a);
651      for (i = sa; i < bl; i++)
652         adata[i] = 0;
653      adata[bl] = wh;
654
655      sa = bl+1;
656      if (aneg) sa = -sa;
657      SIZE(*a) = sa;
658      return 0;
659   }
660}
661
662long _ntl_gswitchbit(_ntl_gbigint *a, long b)
663{
664   long bl;
665   long sa, aneg;
666   long i;
667   mp_limb_t wh, *adata, tmp;
668
669   if (b<0) ghalt("_ntl_gswitchbit: negative index");
670
671
672   if (ZEROP(*a)) {
673      _ntl_gintoz(1, a);
674      _ntl_glshift(*a, b, a);
675      return 0;
676   }
677
678   bl = (b/NTL_ZZ_NBITS);
679   wh = ((mp_limb_t) 1) << (b - NTL_ZZ_NBITS*bl);
680
681   GET_SIZE_NEG(sa, aneg, *a);
682
683   if (sa > bl) {
684      adata = DATA(*a);
685      tmp = adata[bl] & wh;
686      adata[bl] ^= wh;
687
688      if (bl == sa-1) {
689         STRIP(sa, adata);
690         if (aneg) sa = -sa;
691         SIZE(*a) = sa;
692      }
693
694      if (tmp) return 1;
695      return 0;
696   } 
697   else {
698      _ntl_gsetlength(a, bl+1);
699      adata = DATA(*a);
700      for (i = sa; i < bl; i++)
701         adata[i] = 0;
702      adata[bl] = wh;
703
704      sa = bl+1;
705      if (aneg) sa = -sa;
706      SIZE(*a) = sa;
707      return 0;
708   }
709}
710
711long
712_ntl_gweights(
713        long aa
714        )
715{
716        unsigned long a;
717        long res = 0;
718        if (aa < 0) 
719                a = -((unsigned long) aa);
720        else
721                a = aa;
722   
723        while (a) {
724                if (a & 1) res ++;
725                a >>= 1;
726        }
727        return (res);
728}
729
730static long
731gweights_mp_limb(
732        mp_limb_t a
733        )
734{
735        long res = 0;
736   
737        while (a) {
738                if (a & 1) res ++;
739                a >>= 1;
740        }
741        return (res);
742}
743
744long
745_ntl_gweight(
746        _ntl_gbigint a
747        )
748{
749        long i;
750        long sa;
751        mp_limb_t *adata;
752        long res;
753
754        if (!a) return (0);
755
756        sa = SIZE(a);
757        if (sa < 0) sa = -sa;
758        adata = DATA(a);
759
760        res = 0;
761        for (i = 0; i < sa; i++)
762                res += gweights_mp_limb(adata[i]);
763
764        return (res);
765}
766
767long 
768_ntl_g2logs(
769        long aa
770        )
771{
772        long i = 0;
773        unsigned long a;
774
775        if (aa < 0)
776                a = - ((unsigned long) aa);
777        else
778                a = aa;
779
780        while (a>=256)
781                i += 8, a >>= 8;
782        if (a >=16)
783                i += 4, a >>= 4;
784        if (a >= 4)
785                i += 2, a >>= 2;
786        if (a >= 2)
787                i += 2;
788        else if (a >= 1)
789                i++;
790        return (i);
791}
792
793long _ntl_g2log(_ntl_gbigint a)
794{
795   long la;
796   long t;
797
798   if (!a) return 0;
799   la = SIZE(a);
800   if (la == 0) return 0;
801   if (la < 0) la = -la;
802   COUNT_BITS(t, DATA(a)[la-1]);
803   return NTL_ZZ_NBITS*(la - 1) + t;
804}
805
806
807
808long _ntl_gmakeodd(_ntl_gbigint *nn)
809{
810   _ntl_gbigint n = *nn;
811   long shift;
812   mp_limb_t *ndata;
813   mp_limb_t i;
814
815   if (ZEROP(n))
816      return (0);
817
818   shift = 0;
819   ndata = DATA(n);
820
821   while (ndata[shift] == 0)
822      shift++;
823
824   i = ndata[shift];
825
826   shift = NTL_ZZ_NBITS * shift;
827
828   while ((i & 1) == 0) {
829      shift++;
830      i >>= 1;
831   }
832   _ntl_grshift(n, shift, &n);
833   return shift;
834}
835
836
837long _ntl_gnumtwos(_ntl_gbigint n)
838{
839   long shift;
840   mp_limb_t *ndata;
841   mp_limb_t i;
842
843   if (ZEROP(n))
844      return (0);
845
846   shift = 0;
847   ndata = DATA(n);
848
849   while (ndata[shift] == 0)
850      shift++;
851
852   i = ndata[shift];
853
854   shift = NTL_ZZ_NBITS * shift;
855
856   while ((i & 1) == 0) {
857      shift++;
858      i >>= 1;
859   }
860
861   return shift;
862}
863
864
865void _ntl_gand(_ntl_gbigint a, _ntl_gbigint b, _ntl_gbigint *cc)
866{
867   _ntl_gbigint c;
868   long sa;
869   long sb;
870   long sm;
871   long i;
872   long a_alias, b_alias;
873   mp_limb_t *adata, *bdata, *cdata;
874
875   if (ZEROP(a) || ZEROP(b)) {
876      _ntl_gzero(cc);
877      return;
878   }
879
880   c = *cc;
881   a_alias = (a == c);
882   b_alias = (b == c);
883
884   sa = SIZE(a);
885   if (sa < 0) sa = -sa;
886
887   sb = SIZE(b);
888   if (sb < 0) sb = -sb;
889
890   sm = (sa > sb ? sb : sa);
891
892   _ntl_gsetlength(&c, sm);
893   if (a_alias) a = c;
894   if (b_alias) b = c;
895   *cc = c;
896
897   adata = DATA(a);
898   bdata = DATA(b);
899   cdata = DATA(c);
900
901   for (i = 0; i < sm; i++)
902      cdata[i] = adata[i] & bdata[i];
903
904   STRIP(sm, cdata);
905   SIZE(c) = sm;
906}
907
908
909void _ntl_gxor(_ntl_gbigint a, _ntl_gbigint b, _ntl_gbigint *cc)
910{
911   _ntl_gbigint c;
912   long sa;
913   long sb;
914   long sm;
915   long la;
916   long i;
917   long a_alias, b_alias;
918   mp_limb_t *adata, *bdata, *cdata;
919
920   if (ZEROP(a)) {
921      _ntl_gcopy(b,cc);
922      _ntl_gabs(cc);
923      return;
924   }
925
926   if (ZEROP(b)) {
927      _ntl_gcopy(a,cc);
928      _ntl_gabs(cc);
929      return;
930   }
931
932   c = *cc;
933   a_alias = (a == c);
934   b_alias = (b == c);
935
936   sa = SIZE(a);
937   if (sa < 0) sa = -sa;
938
939   sb = SIZE(b);
940   if (sb < 0) sb = -sb;
941
942   if (sa > sb) {
943      la = sa;
944      sm = sb;
945   } 
946   else {
947      la = sb;
948      sm = sa;
949   }
950
951   _ntl_gsetlength(&c, la);
952   if (a_alias) a = c;
953   if (b_alias) b = c;
954   *cc = c;
955
956   adata = DATA(a);
957   bdata = DATA(b);
958   cdata = DATA(c);
959
960   for (i = 0; i < sm; i ++)
961      cdata[i] = adata[i] ^ bdata[i];
962
963   if (sa > sb)
964      for (;i < la; i++) cdata[i] = adata[i];
965   else
966      for (;i < la; i++) cdata[i] = bdata[i];
967
968   STRIP(la, cdata);
969   SIZE(c) = la;
970}
971
972
973void _ntl_gor(_ntl_gbigint a, _ntl_gbigint b, _ntl_gbigint *cc)
974{
975   _ntl_gbigint c;
976   long sa;
977   long sb;
978   long sm;
979   long la;
980   long i;
981   long a_alias, b_alias;
982   mp_limb_t *adata, *bdata, *cdata;
983
984   if (ZEROP(a)) {
985      _ntl_gcopy(b,cc);
986      _ntl_gabs(cc);
987      return;
988   }
989
990   if (ZEROP(b)) {
991      _ntl_gcopy(a,cc);
992      _ntl_gabs(cc);
993      return;
994   }
995
996   c = *cc;
997   a_alias = (a == c);
998   b_alias = (b == c);
999
1000   sa = SIZE(a);
1001   if (sa < 0) sa = -sa;
1002
1003   sb = SIZE(b);
1004   if (sb < 0) sb = -sb;
1005
1006   if (sa > sb) {
1007      la = sa;
1008      sm = sb;
1009   } 
1010   else {
1011      la = sb;
1012      sm = sa;
1013   }
1014
1015   _ntl_gsetlength(&c, la);
1016   if (a_alias) a = c;
1017   if (b_alias) b = c;
1018   *cc = c;
1019
1020   adata = DATA(a);
1021   bdata = DATA(b);
1022   cdata = DATA(c);
1023
1024   for (i = 0; i < sm; i ++)
1025      cdata[i] = adata[i] | bdata[i];
1026
1027   if (sa > sb)
1028      for (;i < la; i++) cdata[i] = adata[i];
1029   else
1030      for (;i < la; i++) cdata[i] = bdata[i];
1031
1032   STRIP(la, cdata);
1033   SIZE(c) = la;
1034}
1035
1036
1037void _ntl_gnegate(_ntl_gbigint *aa)
1038{
1039   _ntl_gbigint a = *aa;
1040   if (a) SIZE(a) = -SIZE(a);
1041}
1042
1043
1044/*
1045 * DIRT: this implementation of _ntl_gintoz relies crucially
1046 * on the assumption that the number of bits per limb_t is at least
1047 * equal to the number of bits per long.
1048 */
1049
1050void _ntl_gintoz(long d, _ntl_gbigint *aa)
1051{
1052   _ntl_gbigint a = *aa;
1053
1054   if (d == 0) {
1055      if (a) SIZE(a) = 0;
1056   }
1057   else if (d > 0) {
1058      if (!a) {
1059         _ntl_gsetlength(&a, 1);
1060         *aa = a;
1061      }
1062   
1063      SIZE(a) = 1;
1064      DATA(a)[0] = d;
1065   }
1066   else {
1067      if (!a) {
1068         _ntl_gsetlength(&a, 1);
1069         *aa = a;
1070      }
1071   
1072      SIZE(a) = -1;
1073      DATA(a)[0] = -((mp_limb_t) d); /* careful! */
1074   }
1075}
1076
1077
1078/*
1079 * DIRT: this implementation of _ntl_guintoz relies crucially
1080 * on the assumption that the number of bits per limb_t is at least
1081 * equal to the number of bits per long.
1082 */
1083
1084void _ntl_guintoz(unsigned long d, _ntl_gbigint *aa)
1085{
1086   _ntl_gbigint a = *aa;
1087
1088   if (d == 0) {
1089      if (a) SIZE(a) = 0;
1090   }
1091   else {
1092      if (!a) {
1093         _ntl_gsetlength(&a, 1);
1094         *aa = a;
1095      }
1096   
1097      SIZE(a) = 1;
1098      DATA(a)[0] = d;
1099   }
1100}
1101
1102
1103long _ntl_gtoint(_ntl_gbigint a)
1104{
1105   unsigned long res = _ntl_gtouint(a);
1106   return NTL_ULONG_TO_LONG(res);
1107}
1108
1109/*
1110 * DIRT: this implementation of _ntl_gtouint relies crucially
1111 * on the assumption that the number of bits per limb_t is at least
1112 * equal to the number of bits per long.
1113 */
1114
1115unsigned long _ntl_gtouint(_ntl_gbigint a)
1116{
1117   if (ZEROP(a)) 
1118      return 0;
1119
1120   if (SIZE(a) > 0) 
1121      return DATA(a)[0];
1122
1123   return -DATA(a)[0];
1124}
1125
1126
1127long _ntl_gcompare(_ntl_gbigint a, _ntl_gbigint b)
1128{
1129   long sa, sb, cmp;
1130   mp_limb_t *adata, *bdata;
1131
1132   if (!a) 
1133      sa = 0;
1134   else
1135      sa = SIZE(a);
1136
1137   if (!b) 
1138      sb = 0;
1139   else
1140      sb = SIZE(b);
1141
1142   if (sa != sb) {
1143      if (sa > sb)
1144         return 1;
1145      else
1146         return -1;
1147   }
1148
1149   if (sa == 0)
1150      return 0;
1151
1152   adata = DATA(a);
1153   bdata = DATA(b);
1154
1155   if (sa > 0) {
1156      cmp = mpn_cmp(adata, bdata, sa);
1157
1158      if (cmp > 0)
1159         return 1;
1160      else if (cmp < 0) 
1161         return -1;
1162      else
1163         return 0;
1164   }
1165   else {
1166      cmp = mpn_cmp(adata, bdata, -sa);
1167
1168      if (cmp > 0)
1169         return -1;
1170      else if (cmp < 0) 
1171         return 1;
1172      else
1173         return 0;
1174   }
1175}
1176
1177
1178long _ntl_gsign(_ntl_gbigint a)
1179{
1180   long sa;
1181
1182   if (!a) return 0;
1183
1184   sa = SIZE(a);
1185   if (sa > 0) return 1;
1186   if (sa == 0) return 0;
1187   return -1;
1188}
1189
1190void _ntl_gabs(_ntl_gbigint *pa)
1191{
1192   _ntl_gbigint a = *pa;
1193
1194   if (!a) return;
1195   if (SIZE(a) < 0) SIZE(a) = -SIZE(a);
1196}
1197
1198long _ntl_gscompare(_ntl_gbigint a, long b)
1199{
1200   if (b == 0) {
1201      long sa;
1202      if (!a) return 0;
1203      sa = SIZE(a);
1204      if (sa > 0) return 1;
1205      if (sa == 0) return 0;
1206      return -1;
1207   }
1208   else {
1209      static _ntl_gbigint B = 0;
1210      _ntl_gintoz(b, &B);
1211      return _ntl_gcompare(a, B);
1212   }
1213}
1214
1215
1216void _ntl_glshift(_ntl_gbigint n, long k, _ntl_gbigint *rres)
1217{
1218   _ntl_gbigint res;
1219   mp_limb_t *ndata, *resdata, *resdata1;
1220   long limb_cnt, i, sn, nneg, sres;
1221   long n_alias;
1222
1223   if (ZEROP(n)) {
1224      _ntl_gzero(rres);
1225      return;
1226   }
1227
1228   res = *rres;
1229   n_alias = (n == res);
1230
1231   if (!k) {
1232      if (!n_alias)
1233         _ntl_gcopy(n, rres);
1234      return;
1235   }
1236
1237   if (k < 0) {
1238      if (k < -NTL_MAX_LONG) 
1239         _ntl_gzero(rres);
1240      else
1241         _ntl_grshift(n, -k, rres);
1242      return;
1243   }
1244
1245   GET_SIZE_NEG(sn, nneg, n);
1246
1247   limb_cnt = k/NTL_ZZ_NBITS;
1248   sres = sn + limb_cnt + 1; 
1249
1250   if (MustAlloc(res, sres)) {
1251      _ntl_gsetlength(&res, sres);
1252      if (n_alias) n = res;
1253      *rres = res;
1254   }
1255
1256   ndata = DATA(n);
1257   resdata = DATA(res);
1258   resdata1 = resdata + limb_cnt;
1259   k %= NTL_ZZ_NBITS;
1260   sres--;
1261
1262   if (k != 0) {
1263      mp_limb_t t = mpn_lshift(resdata1, ndata, sn, k);
1264      if (t != 0) {
1265         resdata[sres] = t;
1266         sres++;
1267      }
1268   }
1269   else {
1270      for (i = sn-1; i >= 0; i--)
1271         resdata1[i] = ndata[i];
1272   }
1273
1274   for (i = 0; i < limb_cnt; i++)
1275      resdata[i] = 0;
1276
1277   if (nneg) sres = -sres;
1278   SIZE(res) = sres;
1279}
1280
1281void _ntl_grshift(_ntl_gbigint n, long k, _ntl_gbigint *rres)
1282{
1283   _ntl_gbigint res;
1284   mp_limb_t *ndata, *resdata, *ndata1;
1285   long limb_cnt, i, sn, nneg, sres;
1286
1287   if (ZEROP(n)) {
1288      _ntl_gzero(rres);
1289      return;
1290   }
1291
1292   if (!k) {
1293      if (n != *rres)
1294         _ntl_gcopy(n, rres);
1295      return;
1296   }
1297
1298   if (k < 0) {
1299      if (k < -NTL_MAX_LONG) ghalt("overflow in _ntl_glshift");
1300      _ntl_glshift(n, -k, rres);
1301      return;
1302   }
1303
1304   GET_SIZE_NEG(sn, nneg, n);
1305
1306   limb_cnt = k/NTL_ZZ_NBITS;
1307
1308   sres = sn - limb_cnt;
1309
1310   if (sres <= 0) {
1311      _ntl_gzero(rres);
1312      return;
1313   }
1314
1315   res = *rres;
1316   if (MustAlloc(res, sres)) {
1317      /* n won't move if res aliases n */
1318      _ntl_gsetlength(&res, sres);
1319      *rres = res;
1320   }
1321
1322   ndata = DATA(n);
1323   resdata = DATA(res);
1324   ndata1 = ndata + limb_cnt;
1325   k %= NTL_ZZ_NBITS;
1326
1327   if (k != 0) {
1328      mpn_rshift(resdata, ndata1, sres, k);
1329      if (resdata[sres-1] == 0)
1330         sres--;
1331   }
1332   else {
1333      for (i = 0; i < sres; i++)
1334         resdata[i] = ndata1[i];
1335   }
1336
1337   if (nneg) sres = -sres;
1338   SIZE(res) = sres;
1339}
1340   
1341   
1342
1343void
1344_ntl_gadd(_ntl_gbigint a, _ntl_gbigint b, _ntl_gbigint *cc)
1345{
1346   long sa, aneg, sb, bneg, sc, cmp;
1347   mp_limb_t *adata, *bdata, *cdata, carry;
1348   _ntl_gbigint c;
1349   long a_alias, b_alias;
1350
1351   if (ZEROP(a)) {
1352      _ntl_gcopy(b, cc);
1353      return;
1354   }
1355
1356   if (ZEROP(b)) {
1357      _ntl_gcopy(a, cc);
1358      return;
1359   }
1360
1361   GET_SIZE_NEG(sa, aneg, a);
1362   GET_SIZE_NEG(sb, bneg, b);
1363
1364   if (sa < sb) {
1365      SWAP_BIGINT(a, b);
1366      SWAP_LONG(sa, sb);
1367      SWAP_LONG(aneg, bneg);
1368   }
1369
1370   /* sa >= sb */
1371
1372   c = *cc;
1373   a_alias = (a == c);
1374   b_alias = (b == c);
1375
1376   if (aneg == bneg) {
1377      /* same sign => addition */
1378
1379      sc = sa + 1;
1380      if (MustAlloc(c, sc)) {
1381         _ntl_gsetlength(&c, sc);
1382         if (a_alias) a = c; 
1383         if (b_alias) b = c;
1384         *cc = c;
1385      }
1386
1387      adata = DATA(a);
1388      bdata = DATA(b);
1389      cdata = DATA(c);
1390
1391      carry = mpn_add(cdata, adata, sa, bdata, sb);
1392      if (carry) 
1393         cdata[sc-1] = carry;
1394      else
1395         sc--;
1396
1397      if (aneg) sc = -sc;
1398      SIZE(c) = sc;
1399   }
1400   else {
1401      /* opposite sign => subtraction */
1402
1403      sc = sa;
1404      if (MustAlloc(c, sc)) {
1405         _ntl_gsetlength(&c, sc);
1406         if (a_alias) a = c; 
1407         if (b_alias) b = c;
1408         *cc = c;
1409      }
1410
1411      adata = DATA(a);
1412      bdata = DATA(b);
1413      cdata = DATA(c);
1414
1415      if (sa > sb) 
1416         cmp = 1;
1417      else
1418         cmp = mpn_cmp(adata, bdata, sa);
1419
1420      if (cmp == 0) {
1421         SIZE(c) = 0;
1422      }
1423      else {
1424         if (cmp < 0) cmp = 0;
1425         if (cmp > 0) cmp = 1;
1426         /* abs(a) != abs(b) && (abs(a) > abs(b) <=> cmp) */
1427
1428         if (cmp)
1429            mpn_sub(cdata, adata, sa, bdata, sb);
1430         else
1431            mpn_sub(cdata, bdata, sb, adata, sa); /* sa == sb */
1432
1433         STRIP(sc, cdata);
1434         if (aneg == cmp) sc = -sc;
1435         SIZE(c) = sc;
1436      }
1437   }
1438}
1439
1440void
1441_ntl_gsadd(_ntl_gbigint a, long b, _ntl_gbigint *cc)
1442{
1443   static _ntl_gbigint B = 0;
1444   _ntl_gintoz(b, &B);
1445   _ntl_gadd(a, B, cc);
1446}
1447
1448void
1449_ntl_gsub(_ntl_gbigint a, _ntl_gbigint b, _ntl_gbigint *cc)
1450{
1451   long sa, aneg, sb, bneg, sc, cmp, rev;
1452   mp_limb_t *adata, *bdata, *cdata, carry;
1453   _ntl_gbigint c;
1454   long a_alias, b_alias;
1455
1456   if (ZEROP(a)) {
1457      _ntl_gcopy(b, cc);
1458      c = *cc;
1459      if (c) SIZE(c) = -SIZE(c); 
1460      return;
1461   }
1462
1463   if (ZEROP(b)) {
1464      _ntl_gcopy(a, cc);
1465      return;
1466   }
1467
1468   GET_SIZE_NEG(sa, aneg, a);
1469   GET_SIZE_NEG(sb, bneg, b);
1470
1471   if (sa < sb) {
1472      SWAP_BIGINT(a, b);
1473      SWAP_LONG(sa, sb);
1474      SWAP_LONG(aneg, bneg);
1475      rev = 1;
1476   }
1477   else 
1478      rev = 0;
1479
1480   /* sa >= sb */
1481
1482   c = *cc;
1483   a_alias = (a == c);
1484   b_alias = (b == c);
1485
1486   if (aneg != bneg) {
1487      /* opposite sign => addition */
1488
1489      sc = sa + 1;
1490      if (MustAlloc(c, sc)) {
1491         _ntl_gsetlength(&c, sc);
1492         if (a_alias) a = c; 
1493         if (b_alias) b = c;
1494         *cc = c;
1495      }
1496
1497      adata = DATA(a);
1498      bdata = DATA(b);
1499      cdata = DATA(c);
1500
1501      carry = mpn_add(cdata, adata, sa, bdata, sb);
1502      if (carry) 
1503         cdata[sc-1] = carry;
1504      else
1505         sc--;
1506
1507      if (aneg ^ rev) sc = -sc;
1508      SIZE(c) = sc;
1509   }
1510   else {
1511      /* same sign => subtraction */
1512
1513      sc = sa;
1514      if (MustAlloc(c, sc)) {
1515         _ntl_gsetlength(&c, sc);
1516         if (a_alias) a = c; 
1517         if (b_alias) b = c;
1518         *cc = c;
1519      }
1520
1521      adata = DATA(a);
1522      bdata = DATA(b);
1523      cdata = DATA(c);
1524
1525      if (sa > sb) 
1526         cmp = 1;
1527      else
1528         cmp = mpn_cmp(adata, bdata, sa);
1529
1530      if (cmp == 0) {
1531         SIZE(c) = 0;
1532      }
1533      else {
1534         if (cmp < 0) cmp = 0;
1535         if (cmp > 0) cmp = 1;
1536         /* abs(a) != abs(b) && (abs(a) > abs(b) <=> cmp) */
1537
1538         if (cmp)
1539            mpn_sub(cdata, adata, sa, bdata, sb);
1540         else
1541            mpn_sub(cdata, bdata, sb, adata, sa); /* sa == sb */
1542
1543         STRIP(sc, cdata);
1544         if ((aneg == cmp) ^ rev) sc = -sc;
1545         SIZE(c) = sc;
1546      }
1547   }
1548}
1549
1550void
1551_ntl_gsubpos(_ntl_gbigint a, _ntl_gbigint b, _ntl_gbigint *cc)
1552{
1553   long sa, sb, sc;
1554   mp_limb_t *adata, *bdata, *cdata;
1555   _ntl_gbigint c;
1556   long a_alias, b_alias;
1557
1558   if (ZEROP(a)) {
1559      _ntl_gzero(cc);
1560      return;
1561   }
1562
1563   if (ZEROP(b)) {
1564      _ntl_gcopy(a, cc);
1565      return;
1566   }
1567
1568   sa = SIZE(a);
1569   sb = SIZE(b);
1570
1571   c = *cc;
1572   a_alias = (a == c);
1573   b_alias = (b == c);
1574
1575   sc = sa;
1576   if (MustAlloc(c, sc)) {
1577      _ntl_gsetlength(&c, sc);
1578      if (a_alias) a = c; 
1579      if (b_alias) b = c;
1580      *cc = c;
1581   }
1582
1583   adata = DATA(a);
1584   bdata = DATA(b);
1585   cdata = DATA(c);
1586
1587   mpn_sub(cdata, adata, sa, bdata, sb);
1588
1589   STRIP(sc, cdata);
1590   SIZE(c) = sc;
1591}
1592
1593void _ntl_gmul(_ntl_gbigint a, _ntl_gbigint b, _ntl_gbigint *cc)
1594{
1595   static _ntl_gbigint mem = 0;
1596
1597   long sa, aneg, sb, bneg, alias, sc;
1598   mp_limb_t *adata, *bdata, *cdata, msl;
1599   _ntl_gbigint c;
1600
1601   if (ZEROP(a) || ZEROP(b)) {
1602      _ntl_gzero(cc);
1603      return;
1604   }
1605
1606   GET_SIZE_NEG(sa, aneg, a);
1607   GET_SIZE_NEG(sb, bneg, b);
1608
1609   if (a == *cc || b == *cc) {
1610      c = mem;
1611      alias = 1;
1612   }
1613   else {
1614      c = *cc;
1615      alias = 0;
1616   }
1617
1618   sc = sa + sb;
1619   if (MustAlloc(c, sc))
1620      _ntl_gsetlength(&c, sc);
1621
1622   if (alias)
1623      mem = c;
1624   else
1625      *cc = c;
1626
1627   adata = DATA(a);
1628   bdata = DATA(b);
1629   cdata = DATA(c);
1630
1631   if (sa >= sb)
1632      msl = mpn_mul(cdata, adata, sa, bdata, sb);
1633   else
1634      msl = mpn_mul(cdata, bdata, sb, adata, sa);
1635
1636   if (!msl) sc--;
1637   if (aneg != bneg) sc = -sc;
1638   SIZE(c) = sc;
1639
1640   if (alias) _ntl_gcopy(mem, cc);
1641}
1642
1643void _ntl_gsq(_ntl_gbigint a, _ntl_gbigint *cc)
1644{
1645   _ntl_gmul(a, a, cc);
1646   /* this is good enough...eventually, mpn_sqr_n will be called */
1647}
1648
1649
1650/*
1651 * DIRT: this implementation of _ntl_gsmul relies crucially
1652 * on the assumption that the number of bits per limb_t is at least
1653 * equal to the number of bits per long.
1654 */
1655
1656void
1657_ntl_gsmul(_ntl_gbigint a, long d, _ntl_gbigint *bb)
1658{
1659   long sa, sb;
1660   long anegative, bnegative;
1661   _ntl_gbigint b;
1662   mp_limb_t *adata, *bdata;
1663   mp_limb_t dd, carry;
1664   long a_alias;
1665
1666   if (ZEROP(a) || !d) {
1667      _ntl_gzero(bb);
1668      return;
1669   }
1670
1671   GET_SIZE_NEG(sa, anegative, a);
1672
1673   if (d < 0) {
1674      dd = - ((mp_limb_t) d); /* careful ! */
1675      bnegative = 1-anegative;
1676   }
1677   else {
1678      dd = (mp_limb_t) d;
1679      bnegative = anegative;
1680   }
1681
1682   sb = sa + 1;
1683
1684   b = *bb;
1685   a_alias = (a == b);
1686
1687   if (MustAlloc(b, sb)) {
1688      _ntl_gsetlength(&b, sb);
1689      if (a_alias) a = b;
1690      *bb = b;
1691   }
1692
1693   adata = DATA(a);
1694   bdata = DATA(b);
1695
1696   if (dd == 2) 
1697      carry = mpn_lshift(bdata, adata, sa, 1);
1698   else
1699      carry = mpn_mul_1(bdata, adata, sa, dd);
1700
1701   if (carry) 
1702      bdata[sa] = carry;
1703   else
1704      sb--;
1705
1706   if (bnegative) sb = -sb;
1707   SIZE(b) = sb;
1708}
1709
1710/*
1711 * DIRT: this implementation of _ntl_gsdiv relies crucially
1712 * on the assumption that the number of bits per limb_t is at least
1713 * equal to the number of bits per long.
1714 */
1715
1716long _ntl_gsdiv(_ntl_gbigint a, long d, _ntl_gbigint *bb)
1717{
1718   long sa, aneg, sb, dneg;
1719   _ntl_gbigint b;
1720   mp_limb_t dd, *adata, *bdata;
1721   long r;
1722
1723   if (!d) {
1724      ghalt("division by zero in _ntl_gsdiv");
1725   }
1726
1727   if (ZEROP(a)) {
1728      _ntl_gzero(bb);
1729      return (0);
1730   }
1731
1732   GET_SIZE_NEG(sa, aneg, a);
1733
1734   if (d < 0) {
1735      dd = - ((mp_limb_t) d); /* careful ! */
1736      dneg = 1;
1737   }
1738   else {
1739      dd = (mp_limb_t) d;
1740      dneg = 0;
1741   }
1742
1743   sb = sa;
1744   b = *bb;
1745   if (MustAlloc(b, sb)) {
1746      /* if b aliases a, then b won't move */
1747      _ntl_gsetlength(&b, sb);
1748      *bb = b;
1749   }
1750
1751   adata = DATA(a);
1752   bdata = DATA(b);
1753
1754   if (dd == 2) 
1755      r = mpn_rshift(bdata, adata, sa, 1) >> (NTL_ZZ_NBITS - 1);
1756   else
1757      r = mpn_divmod_1(bdata, adata, sa, dd);
1758
1759   if (bdata[sb-1] == 0)
1760      sb--;
1761
1762   SIZE(b) = sb;
1763
1764   if (aneg || dneg) {
1765      if (aneg != dneg) {
1766         if (!r) {
1767            SIZE(b) = -SIZE(b);
1768         }
1769         else {
1770            _ntl_gsadd(b, 1, &b);
1771            SIZE(b) = -SIZE(b);
1772            if (dneg)
1773               r = r + d;
1774            else
1775               r = d - r;
1776            *bb = b;
1777         }
1778      }
1779      else
1780         r = -r;
1781   }
1782
1783   return r;
1784}
1785
1786/*
1787 * DIRT: this implementation of _ntl_gsmod relies crucially
1788 * on the assumption that the number of bits per limb_t is at least
1789 * equal to the number of bits per long.
1790 */
1791
1792long _ntl_gsmod(_ntl_gbigint a, long d)
1793{
1794   long sa, aneg, dneg;
1795   mp_limb_t dd, *adata;
1796   long r;
1797
1798   if (!d) {
1799      ghalt("division by zero in _ntl_gsmod");
1800   }
1801
1802   if (ZEROP(a)) {
1803      return (0);
1804   }
1805
1806   GET_SIZE_NEG(sa, aneg, a);
1807
1808   if (d < 0) {
1809      dd = - ((mp_limb_t) d); /* careful ! */
1810      dneg = 1;
1811   }
1812   else {
1813      dd = (mp_limb_t) d;
1814      dneg = 0;
1815   }
1816
1817   adata = DATA(a);
1818
1819   if (dd == 2) 
1820      r = adata[0] & 1;
1821   else
1822      r = mpn_mod_1(adata, sa, dd);
1823
1824   if (aneg || dneg) {
1825      if (aneg != dneg) {
1826         if (r) {
1827            if (dneg)
1828               r = r + d;
1829            else
1830               r = d - r;
1831         }
1832      }
1833      else
1834         r = -r;
1835   }
1836
1837   return r;
1838}
1839
1840
1841void _ntl_gdiv(_ntl_gbigint a, _ntl_gbigint d, 
1842               _ntl_gbigint *bb, _ntl_gbigint *rr)
1843{
1844   static _ntl_gbigint b = 0, rmem = 0;
1845
1846   _ntl_gbigint r;
1847
1848   long sa, aneg, sb, sd, dneg, sr, in_place;
1849   mp_limb_t *adata, *ddata, *bdata, *rdata;
1850
1851   if (ZEROP(d)) {
1852      ghalt("division by zero in _ntl_gdiv");
1853   }
1854
1855   if (ZEROP(a)) {
1856      if (bb) _ntl_gzero(bb);
1857      if (rr) _ntl_gzero(rr);
1858      return;
1859   }
1860
1861   GET_SIZE_NEG(sa, aneg, a);
1862   GET_SIZE_NEG(sd, dneg, d);
1863
1864   if (!aneg && !dneg && rr && *rr != a && *rr != d) {
1865      in_place = 1;
1866      r = *rr;
1867   }
1868   else {
1869      in_place = 0;
1870      r = rmem;
1871   }
1872
1873   if (sa < sd) {
1874      _ntl_gzero(&b);
1875      _ntl_gcopy(a, &r);
1876      if (aneg) SIZE(r) = -SIZE(r);
1877      goto done;
1878   }
1879
1880   sb = sa-sd+1;
1881   if (MustAlloc(b, sb))
1882      _ntl_gsetlength(&b, sb);
1883
1884   sr = sd;
1885   if (MustAlloc(r, sr))
1886      _ntl_gsetlength(&r, sr);
1887
1888   adata = DATA(a);
1889   ddata = DATA(d);
1890   bdata = DATA(b);
1891   rdata = DATA(r);
1892
1893   mpn_tdiv_qr(bdata, rdata, 0, adata, sa, ddata, sd);
1894
1895   if (bdata[sb-1] == 0)
1896      sb--;
1897   SIZE(b) = sb;
1898
1899   STRIP(sr, rdata);
1900   SIZE(r) = sr;
1901
1902done:
1903
1904   if (aneg || dneg) {
1905      if (aneg != dneg) {
1906         if (ZEROP(r)) {
1907            SIZE(b) = -SIZE(b);
1908         }
1909         else {
1910            if (bb) {
1911               _ntl_gsadd(b, 1, &b);
1912               SIZE(b) = -SIZE(b);
1913            }
1914            if (rr) {
1915               if (dneg)
1916                  _ntl_gadd(r, d, &r);
1917               else
1918                  _ntl_gsub(d, r, &r);
1919            }
1920         }
1921      }
1922      else
1923         SIZE(r) = -SIZE(r);
1924   }
1925
1926   if (bb) _ntl_gcopy(b, bb);
1927
1928   if (in_place)
1929      *rr = r;
1930   else {
1931      if (rr) _ntl_gcopy(r, rr);
1932      rmem = r;
1933   }
1934}
1935
1936
1937/* a simplified mod operation:  assumes a >= 0, d > 0 are non-negative,
1938 * that space for the result has already been allocated,
1939 * and that inputs do not alias output. */
1940
1941static
1942void gmod_simple(_ntl_gbigint a, _ntl_gbigint d, _ntl_gbigint *rr)
1943{
1944   static _ntl_gbigint b = 0;
1945
1946   long sa, sb, sd, sr;
1947   mp_limb_t *adata, *ddata, *bdata, *rdata;
1948   _ntl_gbigint r;
1949
1950   if (ZEROP(a)) {
1951      _ntl_gzero(rr);
1952      return;
1953   }
1954
1955   sa = SIZE(a);
1956   sd = SIZE(d);
1957
1958   if (sa < sd) {
1959      _ntl_gcopy(a, rr);
1960      return;
1961   }
1962
1963   sb = sa-sd+1;
1964   if (MustAlloc(b, sb))
1965      _ntl_gsetlength(&b, sb);
1966
1967   sr = sd;
1968   r = *rr;
1969
1970   adata = DATA(a);
1971   ddata = DATA(d);
1972   bdata = DATA(b);
1973   rdata = DATA(r);
1974
1975   mpn_tdiv_qr(bdata, rdata, 0, adata, sa, ddata, sd);
1976
1977   STRIP(sr, rdata);
1978   SIZE(r) = sr;
1979}
1980
1981
1982void _ntl_gmod(_ntl_gbigint a, _ntl_gbigint d, _ntl_gbigint *rr)
1983{
1984   _ntl_gdiv(a, d, 0, rr);
1985}
1986
1987void _ntl_gquickmod(_ntl_gbigint *rr, _ntl_gbigint d)
1988{
1989   _ntl_gdiv(*rr, d, 0, rr);
1990}
1991
1992void _ntl_gsqrt(_ntl_gbigint n, _ntl_gbigint *rr)
1993{
1994   static _ntl_gbigint r = 0;
1995
1996   long sn, sr;
1997   mp_limb_t *ndata, *rdata;
1998
1999   if (ZEROP(n)) {
2000      _ntl_gzero(rr);
2001      return;
2002   }
2003
2004   sn = SIZE(n);
2005   if (sn < 0) ghalt("negative argument to _ntl_sqrt");
2006
2007   sr = (sn+1)/2;
2008   _ntl_gsetlength(&r, sr);
2009
2010   ndata = DATA(n);
2011   rdata = DATA(r);
2012
2013   mpn_sqrtrem(rdata, 0, ndata, sn);
2014
2015   STRIP(sr, rdata);
2016   SIZE(r) = sr;
2017
2018   _ntl_gcopy(r, rr);
2019}
2020
2021/*
2022 * DIRT: this implementation of _ntl_gsqrts relies crucially
2023 * on the assumption that the number of bits per limb_t is at least
2024 * equal to the number of bits per long.
2025 */
2026
2027long _ntl_gsqrts(long n)
2028{
2029   mp_limb_t ndata, rdata;
2030
2031   if (n == 0) {
2032      return 0;
2033   }
2034
2035   if (n < 0) ghalt("negative argument to _ntl_sqrts");
2036
2037   ndata = n;
2038
2039   mpn_sqrtrem(&rdata, 0, &ndata, 1);
2040
2041   return rdata;
2042}
2043
2044
2045void _ntl_ggcd(_ntl_gbigint m1, _ntl_gbigint m2, _ntl_gbigint *r)
2046{
2047   static _ntl_gbigint s1 = 0, s2 = 0, res = 0;
2048
2049   long k1, k2, k_min, l1, l2, ss1, ss2, sres;
2050
2051   _ntl_gcopy(m1, &s1);
2052   _ntl_gabs(&s1);
2053
2054   _ntl_gcopy(m2, &s2);
2055   _ntl_gabs(&s2);
2056
2057   if (ZEROP(s1)) {
2058      _ntl_gcopy(s2, r);
2059      return;
2060   }
2061
2062   if (ZEROP(s2)) {
2063      _ntl_gcopy(s1, r);
2064      return;
2065   }
2066
2067   k1 = _ntl_gmakeodd(&s1);
2068   k2 = _ntl_gmakeodd(&s2);
2069
2070   if (k1 <= k2)
2071      k_min = k1;
2072   else
2073      k_min = k2;
2074
2075   l1 = _ntl_g2log(s1);
2076   l2 = _ntl_g2log(s2);
2077
2078   ss1 = SIZE(s1);
2079   ss2 = SIZE(s2);
2080
2081   if (ss1 >= ss2)
2082      sres = ss1;
2083   else
2084      sres = ss2;
2085
2086   /* set to max: gmp documentation is unclear on this point */
2087
2088   _ntl_gsetlength(&res, sres);
2089   
2090   if (l1 >= l2)
2091      SIZE(res) = mpn_gcd(DATA(res), DATA(s1), ss1, DATA(s2), ss2);
2092   else
2093      SIZE(res) = mpn_gcd(DATA(res), DATA(s2), ss2, DATA(s1), ss1);
2094
2095   _ntl_glshift(res, k_min, &res);
2096
2097   _ntl_gcopy(res, r);
2098}
2099
2100static long 
2101gxxeucl(
2102   _ntl_gbigint ain,
2103   _ntl_gbigint nin,
2104   _ntl_gbigint *invv,
2105   _ntl_gbigint *uu
2106   )
2107{
2108   static _ntl_gbigint a = 0;
2109   static _ntl_gbigint n = 0;
2110   static _ntl_gbigint q = 0;
2111   static _ntl_gbigint w = 0;
2112   static _ntl_gbigint x = 0;
2113   static _ntl_gbigint y = 0;
2114   static _ntl_gbigint z = 0;
2115   _ntl_gbigint inv = *invv;
2116   _ntl_gbigint u = *uu;
2117   long diff;
2118   long ilo;
2119   long sa;
2120   long sn;
2121   long temp;
2122   long e;
2123   long fast;
2124   long parity;
2125   long gotthem;
2126   mp_limb_t *p;
2127   long try11;
2128   long try12;
2129   long try21;
2130   long try22;
2131   long got11;
2132   long got12;
2133   long got21;
2134   long got22;
2135   double hi;
2136   double lo;
2137   double dt;
2138   double fhi, fhi1;
2139   double flo, flo1;
2140   double num;
2141   double den;
2142   double dirt;
2143
2144   _ntl_gsetlength(&a, (e = (SIZE(ain) > SIZE(nin) ? SIZE(ain) : SIZE(nin))));
2145   _ntl_gsetlength(&n, e);
2146   _ntl_gsetlength(&q, e);
2147   _ntl_gsetlength(&w, e);
2148   _ntl_gsetlength(&x, e);
2149   _ntl_gsetlength(&y, e);
2150   _ntl_gsetlength(&z, e);
2151   _ntl_gsetlength(&inv, e);
2152   *invv = inv;
2153   _ntl_gsetlength(&u, e);
2154   *uu = u;
2155
2156   fhi1 = 1.0 + ((double) 32.0)/NTL_FDOUBLE_PRECISION;
2157   flo1 = 1.0 - ((double) 32.0)/NTL_FDOUBLE_PRECISION;
2158
2159   fhi = 1.0 + ((double) 8.0)/NTL_FDOUBLE_PRECISION;
2160   flo = 1.0 - ((double) 8.0)/NTL_FDOUBLE_PRECISION;
2161
2162   _ntl_gcopy(ain, &a);
2163   _ntl_gcopy(nin, &n);
2164
2165   _ntl_gone(&inv);
2166   _ntl_gzero(&w);
2167
2168   while (SIZE(n) > 0)
2169   {
2170      gotthem = 0;
2171      sa = SIZE(a);
2172      sn = SIZE(n);
2173      diff = sa - sn;
2174      if (!diff || diff == 1)
2175      {
2176         sa = SIZE(a);
2177         p = DATA(a) + (sa-1);
2178         num = (double) (*p) * NTL_ZZ_FRADIX;
2179         if (sa > 1)
2180            num += (*(--p));
2181         num *= NTL_ZZ_FRADIX;
2182         if (sa > 2)
2183            num += (*(p - 1));
2184
2185         sn = SIZE(n);
2186         p = DATA(n) + (sn-1);
2187         den = (double) (*p) * NTL_ZZ_FRADIX;
2188         if (sn > 1)
2189            den += (*(--p));
2190         den *= NTL_ZZ_FRADIX;
2191         if (sn > 2)
2192            den += (*(p - 1));
2193
2194         hi = fhi1 * (num + 1.0) / den;
2195         lo = flo1 * num / (den + 1.0);
2196         if (diff > 0)
2197         {
2198            hi *= NTL_ZZ_FRADIX;
2199            lo *= NTL_ZZ_FRADIX;
2200         }
2201         try11 = 1;
2202         try12 = 0;
2203         try21 = 0;
2204         try22 = 1;
2205         parity = 1;
2206         fast = 1; 
2207         while (fast > 0)
2208         {
2209            parity = 1 - parity;
2210            if (hi >= NTL_SP_BOUND)
2211               fast = 0;
2212            else
2213            {
2214               ilo = (long)lo;
2215               dirt = hi - ilo;
2216               if (dirt < 1.0/NTL_FDOUBLE_PRECISION || !ilo || ilo < (long)hi)
2217                  fast = 0;
2218               else
2219               {
2220                  dt = lo-ilo;
2221                  lo = flo / dirt;
2222                  if (dt > 1.0/NTL_FDOUBLE_PRECISION)
2223                     hi = fhi / dt;
2224                  else
2225                     hi = NTL_SP_BOUND;
2226                  temp = try11;
2227                  try11 = try21;
2228                  if ((NTL_WSP_BOUND - temp) / ilo < try21)
2229                     fast = 0;
2230                  else
2231                     try21 = temp + ilo * try21;
2232                  temp = try12;
2233                  try12 = try22;
2234                  if ((NTL_WSP_BOUND - temp) / ilo < try22)
2235                     fast = 0;
2236                  else
2237                     try22 = temp + ilo * try22;
2238                  if ((fast > 0) && (parity > 0))
2239                  {
2240                     gotthem = 1;
2241                     got11 = try11;
2242                     got12 = try12;
2243                     got21 = try21;
2244                     got22 = try22;
2245                  }
2246               }
2247            }
2248         }
2249      }
2250      if (gotthem)
2251      {
2252         _ntl_gsmul(inv, got11, &x);
2253         _ntl_gsmul(w, got12, &y);
2254         _ntl_gsmul(inv, got21, &z);
2255         _ntl_gsmul(w, got22, &w);
2256         _ntl_gadd(x, y, &inv);
2257         _ntl_gadd(z, w, &w);
2258         _ntl_gsmul(a, got11, &x);
2259         _ntl_gsmul(n, got12, &y);
2260         _ntl_gsmul(a, got21, &z);
2261         _ntl_gsmul(n, got22, &n);
2262         _ntl_gsub(x, y, &a);
2263         _ntl_gsub(n, z, &n);
2264      }
2265      else
2266      {
2267         _ntl_gdiv(a, n, &q, &a);
2268         _ntl_gmul(q, w, &x);
2269         _ntl_gadd(inv, x, &inv);
2270         if (!ZEROP(a))
2271         {
2272            _ntl_gdiv(n, a, &q, &n);
2273            _ntl_gmul(q, inv, &x);
2274            _ntl_gadd(w, x, &w);
2275         }
2276         else
2277         {
2278            _ntl_gcopy(n, &a);
2279            _ntl_gzero(&n);
2280            _ntl_gcopy(w, &inv);
2281            _ntl_gnegate(&inv);
2282         }
2283      }
2284   }
2285
2286   if (_ntl_gscompare(a, 1) == 0)
2287      e = 0;
2288   else 
2289      e = 1;
2290
2291   _ntl_gcopy(a, &u);
2292
2293   *invv = inv;
2294   *uu = u;
2295
2296   return (e);
2297}
2298
2299#if 0
2300void
2301_ntl_gexteucl(
2302        _ntl_gbigint aa,
2303        _ntl_gbigint *xa,
2304        _ntl_gbigint bb,
2305        _ntl_gbigint *xb,
2306        _ntl_gbigint *d
2307        )
2308{
2309   static _ntl_gbigint modcon = 0;
2310   static _ntl_gbigint a=0, b=0;
2311   long anegative = 0;
2312   long bnegative = 0;
2313
2314   _ntl_gcopy(aa, &a);
2315   _ntl_gcopy(bb, &b);
2316
2317   if (a && SIZE(a) < 0) {
2318      anegative = 1;
2319      SIZE(a) = -SIZE(a);
2320   }
2321   else
2322      anegative = 0;
2323
2324   if (b && SIZE(b) < 0) {
2325      bnegative = 1;
2326      SIZE(b) = -SIZE(b);
2327   }
2328   else
2329      bnegative = 0;
2330
2331
2332   if (ZEROP(b))
2333   {
2334      _ntl_gone(xa);
2335      _ntl_gzero(xb);
2336      _ntl_gcopy(a, d);
2337      goto done;
2338   }
2339
2340   if (ZEROP(a))
2341   {
2342      _ntl_gzero(xa);
2343      _ntl_gone(xb);
2344      _ntl_gcopy(b, d);
2345      goto done;
2346   }
2347
2348   gxxeucl(a, b, xa, d);
2349   _ntl_gmul(a, *xa, xb);
2350   _ntl_gsub(*d, *xb, xb);
2351   _ntl_gdiv(*xb, b, xb, &modcon);
2352
2353   if (!ZEROP(modcon))
2354   {
2355      ghalt("non-zero remainder in _ntl_gexteucl   BUG");
2356   }
2357
2358
2359done:
2360   if (anegative)
2361   {
2362      _ntl_gnegate(xa);
2363   }
2364   if (bnegative)
2365   {
2366      _ntl_gnegate(xb);
2367   }
2368}
2369#endif
2370
2371void
2372_ntl_gexteucl(
2373        _ntl_gbigint ain,
2374        _ntl_gbigint *xap,
2375        _ntl_gbigint bin,
2376        _ntl_gbigint *xbp,
2377        _ntl_gbigint *dp
2378        )
2379{
2380   if (ZEROP(bin)) {
2381      long asign = _ntl_gsign(ain);
2382
2383      _ntl_gcopy(ain, dp);
2384      _ntl_gabs(dp);
2385      _ntl_gintoz( (asign >= 0 ? 1 : -1), xap);
2386      _ntl_gzero(xbp);
2387   }
2388   else if (ZEROP(ain)) {
2389      long bsign = _ntl_gsign(bin);
2390
2391      _ntl_gcopy(bin, dp);
2392      _ntl_gabs(dp);
2393      _ntl_gzero(xap);
2394      _ntl_gintoz(bsign, xbp); 
2395   }
2396   else {
2397      static _ntl_gbigint a = 0, b = 0, xa = 0, xb = 0, d = 0, tmp = 0;
2398
2399      long sa, aneg, sb, bneg, rev;
2400      mp_limb_t *adata, *bdata, *ddata, *xadata;
2401      mp_size_t sxa, sd;
2402
2403      GET_SIZE_NEG(sa, aneg, ain);
2404      GET_SIZE_NEG(sb, bneg, bin);
2405
2406      _ntl_gsetlength(&a, sa+1); /* +1 because mpn_gcdext may need it */
2407      _ntl_gcopy(ain, &a);
2408
2409      _ntl_gsetlength(&b, sb+1); /* +1 because mpn_gcdext may need it */
2410      _ntl_gcopy(bin, &b);
2411
2412
2413      adata = DATA(a);
2414      bdata = DATA(b);
2415
2416      if (sa < sb || (sa == sb && mpn_cmp(adata, bdata, sa) < 0)) {
2417         SWAP_BIGINT(ain, bin);
2418         SWAP_LONG(sa, sb);
2419         SWAP_LONG(aneg, bneg);
2420         SWAP_LIMB_PTR(adata, bdata);
2421         rev = 1;
2422      }
2423      else 
2424         rev = 0;
2425
2426      _ntl_gsetlength(&d, sa+1); /* +1 because mpn_gcdext may need it...
2427                                    documentation is unclear, but this is
2428                                    what is done in mpz_gcdext */
2429      _ntl_gsetlength(&xa, sa+1); /* ditto */
2430
2431      ddata = DATA(d);
2432      xadata = DATA(xa);
2433
2434      sd = mpn_gcdext(ddata, xadata, &sxa, adata, sa, bdata, sb);
2435
2436      SIZE(d) = sd;
2437      SIZE(xa) = sxa;
2438
2439      /* Thes two ForceNormal's are work-arounds for GMP bugs
2440         in GMP 4.3.0 */
2441      ForceNormal(d);
2442      ForceNormal(xa);
2443
2444      /* now we normalize xa, so that so that xa in ( -b/2d, b/2d ],
2445         which makes the output agree with Euclid's algorithm,
2446         regardless of what mpn_gcdext does */
2447
2448      if (!ZEROP(xa)) {
2449         _ntl_gcopy(bin, &b);
2450         SIZE(b) = sb;
2451         if (!ONEP(d)) {
2452            _ntl_gdiv(b, d, &b, &tmp);
2453            if (!ZEROP(tmp)) ghalt("internal bug in _ntl_gexteucl");
2454         }
2455
2456         if (SIZE(xa) > 0) { /* xa positive */
2457            if (_ntl_gcompare(xa, b) > 0) { 
2458               _ntl_gmod(xa, b, &xa);
2459            }
2460            _ntl_glshift(xa, 1, &tmp);
2461            if (_ntl_gcompare(tmp, b) > 0) {
2462               _ntl_gsub(xa, b, &xa);
2463            }
2464         }
2465         else { /* xa negative */
2466            SIZE(xa) = -SIZE(xa);
2467            if (_ntl_gcompare(xa, b) > 0) {
2468               SIZE(xa) = -SIZE(xa);
2469               _ntl_gmod(xa, b, &xa);
2470               _ntl_gsub(xa, b, &xa);
2471            }
2472            else {
2473               SIZE(xa) = -SIZE(xa);
2474            }
2475            _ntl_glshift(xa, 1, &tmp);
2476            SIZE(tmp) = -SIZE(tmp);
2477            if (_ntl_gcompare(tmp, b) >= 0) {
2478               _ntl_gadd(xa, b, &xa);
2479            }
2480         }
2481      }
2482
2483      /* end normalize */
2484   
2485
2486      if (aneg) _ntl_gnegate(&xa);
2487
2488      _ntl_gmul(ain, xa, &tmp);
2489      _ntl_gsub(d, tmp, &tmp);
2490      _ntl_gdiv(tmp, bin, &xb, &tmp);
2491
2492      if (!ZEROP(tmp)) ghalt("internal bug in _ntl_gexteucl");
2493
2494      if (rev) SWAP_BIGINT(xa, xb);
2495
2496      _ntl_gcopy(xa, xap);
2497      _ntl_gcopy(xb, xbp);
2498      _ntl_gcopy(d, dp); 
2499   }
2500}
2501
2502
2503long _ntl_ginv(_ntl_gbigint ain, _ntl_gbigint nin, _ntl_gbigint *invv)
2504{
2505   static _ntl_gbigint u = 0;
2506   static _ntl_gbigint d = 0;
2507   static _ntl_gbigint a = 0;
2508   static _ntl_gbigint n = 0;
2509
2510   long sz; 
2511   long sd;
2512   mp_size_t su;
2513
2514   if (_ntl_gscompare(nin, 1) <= 0) {
2515      ghalt("InvMod: second input <= 1");
2516   }
2517
2518   if (_ntl_gsign(ain) < 0) {
2519      ghalt("InvMod: first input negative");
2520   }
2521
2522   if (_ntl_gcompare(ain, nin) >= 0) {
2523      ghalt("InvMod: first input too big");
2524   }
2525
2526   sz = SIZE(nin) + 2;
2527
2528   if (MustAlloc(a, sz))
2529      _ntl_gsetlength(&a, sz);
2530
2531
2532   if (MustAlloc(n, sz))
2533       _ntl_gsetlength(&n, sz);
2534
2535
2536   if (MustAlloc(d, sz))
2537       _ntl_gsetlength(&d, sz);
2538
2539   if (MustAlloc(u, sz))
2540       _ntl_gsetlength(&u, sz);
2541
2542   _ntl_gadd(ain, nin, &a);
2543   _ntl_gcopy(nin, &n);
2544
2545   /* We apply mpn_gcdext to (a, n) = (ain+nin, nin), because that function
2546    * only computes the co-factor of the larger input. This way, we avoid
2547    * a multiplication and a division.
2548    */
2549
2550   sd = mpn_gcdext(DATA(d), DATA(u), &su, DATA(a), SIZE(a), DATA(n), SIZE(n));
2551
2552   SIZE(d) = sd;
2553   SIZE(u) = su;
2554
2555      /* Thes two ForceNormal's are work-arounds for GMP bugs
2556         in GMP 4.3.0 */
2557      ForceNormal(d);
2558      ForceNormal(u);
2559
2560
2561   if (ONEP(d)) {
2562
2563      /*
2564       * We make sure that u is in range 0..n-1, just in case
2565       * GMP is sloppy.
2566       */
2567
2568
2569      if (_ntl_gsign(u) < 0) {
2570         _ntl_gadd(u, nin, &u);
2571         if (_ntl_gsign(u) < 0) {
2572            _ntl_gmod(u, nin, &u);
2573         }
2574      }
2575      else if (_ntl_gcompare(u, nin) >= 0) {
2576         _ntl_gsub(u, nin, &u);
2577         if (_ntl_gcompare(u, nin) >= 0) {
2578             _ntl_gmod(u, nin, &u);
2579         }
2580      }
2581
2582      _ntl_gcopy(u, invv);
2583      return 0;
2584   }
2585   else {
2586      _ntl_gcopy(d, invv);
2587      return 1;
2588   }
2589}
2590
2591
2592void
2593_ntl_ginvmod(
2594        _ntl_gbigint a,
2595        _ntl_gbigint n,
2596        _ntl_gbigint *c
2597        )
2598{
2599        if (_ntl_ginv(a, n, c))
2600                ghalt("undefined inverse in _ntl_ginvmod");
2601}
2602
2603
2604void
2605_ntl_gaddmod(
2606        _ntl_gbigint a,
2607        _ntl_gbigint b,
2608        _ntl_gbigint n,
2609        _ntl_gbigint *c
2610        )
2611{
2612        if (*c != n) {
2613                _ntl_gadd(a, b, c);
2614                if (_ntl_gcompare(*c, n) >= 0)
2615                        _ntl_gsubpos(*c, n, c);
2616        }
2617        else {
2618                static _ntl_gbigint mem = 0;
2619
2620                _ntl_gadd(a, b, &mem);
2621                if (_ntl_gcompare(mem, n) >= 0)
2622                        _ntl_gsubpos(mem, n, c);
2623                else
2624                        _ntl_gcopy(mem, c);
2625        }
2626}
2627
2628
2629void
2630_ntl_gsubmod(
2631        _ntl_gbigint a,
2632        _ntl_gbigint b,
2633        _ntl_gbigint n,
2634        _ntl_gbigint *c
2635        )
2636{
2637        static _ntl_gbigint mem = 0;
2638        long cmp;
2639
2640        if ((cmp=_ntl_gcompare(a, b)) < 0) {
2641                _ntl_gadd(n, a, &mem);
2642                _ntl_gsubpos(mem, b, c);
2643        } else if (!cmp) 
2644                _ntl_gzero(c);
2645        else 
2646                _ntl_gsubpos(a, b, c);
2647}
2648
2649void
2650_ntl_gsmulmod(
2651        _ntl_gbigint a,
2652        long d,
2653        _ntl_gbigint n,
2654        _ntl_gbigint *c
2655        )
2656{
2657        static _ntl_gbigint mem = 0;
2658
2659        _ntl_gsmul(a, d, &mem);
2660        _ntl_gmod(mem, n, c);
2661}
2662
2663
2664
2665void
2666_ntl_gmulmod(
2667        _ntl_gbigint a,
2668        _ntl_gbigint b,
2669        _ntl_gbigint n,
2670        _ntl_gbigint *c
2671        )
2672{
2673        static _ntl_gbigint mem = 0;
2674
2675        _ntl_gmul(a, b, &mem);
2676        _ntl_gmod(mem, n, c);
2677}
2678
2679void
2680_ntl_gsqmod(
2681        _ntl_gbigint a,
2682        _ntl_gbigint n,
2683        _ntl_gbigint *c
2684        )
2685{
2686        _ntl_gmulmod(a, a, n, c);
2687}
2688
2689
2690double _ntl_gdoub_aux(_ntl_gbigint n)
2691{
2692   double res;
2693   mp_limb_t *ndata;
2694   long i, sn, nneg;
2695
2696   if (!n)
2697      return ((double) 0);
2698
2699   GET_SIZE_NEG(sn, nneg, n);
2700
2701   ndata = DATA(n);
2702
2703   res = 0;
2704   for (i = sn-1; i >= 0; i--)
2705      res = res * NTL_ZZ_FRADIX + ((double) ndata[i]);
2706
2707   if (nneg) res = -res;
2708
2709   return res;
2710}
2711
2712long _ntl_ground_correction(_ntl_gbigint a, long k, long residual)
2713{
2714   long direction;
2715   long p;
2716   long sgn;
2717   long bl;
2718   mp_limb_t wh;
2719   long i;
2720   mp_limb_t *adata;
2721
2722   if (SIZE(a) > 0)
2723      sgn = 1;
2724   else
2725      sgn = -1;
2726
2727   adata = DATA(a);
2728
2729   p = k - 1;
2730   bl = (p/NTL_ZZ_NBITS);
2731   wh = ((mp_limb_t) 1) << (p - NTL_ZZ_NBITS*bl);
2732
2733   if (adata[bl] & wh) {
2734      /* bit is 1...we have to see if lower bits are all 0
2735         in order to implement "round to even" */
2736
2737      if (adata[bl] & (wh - ((mp_limb_t) 1))) 
2738         direction = 1;
2739      else {
2740         i = bl - 1;
2741         while (i >= 0 && adata[i] == 0) i--;
2742         if (i >= 0)
2743            direction = 1;
2744         else
2745            direction = 0;
2746      }
2747
2748      /* use residual to break ties */
2749
2750      if (direction == 0 && residual != 0) {
2751         if (residual == sgn)
2752            direction = 1;
2753         else 
2754            direction = -1;
2755      }
2756
2757      if (direction == 0) {
2758         /* round to even */
2759
2760         wh = wh << 1;
2761
2762         /*
2763          * DIRT: if GMP has non-empty "nails", this won't work.
2764          */
2765
2766         if (wh == 0) {
2767            wh = 1;
2768            bl++;
2769         }
2770
2771         if (adata[bl] & wh)
2772            direction = 1;
2773         else
2774            direction = -1;
2775      }
2776   }
2777   else
2778      direction = -1;
2779
2780   if (direction == 1)
2781      return sgn;
2782
2783   return 0;
2784}
2785
2786
2787
2788
2789double _ntl_gdoub(_ntl_gbigint n)
2790{
2791   static _ntl_gbigint tmp = 0;
2792
2793   long s;
2794   long shamt;
2795   long correction;
2796   double x;
2797
2798   s = _ntl_g2log(n);
2799   shamt = s - NTL_DOUBLE_PRECISION;
2800
2801   if (shamt <= 0)
2802      return _ntl_gdoub_aux(n);
2803
2804   _ntl_grshift(n, shamt, &tmp);
2805
2806   correction = _ntl_ground_correction(n, shamt, 0);
2807
2808   if (correction) _ntl_gsadd(tmp, correction, &tmp);
2809
2810   x = _ntl_gdoub_aux(tmp);
2811
2812   x = _ntl_ldexp(x, shamt);
2813
2814   return x;
2815}
2816
2817
2818double _ntl_glog(_ntl_gbigint n)
2819{
2820   static _ntl_gbigint tmp = 0;
2821
2822   static double log_2;
2823   static long init = 0;
2824
2825   long s;
2826   long shamt;
2827   long correction;
2828   double x;
2829
2830   if (!init) {
2831      log_2 = log(2.0);
2832      init = 1;
2833   }
2834
2835   if (_ntl_gsign(n) <= 0)
2836      ghalt("log argument <= 0");
2837
2838   s = _ntl_g2log(n);
2839   shamt = s - NTL_DOUBLE_PRECISION;
2840
2841   if (shamt <= 0)
2842      return log(_ntl_gdoub_aux(n));
2843
2844   _ntl_grshift(n, shamt, &tmp);
2845
2846   correction = _ntl_ground_correction(n, shamt, 0);
2847
2848   if (correction) _ntl_gsadd(tmp, correction, &tmp);
2849
2850   x = _ntl_gdoub_aux(tmp);
2851
2852   return log(x) + shamt*log_2;
2853}
2854
2855
2856
2857
2858
2859/* To implement _ntl_gdoubtoz, I've implemented essentially the
2860 * same algorithm as in LIP, processing in blocks of
2861 * NTL_SP_NBITS bits, rather than NTL_ZZ_NBITS.
2862 * This is conversion is rather delicate, and I don't want to
2863 * make any new assumptions about the underlying arithmetic.
2864 * This implementation should be quite portable. */
2865
2866void _ntl_gdoubtoz(double a, _ntl_gbigint *xx)
2867{
2868   static _ntl_gbigint x = 0;
2869
2870   long neg, i, t, sz;
2871
2872   a = floor(a);
2873
2874   if (!_ntl_IsFinite(&a))
2875      ghalt("_ntl_gdoubtoz: attempt to convert non-finite value");
2876
2877   if (a < 0) {
2878      a = -a;
2879      neg = 1;
2880   }
2881   else
2882      neg = 0;
2883
2884   if (a == 0) {
2885      _ntl_gzero(xx);
2886      return;
2887   }
2888
2889   sz = 0;
2890   while (a >= 1) {
2891      a = a*(1.0/NTL_SP_FBOUND);
2892      sz++;
2893   }
2894
2895   i = 0;
2896   _ntl_gzero(&x);
2897
2898   while (a != 0) {
2899      i++;
2900      a = a*NTL_SP_FBOUND;
2901      t = (long) a;
2902      a = a - t;
2903
2904      if (i == 1) {
2905         _ntl_gintoz(t, &x);
2906      }
2907      else {
2908         _ntl_glshift(x, NTL_SP_NBITS, &x);
2909         _ntl_gsadd(x, t, &x);
2910      }
2911   }
2912
2913   if (i > sz) ghalt("bug in _ntl_gdoubtoz");
2914
2915   _ntl_glshift(x, (sz-i)*NTL_SP_NBITS, xx);
2916   if (neg) _ntl_gnegate(xx);
2917}
2918
2919
2920
2921/* I've adapted LIP's extended euclidean algorithm to
2922 * do rational reconstruction.  -- VJS.
2923 */
2924
2925
2926long 
2927_ntl_gxxratrecon(
2928   _ntl_gbigint ain,
2929   _ntl_gbigint nin,
2930   _ntl_gbigint num_bound,
2931   _ntl_gbigint den_bound,
2932   _ntl_gbigint *num_out,
2933   _ntl_gbigint *den_out
2934   )
2935{
2936   static _ntl_gbigint a = 0;
2937   static _ntl_gbigint n = 0;
2938   static _ntl_gbigint q = 0;
2939   static _ntl_gbigint w = 0;
2940   static _ntl_gbigint x = 0;
2941   static _ntl_gbigint y = 0;
2942   static _ntl_gbigint z = 0;
2943   static _ntl_gbigint inv = 0;
2944   static _ntl_gbigint u = 0;
2945   static _ntl_gbigint a_bak = 0;
2946   static _ntl_gbigint n_bak = 0;
2947   static _ntl_gbigint inv_bak = 0;
2948   static _ntl_gbigint w_bak = 0;
2949
2950   mp_limb_t *p;
2951
2952   long diff;
2953   long ilo;
2954   long sa;
2955   long sn;
2956   long snum;
2957   long sden;
2958   long e;
2959   long fast;
2960   long temp;
2961   long parity;
2962   long gotthem;
2963   long try11;
2964   long try12;
2965   long try21;
2966   long try22;
2967   long got11;
2968   long got12;
2969   long got21;
2970   long got22;
2971
2972   double hi;
2973   double lo;
2974   double dt;
2975   double fhi, fhi1;
2976   double flo, flo1;
2977   double num;
2978   double den;
2979   double dirt;
2980
2981   if (_ntl_gsign(num_bound) < 0)
2982      ghalt("rational reconstruction: bad numerator bound");
2983
2984   if (!num_bound)
2985      snum = 0;
2986   else
2987      snum = SIZE(num_bound);
2988
2989   if (_ntl_gsign(den_bound) <= 0)
2990      ghalt("rational reconstruction: bad denominator bound");
2991
2992   sden = SIZE(den_bound);
2993
2994   if (_ntl_gsign(nin) <= 0)
2995      ghalt("rational reconstruction: bad modulus");
2996
2997   if (_ntl_gsign(ain) < 0 || _ntl_gcompare(ain, nin) >= 0)
2998      ghalt("rational reconstruction: bad residue");
2999
3000     
3001   e = SIZE(nin);
3002
3003   _ntl_gsetlength(&a, e);
3004   _ntl_gsetlength(&n, e);
3005   _ntl_gsetlength(&q, e);
3006   _ntl_gsetlength(&w, e);
3007   _ntl_gsetlength(&x, e);
3008   _ntl_gsetlength(&y, e);
3009   _ntl_gsetlength(&z, e);
3010   _ntl_gsetlength(&inv, e);
3011   _ntl_gsetlength(&u, e);
3012   _ntl_gsetlength(&a_bak, e);
3013   _ntl_gsetlength(&n_bak, e);
3014   _ntl_gsetlength(&inv_bak, e);
3015   _ntl_gsetlength(&w_bak, e);
3016
3017   fhi1 = 1.0 + ((double) 32.0)/NTL_FDOUBLE_PRECISION;
3018   flo1 = 1.0 - ((double) 32.0)/NTL_FDOUBLE_PRECISION;
3019
3020   fhi = 1.0 + ((double) 8.0)/NTL_FDOUBLE_PRECISION;
3021   flo = 1.0 - ((double) 8.0)/NTL_FDOUBLE_PRECISION;
3022
3023   _ntl_gcopy(ain, &a);
3024   _ntl_gcopy(nin, &n);
3025
3026   _ntl_gone(&inv);
3027   _ntl_gzero(&w);
3028
3029   while (1)
3030   {
3031      if (SIZE(w) >= sden && _ntl_gcompare(w, den_bound) > 0) break;
3032      if (SIZE(n) <= snum && _ntl_gcompare(n, num_bound) <= 0) break;
3033
3034      _ntl_gcopy(a, &a_bak);
3035      _ntl_gcopy(n, &n_bak);
3036      _ntl_gcopy(w, &w_bak);
3037      _ntl_gcopy(inv, &inv_bak);
3038
3039      gotthem = 0;
3040      sa = SIZE(a);
3041      sn = SIZE(n);
3042      diff = sa - sn;
3043      if (!diff || diff == 1)
3044      {
3045         sa = SIZE(a);
3046         p = DATA(a) + (sa-1);
3047         num = (double) (*p) * NTL_ZZ_FRADIX;
3048         if (sa > 1)
3049            num += (*(--p));
3050         num *= NTL_ZZ_FRADIX;
3051         if (sa > 2)
3052            num += (*(p - 1));
3053
3054         sn = SIZE(n);
3055         p = DATA(n) + (sn-1);
3056         den = (double) (*p) * NTL_ZZ_FRADIX;
3057         if (sn > 1)
3058            den += (*(--p));
3059         den *= NTL_ZZ_FRADIX;
3060         if (sn > 2)
3061            den += (*(p - 1));
3062
3063         hi = fhi1 * (num + 1.0) / den;
3064         lo = flo1 * num / (den + 1.0);
3065         if (diff > 0)
3066         {
3067            hi *= NTL_ZZ_FRADIX;
3068            lo *= NTL_ZZ_FRADIX;
3069         }
3070
3071         try11 = 1;
3072         try12 = 0;
3073         try21 = 0;
3074         try22 = 1;
3075         parity = 1;
3076         fast = 1; 
3077         while (fast > 0)
3078         {
3079            parity = 1 - parity;
3080            if (hi >= NTL_SP_BOUND)
3081               fast = 0;
3082            else
3083            {
3084               ilo = (long)lo;
3085               dirt = hi - ilo;
3086               if (dirt < 1.0/NTL_FDOUBLE_PRECISION || !ilo || ilo < (long)hi)
3087                  fast = 0;
3088               else
3089               {
3090                  dt = lo-ilo;
3091                  lo = flo / dirt;
3092                  if (dt > 1.0/NTL_FDOUBLE_PRECISION)
3093                     hi = fhi / dt;
3094                  else
3095                     hi = NTL_SP_BOUND;
3096                  temp = try11;
3097                  try11 = try21;
3098                  if ((NTL_WSP_BOUND - temp) / ilo < try21)
3099                     fast = 0;
3100                  else
3101                     try21 = temp + ilo * try21;
3102                  temp = try12;
3103                  try12 = try22;
3104                  if ((NTL_WSP_BOUND - temp) / ilo < try22)
3105                     fast = 0;
3106                  else
3107                     try22 = temp + ilo * try22;
3108                  if ((fast > 0) && (parity > 0))
3109                  {
3110                     gotthem = 1;
3111                     got11 = try11;
3112                     got12 = try12;
3113                     got21 = try21;
3114                     got22 = try22;
3115                  }
3116               }
3117            }
3118         }
3119      }
3120      if (gotthem)
3121      {
3122         _ntl_gsmul(inv, got11, &x);
3123         _ntl_gsmul(w, got12, &y);
3124         _ntl_gsmul(inv, got21, &z);
3125         _ntl_gsmul(w, got22, &w);
3126         _ntl_gadd(x, y, &inv);
3127         _ntl_gadd(z, w, &w);
3128         _ntl_gsmul(a, got11, &x);
3129         _ntl_gsmul(n, got12, &y);
3130         _ntl_gsmul(a, got21, &z);
3131         _ntl_gsmul(n, got22, &n);
3132         _ntl_gsub(x, y, &a);
3133         _ntl_gsub(n, z, &n);
3134      }
3135      else
3136      {
3137         _ntl_gdiv(a, n, &q, &a);
3138         _ntl_gmul(q, w, &x);
3139         _ntl_gadd(inv, x, &inv);
3140         if (!ZEROP(a))
3141         {
3142            _ntl_gdiv(n, a, &q, &n);
3143            _ntl_gmul(q, inv, &x);
3144            _ntl_gadd(w, x, &w);
3145         }
3146         else
3147         {
3148            break;
3149         }
3150      }
3151   }
3152
3153   _ntl_gcopy(a_bak, &a);
3154   _ntl_gcopy(n_bak, &n);
3155   _ntl_gcopy(w_bak, &w);
3156   _ntl_gcopy(inv_bak, &inv);
3157
3158   _ntl_gnegate(&w);
3159
3160   while (1)
3161   {
3162      sa = SIZE(w);
3163      if (sa < 0) SIZE(w) = -sa;
3164      if (SIZE(w) >= sden && _ntl_gcompare(w, den_bound) > 0) return 0;
3165      SIZE(w) = sa;
3166
3167      if (SIZE(n) <= snum && _ntl_gcompare(n, num_bound) <= 0) break;
3168     
3169      fast = 0;
3170      sa = SIZE(a);
3171      sn = SIZE(n);
3172      diff = sa - sn;
3173      if (!diff || diff == 1)
3174      {
3175         sa = SIZE(a);
3176         p = DATA(a) + (sa-1);
3177         num = (double) (*p) * NTL_ZZ_FRADIX;
3178         if (sa > 1)
3179            num += (*(--p));
3180         num *= NTL_ZZ_FRADIX;
3181         if (sa > 2)
3182            num += (*(p - 1));
3183
3184         sn = SIZE(n);
3185         p = DATA(n) + (sn-1);
3186         den = (double) (*p) * NTL_ZZ_FRADIX;
3187         if (sn > 1)
3188            den += (*(--p));
3189         den *= NTL_ZZ_FRADIX;
3190         if (sn > 2)
3191            den += (*(p - 1));
3192
3193         hi = fhi1 * (num + 1.0) / den;
3194         lo = flo1 * num / (den + 1.0);
3195         if (diff > 0)
3196         {
3197            hi *= NTL_ZZ_FRADIX;
3198            lo *= NTL_ZZ_FRADIX;
3199         }
3200
3201         if (hi < NTL_SP_BOUND)
3202         {
3203            ilo = (long)lo;
3204            if (ilo == (long)hi)
3205               fast = 1;
3206         }
3207      }
3208
3209      if (fast) 
3210      {
3211         if (ilo != 0) {
3212            if (ilo == 1) {
3213               _ntl_gsub(inv, w, &inv);
3214               _ntl_gsubpos(a, n, &a);
3215            }
3216            else {
3217               _ntl_gsmul(w, ilo, &x);
3218               _ntl_gsub(inv, x, &inv);
3219               _ntl_gsmul(n, ilo, &x);
3220               _ntl_gsubpos(a, x, &a);
3221            }
3222         }
3223      }
3224      else {
3225         _ntl_gdiv(a, n, &q, &a);
3226         _ntl_gmul(q, w, &x);
3227         _ntl_gsub(inv, x, &inv);
3228      }
3229
3230      _ntl_gswap(&a, &n);
3231      _ntl_gswap(&inv, &w);
3232   }
3233
3234   if (_ntl_gsign(w) < 0) {
3235      _ntl_gnegate(&w);
3236      _ntl_gnegate(&n);
3237   }
3238
3239   _ntl_gcopy(n, num_out);
3240   _ntl_gcopy(w, den_out);
3241
3242   return 1;
3243}
3244
3245
3246void
3247_ntl_gexp(
3248        _ntl_gbigint a,
3249        long e,
3250        _ntl_gbigint *bb
3251        )
3252{
3253        long k;
3254        long len_a;
3255        static _ntl_gbigint res = 0;
3256
3257        if (!e)
3258        {
3259                _ntl_gone(bb);
3260                return;
3261        }
3262
3263        if (e < 0)
3264                ghalt("negative exponent in _ntl_gexp");
3265
3266        if (_ntl_giszero(a))
3267        {
3268                _ntl_gzero(bb);
3269                return;
3270        }
3271
3272        len_a = _ntl_g2log(a);
3273        if (len_a > (NTL_MAX_LONG-(NTL_ZZ_NBITS-1))/e)
3274                ghalt("overflow in _ntl_gexp");
3275
3276        _ntl_gsetlength(&res, (len_a*e+NTL_ZZ_NBITS-1)/NTL_ZZ_NBITS);
3277
3278        _ntl_gcopy(a, &res);
3279        k = 1;
3280        while ((k << 1) <= e)
3281                k <<= 1;
3282        while (k >>= 1) {
3283                _ntl_gsq(res, &res);
3284                if (e & k)
3285                        _ntl_gmul(a, res, &res);
3286        }
3287
3288        _ntl_gcopy(res, bb);
3289}
3290
3291void
3292_ntl_gexps(
3293        long a,
3294        long e,
3295        _ntl_gbigint *bb
3296        )
3297{
3298        long k;
3299        long len_a;
3300        static _ntl_gbigint res = 0;
3301
3302        if (!e)
3303        {
3304                _ntl_gone(bb);
3305                return;
3306        }
3307
3308        if (e < 0)
3309                ghalt("negative exponent in _ntl_zexps");
3310
3311        if (!a)
3312        {
3313                _ntl_gzero(bb);
3314                return;
3315        }
3316
3317        len_a = _ntl_g2logs(a);
3318        if (len_a > (NTL_MAX_LONG-(NTL_ZZ_NBITS-1))/e)
3319                ghalt("overflow in _ntl_gexps");
3320
3321        _ntl_gsetlength(&res, (len_a*e+NTL_ZZ_NBITS-1)/NTL_ZZ_NBITS);
3322
3323        _ntl_gintoz(a, &res);
3324        k = 1;
3325        while ((k << 1) <= e)
3326                k <<= 1;
3327        while (k >>= 1) {
3328                _ntl_gsq(res, &res);
3329                if (e & k)
3330                        _ntl_gsmul(res, a, &res);
3331        }
3332
3333        _ntl_gcopy(res, bb);
3334}
3335
3336
3337static
3338long OptWinSize(long n)
3339/* finds k that minimizes n/(k+1) + 2^{k-1} */
3340
3341{
3342   long k;
3343   double v, v_new;
3344
3345
3346   v = n/2.0 + 1.0;
3347   k = 1;
3348
3349   for (;;) {
3350      v_new = n/((double)(k+2)) + ((double)(1L << k));
3351      if (v_new >= v) break;
3352      v = v_new;
3353      k++;
3354   }
3355
3356   return k;
3357}
3358
3359
3360
3361/* DIRT: will not work with non-empty "nails" */
3362
3363static
3364mp_limb_t neg_inv_mod_limb(mp_limb_t m0)
3365{
3366   mp_limb_t x; 
3367   long k;
3368
3369   x = 1; 
3370   k = 1; 
3371   while (k < NTL_ZZ_NBITS) {
3372      x += x * (1 - x * m0);
3373      k <<= 1;
3374   }
3375
3376
3377   return - x;
3378}
3379
3380
3381/* Montgomery reduction:
3382 * This computes res = T/b^m mod N, where b = 2^{NTL_ZZ_NBITS}.
3383 * It is assumed that N has n limbs, and that T has at most n + m limbs.
3384 * Also, inv should be set to -N^{-1} mod b.
3385 * Finally, it is assumed that T has space allocated for n + m limbs,
3386 * and that res has space allocated for n limbs. 
3387 * Note: res should not overlap any inputs, and T is destroyed.
3388 * Note: res will have at most n limbs, but may not be fully reduced
3389 * mod N.  In general, we will have res < T/b^m + N.
3390 */
3391
3392/* DIRT: this routine may not work with non-empty "nails" */
3393
3394static
3395void redc(_ntl_gbigint T, _ntl_gbigint N, long m, mp_limb_t inv, 
3396          _ntl_gbigint res) 
3397{
3398   long n, sT, i;
3399   mp_limb_t *Ndata, *Tdata, *resdata, q, d, t, c;
3400
3401   n = SIZE(N);
3402   Ndata = DATA(N);
3403   sT = SIZE(T);
3404   Tdata = DATA(T);
3405   resdata = DATA(res);
3406
3407   for (i = sT; i < m+n; i++)
3408      Tdata[i] = 0;
3409
3410   c = 0;
3411   for (i = 0; i < m; i++) {
3412      q = Tdata[i]*inv;
3413      d = mpn_addmul_1(Tdata+i, Ndata, n, q);
3414      t = Tdata[i+n] + d;
3415      Tdata[i+n] = t + c;
3416      if (t < d || (c == 1 && t + c  == 0)) 
3417         c = 1;
3418      else
3419         c = 0;
3420   }
3421
3422   if (c) {
3423      mpn_sub_n(resdata, Tdata + m, Ndata, n);
3424   }
3425   else {
3426      for (i = 0; i < n; i++)
3427         resdata[i] = Tdata[m + i];
3428   }
3429
3430   i = n;
3431   STRIP(i, resdata);
3432
3433   SIZE(res) = i;
3434   SIZE(T) = 0;
3435}
3436
3437
3438
3439#define REDC_CROSS (32)
3440
3441void _ntl_gpowermod(_ntl_gbigint g, _ntl_gbigint e, _ntl_gbigint F,
3442                    _ntl_gbigint *h)
3443
3444/* h = g^e mod f using "sliding window" algorithm
3445
3446   remark: the notation (h, g, e, F) is strange, because I
3447   copied the code from BB.c.
3448*/
3449
3450{
3451   _ntl_gbigint res, gg, *v, t;
3452   long n, i, k, val, cnt, m;
3453   long use_redc, sF;
3454   mp_limb_t inv;
3455
3456   if (_ntl_gsign(g) < 0 || _ntl_gcompare(g, F) >= 0 || 
3457       _ntl_gscompare(F, 1) <= 0) 
3458      ghalt("PowerMod: bad args");
3459
3460   if (_ntl_gscompare(e, 0) == 0) {
3461      _ntl_gone(h);
3462      return;
3463   }
3464
3465   if (_ntl_gscompare(e, 1) == 0) {
3466      _ntl_gcopy(g, h);
3467      return;
3468   }
3469
3470   if (_ntl_gscompare(e, -1) == 0) {
3471      _ntl_ginvmod(g, F, h);
3472      return;
3473   }
3474
3475   if (_ntl_gscompare(e, 2) == 0) {
3476      _ntl_gsqmod(g, F, h);
3477      return;
3478   }
3479
3480   if (_ntl_gscompare(e, -2) == 0) {
3481      res = 0;
3482      _ntl_gsqmod(g, F, &res);
3483      _ntl_ginvmod(res, F, h);
3484      _ntl_gfree(&res);
3485      return;
3486   }
3487
3488   n = _ntl_g2log(e);
3489
3490   sF = SIZE(F);
3491
3492   res = 0;
3493   _ntl_gsetlength(&res, sF*2);
3494
3495   t = 0;
3496   _ntl_gsetlength(&t, sF*2);
3497
3498   use_redc = (DATA(F)[0] & 1) && sF < REDC_CROSS;
3499
3500   gg = 0;
3501
3502   if (use_redc) {
3503      _ntl_glshift(g, sF*NTL_ZZ_NBITS, &res);
3504      _ntl_gmod(res, F, &gg);
3505
3506      inv = neg_inv_mod_limb(DATA(F)[0]);
3507   }
3508   else
3509      _ntl_gcopy(g, &gg);
3510
3511
3512   if (_ntl_gscompare(g, 2) == 0) {
3513      /* plain square-and-multiply algorithm, optimized for g == 2 */
3514
3515      _ntl_gbigint F1 = 0;
3516
3517      if (use_redc) {
3518         long shamt;
3519
3520         COUNT_BITS(shamt, DATA(F)[sF-1]);
3521         shamt = NTL_ZZ_NBITS - shamt;
3522         _ntl_glshift(F, shamt, &F1);
3523      }
3524
3525      _ntl_gcopy(gg, &res);
3526
3527      for (i = n - 2; i >= 0; i--) {
3528         _ntl_gsq(res, &t);
3529         if (use_redc) redc(t, F, sF, inv, res); else _ntl_gmod(t, F, &res);
3530
3531         if (_ntl_gbit(e, i)) {
3532            _ntl_gadd(res, res, &res);
3533
3534            if (use_redc) {
3535               while (SIZE(res) > sF) {
3536                  _ntl_gsubpos(res, F1, &res);
3537               }
3538            }
3539            else {
3540               if (_ntl_gcompare(res, F) >= 0)
3541                  _ntl_gsubpos(res, F, &res);
3542            }
3543         }
3544      }
3545
3546
3547      if (use_redc) {
3548         _ntl_gcopy(res, &t);
3549         redc(t, F, sF, inv, res);
3550         if (_ntl_gcompare(res, F) >= 0) {
3551            _ntl_gsub(res, F, &res);
3552         }
3553      }
3554
3555      if (_ntl_gsign(e) < 0) _ntl_ginvmod(res, F, &res);
3556
3557      _ntl_gcopy(res, h);
3558      _ntl_gfree(&res);
3559      _ntl_gfree(&gg);
3560      _ntl_gfree(&t);
3561      _ntl_gfree(&F1);
3562      return;
3563   }
3564
3565
3566   if (n < 16) { 
3567      /* plain square-and-multiply algorithm */
3568
3569      _ntl_gcopy(gg, &res);
3570
3571      for (i = n - 2; i >= 0; i--) {
3572         _ntl_gsq(res, &t);
3573         if (use_redc) redc(t, F, sF, inv, res); else _ntl_gmod(t, F, &res);
3574
3575         if (_ntl_gbit(e, i)) {
3576            _ntl_gmul(res, gg, &t);
3577            if (use_redc) redc(t, F, sF, inv, res); else _ntl_gmod(t, F, &res);
3578         }
3579      }
3580
3581
3582      if (use_redc) {
3583         _ntl_gcopy(res, &t);
3584         redc(t, F, sF, inv, res);
3585         if (_ntl_gcompare(res, F) >= 0) {
3586            _ntl_gsub(res, F, &res);
3587         }
3588      }
3589
3590      if (_ntl_gsign(e) < 0) _ntl_ginvmod(res, F, &res);
3591
3592      _ntl_gcopy(res, h);
3593      _ntl_gfree(&res);
3594      _ntl_gfree(&gg);
3595      _ntl_gfree(&t);
3596      return;
3597   }
3598
3599   k = OptWinSize(n);
3600
3601   if (k > 5) k = 5;
3602
3603   v = (_ntl_gbigint *) NTL_MALLOC((1L << (k-1)), sizeof(_ntl_gbigint), 0);
3604   if (!v) ghalt("out of memory");
3605   for (i = 0; i < (1L << (k-1)); i++) {
3606      v[i] = 0; 
3607      _ntl_gsetlength(&v[i], sF);
3608   }
3609
3610   _ntl_gcopy(gg, &v[0]);
3611 
3612   if (k > 1) {
3613      _ntl_gsq(gg, &t);
3614      if (use_redc) redc(t, F, sF, inv, res); else _ntl_gmod(t, F, &res);
3615
3616      for (i = 1; i < (1L << (k-1)); i++) {
3617         _ntl_gmul(v[i-1], res, &t);
3618         if (use_redc) redc(t, F, sF, inv, v[i]); else _ntl_gmod(t, F, &v[i]);
3619      }
3620   }
3621
3622   _ntl_gcopy(gg, &res);
3623
3624   val = 0;
3625   for (i = n-2; i >= 0; i--) {
3626      val = (val << 1) | _ntl_gbit(e, i); 
3627      if (val == 0) {
3628         _ntl_gsq(res, &t);
3629         if (use_redc) redc(t, F, sF, inv, res); else _ntl_gmod(t, F, &res);
3630      }
3631      else if (val >= (1L << (k-1)) || i == 0) {
3632         cnt = 0;
3633         while ((val & 1) == 0) {
3634            val = val >> 1;
3635            cnt++;
3636         }
3637
3638         m = val;
3639         while (m > 0) {
3640            _ntl_gsq(res, &t);
3641            if (use_redc) redc(t, F, sF, inv, res); else _ntl_gmod(t, F, &res);
3642            m = m >> 1;
3643         }
3644
3645         _ntl_gmul(res, v[val >> 1], &t);
3646         if (use_redc) redc(t, F, sF, inv, res); else _ntl_gmod(t, F, &res);
3647
3648         while (cnt > 0) {
3649            _ntl_gsq(res, &t);
3650            if (use_redc) redc(t, F, sF, inv, res); else _ntl_gmod(t, F, &res);
3651            cnt--;
3652         }
3653
3654         val = 0;
3655      }
3656   }
3657
3658   if (use_redc) {
3659      _ntl_gcopy(res, &t);
3660      redc(t, F, sF, inv, res);
3661      if (_ntl_gcompare(res, F) >= 0) {
3662         _ntl_gsub(res, F, &res);
3663      }
3664   }
3665
3666   if (_ntl_gsign(e) < 0) _ntl_ginvmod(res, F, &res);
3667
3668   _ntl_gcopy(res, h);
3669
3670   _ntl_gfree(&res);
3671   _ntl_gfree(&gg);
3672   _ntl_gfree(&t);
3673   for (i = 0; i < (1L << (k-1)); i++)
3674      _ntl_gfree(&v[i]);
3675   free(v);
3676}
3677
3678long _ntl_gsize(_ntl_gbigint rep)
3679{
3680   if (!rep)
3681      return 0;
3682   else if (SIZE(rep) < 0)
3683      return -SIZE(rep);
3684   else
3685      return SIZE(rep);
3686}
3687
3688long _ntl_gisone(_ntl_gbigint rep)
3689{
3690   return rep != 0 && SIZE(rep) == 1 && DATA(rep)[0] == 1;
3691}
3692
3693long _ntl_gsptest(_ntl_gbigint rep)
3694{
3695   return !rep || SIZE(rep) == 0 ||
3696          ((SIZE(rep) == 1 || SIZE(rep) == -1) && 
3697           DATA(rep)[0] < ((mp_limb_t) NTL_SP_BOUND));
3698}
3699
3700long _ntl_gwsptest(_ntl_gbigint rep)
3701{
3702   return !rep || SIZE(rep) == 0 ||
3703          ((SIZE(rep) == 1 || SIZE(rep) == -1) && 
3704           DATA(rep)[0] < ((mp_limb_t) NTL_WSP_BOUND));
3705}
3706
3707
3708
3709long _ntl_gcrtinrange(_ntl_gbigint g, _ntl_gbigint a)
3710{
3711   long sa, sg, i; 
3712   mp_limb_t carry, u, v;
3713   mp_limb_t *adata, *gdata;
3714
3715   if (!a || SIZE(a) <= 0) return 0;
3716
3717   sa = SIZE(a);
3718
3719   if (!g) return 1;
3720
3721   sg = SIZE(g);
3722
3723   if (sg == 0) return 1;
3724
3725   if (sg < 0) sg = -sg;
3726
3727   if (sa-sg > 1) return 1;
3728
3729   if (sa-sg < 0) return 0;
3730
3731   adata = DATA(a);
3732   gdata = DATA(g);
3733
3734   carry=0;
3735
3736   if (sa-sg == 1) {
3737      if (adata[sa-1] > ((mp_limb_t) 1)) return 1;
3738      carry = 1;
3739   }
3740
3741   i = sg-1;
3742   u = 0;
3743   v = 0;
3744   while (i >= 0 && u == v) {
3745      u = (carry << (NTL_ZZ_NBITS-1)) + (adata[i] >> 1);
3746      v = gdata[i];
3747      carry = (adata[i] & 1);
3748      i--;
3749   }
3750
3751   if (u == v) {
3752      if (carry) return 1;
3753      return (SIZE(g) > 0);
3754   }
3755   else
3756      return (u > v);
3757}
3758
3759
3760
3761/* DIRT: this routine will not work with non-empty "nails" */
3762
3763void _ntl_gfrombytes(_ntl_gbigint *x, const unsigned char *p, long n)
3764{
3765   long BytesPerLimb;
3766   long lw, r, i, j;
3767   mp_limb_t *xp, t;
3768
3769   if (n <= 0) {
3770      x = 0;
3771      return;
3772   }
3773
3774   BytesPerLimb = NTL_ZZ_NBITS/8;
3775
3776
3777   lw = n/BytesPerLimb;
3778   r = n - lw*BytesPerLimb;
3779
3780   if (r != 0) 
3781      lw++;
3782   else
3783      r = BytesPerLimb;
3784
3785   _ntl_gsetlength(x, lw); 
3786   xp = DATA(*x);
3787
3788   for (i = 0; i < lw-1; i++) {
3789      t = 0;
3790      for (j = 0; j < BytesPerLimb; j++) {
3791         t >>= 8;
3792         t += (((mp_limb_t)(*p)) & ((mp_limb_t) 255)) << ((BytesPerLimb-1)*8);
3793         p++;
3794      }
3795      xp[i] = t;
3796   }
3797
3798   t = 0;
3799   for (j = 0; j < r; j++) {
3800      t >>= 8;
3801      t += (((mp_limb_t)(*p)) & ((mp_limb_t) 255)) << ((BytesPerLimb-1)*8);
3802      p++;
3803   }
3804
3805   t >>= (BytesPerLimb-r)*8;
3806   xp[lw-1] = t;
3807
3808   STRIP(lw, xp);
3809   SIZE(*x) = lw; 
3810}
3811
3812
3813
3814/* DIRT: this routine will not work with non-empty "nails" */
3815
3816void _ntl_gbytesfromz(unsigned char *p, _ntl_gbigint a, long n)
3817{
3818   long BytesPerLimb;
3819   long lbits, lbytes, min_bytes, min_words, r;
3820   long i, j;
3821   mp_limb_t *ap, t;
3822
3823   if (n < 0) n = 0;
3824
3825   BytesPerLimb = NTL_ZZ_NBITS/8;
3826
3827   lbits = _ntl_g2log(a);
3828   lbytes = (lbits+7)/8;
3829
3830   min_bytes = (lbytes < n) ? lbytes : n;
3831
3832   min_words = min_bytes/BytesPerLimb;
3833
3834   r = min_bytes - min_words*BytesPerLimb;
3835   if (r != 0)
3836      min_words++;
3837   else
3838      r = BytesPerLimb;
3839
3840   if (a)
3841      ap = DATA(a);
3842   else
3843      ap = 0;
3844
3845
3846   for (i = 0; i < min_words-1; i++) {
3847      t = ap[i];
3848      for (j = 0; j < BytesPerLimb; j++) {
3849         *p = t & ((mp_limb_t) 255);
3850         t >>= 8;
3851         p++;
3852      }
3853   }
3854
3855   if (min_words > 0) {
3856      t = ap[min_words-1];
3857      for (j = 0; j < r; j++) {
3858         *p = t & ((mp_limb_t) 255);
3859         t >>= 8;
3860         p++;
3861      }
3862   }
3863
3864   for (j = min_bytes; j < n; j++) {
3865      *p = 0;
3866      p++;
3867   }
3868}
3869
3870
3871
3872
3873long _ntl_gblock_construct_alloc(_ntl_gbigint *x, long d, long n)
3874{
3875   long d1, sz, AllocAmt, m, j, alloc;
3876   char *p;
3877   _ntl_gbigint t;
3878
3879
3880   /* check n value */
3881
3882   if (n <= 0)
3883      ghalt("block construct: n must be positive");
3884
3885
3886
3887   /* check d value */
3888
3889   if (d <= 0)
3890      ghalt("block construct: d must be positive");
3891
3892   if (NTL_OVERFLOW(d, NTL_ZZ_NBITS, NTL_ZZ_NBITS))
3893      ghalt("block construct: d too large");
3894
3895#ifdef NTL_SMALL_MP_SIZE_T
3896   /* this makes sure that numbers don't get too big for GMP */
3897   if (d >= (1L << (NTL_BITS_PER_INT-4)))
3898      ghalt("size too big for GMP");
3899#endif
3900
3901   d1 = d + 1;
3902
3903   if (STORAGE_OVF(d1))
3904      ghalt("block construct: d too large");
3905
3906
3907
3908   sz = STORAGE(d1);
3909
3910   AllocAmt = NTL_MAX_ALLOC_BLOCK/sz;
3911   if (AllocAmt == 0) AllocAmt = 1;
3912
3913   if (AllocAmt < n)
3914      m = AllocAmt;
3915   else
3916      m = n;
3917
3918   p = (char *) NTL_MALLOC(m, sz, 0);
3919   if (!p) ghalt("out of memory in _ntl_gblock_construct");
3920
3921   *x = (_ntl_gbigint) p;
3922
3923   for (j = 0; j < m; j++) {
3924      t = (_ntl_gbigint) p;
3925      alloc = (d1 << 2) | 1;
3926      if (j < m-1) alloc |= 2;
3927      ALLOC(t) = alloc;
3928      SIZE(t) = 0;
3929      p += sz;
3930   }
3931
3932   return m;
3933}
3934
3935
3936void _ntl_gblock_construct_set(_ntl_gbigint x, _ntl_gbigint *y, long i)
3937{
3938   long d1, sz;
3939
3940
3941   d1 = ALLOC(x) >> 2;
3942   sz = STORAGE(d1);
3943
3944   *y = (_ntl_gbigint) (((char *) x) + i*sz);
3945}
3946
3947
3948long _ntl_gblock_destroy(_ntl_gbigint x)
3949{
3950   long d1, sz, alloc, m;
3951   char *p;
3952   _ntl_gbigint t;
3953
3954   
3955   d1 = ALLOC(x) >> 2;
3956   sz = STORAGE(d1);
3957
3958   p = (char *) x;
3959
3960   m = 1;
3961
3962   for (;;) {
3963      t = (_ntl_gbigint) p;
3964      alloc = ALLOC(t);
3965      if ((alloc & 1) == 0) 
3966         ghalt("corrupted memory detected in _ntl_gblock_destroy");
3967      if ((alloc & 2) == 0) break;
3968      m++;
3969      p += sz;
3970   }
3971
3972   free(x);
3973   return m;
3974}
3975
3976
3977long _ntl_gblock_storage(long d)
3978{
3979   long d1, sz; 
3980
3981   d1 = d + 1;
3982   sz = STORAGE(d1) + sizeof(_ntl_gbigint);
3983
3984   return sz;
3985}
3986
3987
3988/*
3989 * This is a completely portable MulMod routine.
3990 */
3991
3992#define SP_MUL_MOD(r, a, b, n)  \
3993{  \
3994   long l__a = (a);  \
3995   long l__b = (b);  \
3996   long l__n = (n);  \
3997   long l__q;  \
3998   unsigned long l__res;  \
3999  \
4000   l__q  = (long) ((((double) l__a) * ((double) l__b)) / ((double) l__n));  \
4001   l__res = ((unsigned long) l__a)*((unsigned long) l__b) - \
4002            ((unsigned long) l__q)*((unsigned long) l__n);  \
4003   if (l__res >> (NTL_BITS_PER_LONG-1))  \
4004      l__res += l__n;  \
4005   else if (((long) l__res) >= l__n)  \
4006      l__res -= l__n;  \
4007  \
4008   r = (long) l__res;  \
4009}
4010
4011
4012
4013
4014#if (NTL_ARITH_RIGHT_SHIFT && defined(NTL_AVOID_BRANCHING) && !defined(NTL_CLEAN_INT))
4015
4016#define SP_MUL_MOD2(res, a, b, n, bninv) \
4017do {  \
4018   long _a = (a);  \
4019   long _b = (b);  \
4020   long _n = (n);  \
4021   double _bninv = (bninv);  \
4022   long _q, _res;  \
4023  \
4024   _q  = (long) (((double) _a) * _bninv);  \
4025   _res = _a*_b - _q*_n;  \
4026  \
4027   _res += (_res >> (NTL_BITS_PER_LONG-1)) & _n;  \
4028   _res -= _n;  \
4029   _res += (_res >> (NTL_BITS_PER_LONG-1)) & _n;  \
4030  \
4031   res = _res;  \
4032} while (0) 
4033
4034#else
4035
4036/*
4037 * This is a completely portable MulMod routine.
4038 */
4039
4040#define SP_MUL_MOD2(res, a, b, n, bninv) \
4041do { \
4042   long _a = (a); \
4043   long _b = (b); \
4044   long _n = (n); \
4045   double _bninv = (bninv); \
4046   long _q;  \
4047   unsigned long _res; \
4048 \
4049   _q  = (long) (((double) _a) * _bninv); \
4050   _res = ((unsigned long) _a)*((unsigned long) _b)  - \
4051          ((unsigned long) _q)*((unsigned long) _n); \
4052 \
4053   if (_res >> (NTL_BITS_PER_LONG-1))  \
4054      _res += _n;  \
4055   else if (((long) _res) >= _n)  \
4056      _res -= _n;  \
4057 \
4058   res = (long) _res; \
4059} while (0)
4060
4061#endif
4062
4063
4064static
4065long SpecialPower(long e, long p)
4066{
4067   long a;
4068   long x, y;
4069
4070   a = (long) ((((mp_limb_t) 1) << (NTL_ZZ_NBITS-2)) % ((mp_limb_t) p));
4071   SP_MUL_MOD(a, a, 2, p);
4072   SP_MUL_MOD(a, a, 2, p);
4073
4074   x = 1;
4075   y = a;
4076   while (e) {
4077      if (e & 1) SP_MUL_MOD(x, x, y, p);
4078      SP_MUL_MOD(y, y, y, p);
4079      e = e >> 1;
4080   }
4081
4082   return x;
4083}
4084
4085
4086static
4087void sp_ext_eucl(long *dd, long *ss, long *tt, long a, long b)
4088{
4089   long  u, v, u0, v0, u1, v1, u2, v2, q, r;
4090
4091   long aneg = 0, bneg = 0;
4092
4093   if (a < 0) {
4094      if (a < -NTL_MAX_LONG) ghalt("integer overflow");
4095      a = -a;
4096      aneg = 1;
4097   }
4098
4099   if (b < 0) {
4100      if (b < -NTL_MAX_LONG) ghalt("integer overflow");
4101      b = -b;
4102      bneg = 1;
4103   }
4104
4105   u1=1; v1=0;
4106   u2=0; v2=1;
4107   u = a; v = b;
4108
4109   while (v != 0) {
4110      q = u / v;
4111      r = u % v;
4112      u = v;
4113      v = r;
4114      u0 = u2;
4115      v0 = v2;
4116      u2 =  u1 - q*u2;
4117      v2 = v1- q*v2;
4118      u1 = u0;
4119      v1 = v0;
4120   }
4121
4122   if (aneg)
4123      u1 = -u1;
4124
4125   if (bneg)
4126      v1 = -v1;
4127
4128   *dd = u;
4129   *ss = u1;
4130   *tt = v1;
4131}
4132
4133static
4134long sp_inv_mod(long a, long n)
4135{
4136   long d, s, t;
4137
4138   sp_ext_eucl(&d, &s, &t, a, n);
4139   if (d != 1) ghalt("inverse undefined");
4140   if (s < 0)
4141      return s + n;
4142   else
4143      return s;
4144}
4145
4146/* ------ HERE ------ */
4147
4148
4149
4150struct crt_body_gmp {
4151   _ntl_gbigint *v;
4152   long sbuf;
4153   long n;
4154   _ntl_gbigint buf;
4155};
4156
4157struct crt_body_gmp1 {
4158   long n;
4159   long levels;
4160   long *primes;
4161   long *inv_vec;
4162   long *val_vec;
4163   long *index_vec;
4164   _ntl_gbigint *prod_vec;
4165   _ntl_gbigint *rem_vec;
4166   _ntl_gbigint *coeff_vec;
4167   _ntl_gbigint temps[2];
4168   _ntl_gbigint modulus;
4169};
4170
4171
4172struct crt_body {
4173   long strategy;
4174
4175   union {
4176      struct crt_body_gmp G;
4177      struct crt_body_gmp1 G1;
4178   } U;
4179};
4180
4181
4182
4183
4184void _ntl_gcrt_struct_init(void **crt_struct, long n, _ntl_gbigint p,
4185                          const long *primes)
4186{
4187   struct crt_body *c;
4188
4189   c = (struct crt_body *) NTL_MALLOC(1, sizeof(struct crt_body), 0);
4190   if (!c) ghalt("out of memory");
4191
4192   if (n >= 600) {
4193      struct crt_body_gmp1 *C = &c->U.G1;
4194      long *q;
4195      long i, j;
4196      long levels, vec_len;
4197      long *val_vec, *inv_vec;
4198      long *index_vec;
4199      _ntl_gbigint *prod_vec, *rem_vec, *coeff_vec;
4200      _ntl_gbigint *temps;
4201
4202      C->modulus = 0;
4203      _ntl_gcopy(p, &C->modulus);
4204
4205      temps = &C->temps[0];
4206
4207      temps[0] = 0;
4208      temps[1] = 0;
4209   
4210      q = (long *) NTL_MALLOC(n, sizeof(long), 0);
4211      if (!q) ghalt("out of memory");
4212
4213      val_vec = (long *) NTL_MALLOC(n, sizeof(long), 0);
4214      if (!val_vec) ghalt("out of memory");
4215
4216      inv_vec = (long *) NTL_MALLOC(n, sizeof(long), 0);
4217      if (!inv_vec) ghalt("out of memory");
4218
4219      for (i = 0; i < n; i++)
4220         q[i] = primes[i];
4221
4222      levels = 0;
4223      while ((n >> levels) >= 16) levels++;
4224
4225      vec_len = (1L << levels) - 1;
4226
4227      index_vec = (long *) NTL_MALLOC((vec_len+1), sizeof(long), 0);
4228      if (!index_vec) ghalt("out of memory");
4229
4230      prod_vec = (_ntl_gbigint *) NTL_MALLOC(vec_len, sizeof(_ntl_gbigint), 0);
4231      if (!prod_vec) ghalt("out of memory");
4232
4233      rem_vec = (_ntl_gbigint *) NTL_MALLOC(vec_len, sizeof(_ntl_gbigint), 0);
4234      if (!rem_vec) ghalt("out of memory");
4235
4236      coeff_vec = (_ntl_gbigint *) NTL_MALLOC(n, sizeof(_ntl_gbigint), 0);
4237      if (!coeff_vec) ghalt("out of memory");
4238
4239      for (i = 0; i < vec_len; i++)
4240         prod_vec[i] = 0;
4241
4242      for (i = 0; i < vec_len; i++)
4243         rem_vec[i] = 0;
4244
4245      for (i = 0; i < n; i++)
4246         coeff_vec[i] = 0;
4247
4248      index_vec[0] = 0;
4249      index_vec[1] = n;
4250
4251      for (i = 0; i <= levels-2; i++) {
4252         long start = (1L << i) - 1;
4253         long finish = (1L << (i+1)) - 2;
4254         for (j = finish; j >= start; j--) {
4255            index_vec[2*j+2] = index_vec[j] + (index_vec[j+1] - index_vec[j])/2;
4256            index_vec[2*j+1] = index_vec[j];
4257         }
4258         index_vec[2*finish+3] = n;
4259      }
4260
4261      for (i = (1L << (levels-1)) - 1; i < vec_len; i++) {
4262         /* multiply primes index_vec[i]..index_vec[i+1]-1 into
4263          * prod_vec[i]
4264          */
4265
4266         _ntl_gone(&prod_vec[i]);
4267         for (j = index_vec[i]; j < index_vec[i+1]; j++)
4268            _ntl_gsmul(prod_vec[i], q[j], &prod_vec[i]);
4269      }
4270
4271      for (i = (1L << (levels-1)) - 1; i < vec_len; i++) {
4272         for (j = index_vec[i]; j < index_vec[i+1]; j++)
4273            _ntl_gsdiv(prod_vec[i], q[j], &coeff_vec[j]);
4274      }
4275
4276      for (i = (1L << (levels-1)) - 2; i >= 0; i--)
4277         _ntl_gmul(prod_vec[2*i+1], prod_vec[2*i+2], &prod_vec[i]);
4278
4279
4280      /* the following is asymptotically the bottleneck...but it
4281       * it probably doesn't matter. */
4282
4283      for (i = 0; i < n; i++) {
4284         long tt;
4285         _ntl_gsdiv(prod_vec[0], q[i], &temps[0]);
4286         tt = mpn_mod_1(DATA(temps[0]), SIZE(temps[0]), q[i]);
4287         inv_vec[i] = sp_inv_mod(tt, q[i]);
4288      }
4289
4290      c->strategy = 2;
4291      C->n = n;
4292      C->primes = q;
4293      C->val_vec = val_vec;
4294      C->inv_vec = inv_vec;
4295      C->levels = levels;
4296      C->index_vec = index_vec;
4297      C->prod_vec = prod_vec;
4298      C->rem_vec = rem_vec;
4299      C->coeff_vec = coeff_vec;
4300
4301      *crt_struct = (void *) c;
4302      return;
4303   }
4304
4305   {
4306      struct crt_body_gmp *C = &c->U.G;
4307      long i;
4308      c->strategy = 1;
4309
4310      C->n = n;
4311      C->v = (_ntl_gbigint *) NTL_MALLOC(n, sizeof(_ntl_gbigint), 0);
4312      if (!C->v) ghalt("out of memory");
4313
4314      for (i = 0; i < n; i++)
4315         C->v[i] = 0;
4316
4317      C->sbuf = SIZE(p)+2;
4318
4319      C->buf = 0;
4320      _ntl_gsetlength(&C->buf, C->sbuf);
4321
4322      *crt_struct = (void *) c;
4323      return;
4324   }
4325}
4326
4327void _ntl_gcrt_struct_insert(void *crt_struct, long i, _ntl_gbigint m)
4328{
4329   struct crt_body *c = (struct crt_body *) crt_struct;
4330
4331   switch (c->strategy) {
4332   case 1: {
4333      _ntl_gcopy(m, &c->U.G.v[i]);
4334      break;
4335   }
4336
4337   default:
4338      ghalt("_ntl_gcrt_struct_insert: inconsistent strategy");
4339
4340   } /* end switch */
4341}
4342
4343
4344void _ntl_gcrt_struct_free(void *crt_struct)
4345{
4346   struct crt_body *c = (struct crt_body *) crt_struct;
4347
4348   switch (c->strategy) {
4349   case 1: {
4350      struct crt_body_gmp *C = &c->U.G;
4351      long i, n;
4352
4353      n = C->n;
4354
4355      for (i = 0; i < n; i++)
4356         _ntl_gfree(&C->v[i]);
4357
4358      _ntl_gfree(&C->buf);
4359
4360      free(C->v);
4361
4362      free(c);
4363      break;
4364   }
4365
4366   case 2: { 
4367      struct crt_body_gmp1 *C = &c->U.G1;
4368      long n = C->n;
4369      long levels = C->levels;
4370      long *primes = C->primes;
4371      long *inv_vec = C->inv_vec;
4372      long *val_vec = C->val_vec;
4373      long *index_vec = C->index_vec;
4374      _ntl_gbigint *prod_vec = C->prod_vec;
4375      _ntl_gbigint *rem_vec = C->rem_vec;
4376      _ntl_gbigint *coeff_vec = C->coeff_vec;
4377      _ntl_gbigint *temps = C->temps;
4378      _ntl_gbigint modulus = C->modulus;
4379      long vec_len = (1L << levels) - 1;
4380
4381      long i;
4382
4383      for (i = 0; i < vec_len; i++)
4384         _ntl_gfree(&prod_vec[i]);
4385
4386      for (i = 0; i < vec_len; i++)
4387         _ntl_gfree(&rem_vec[i]);
4388
4389      for (i = 0; i < n; i++)
4390         _ntl_gfree(&coeff_vec[i]);
4391
4392      _ntl_gfree(&temps[0]);
4393      _ntl_gfree(&temps[1]);
4394
4395      _ntl_gfree(&modulus);
4396
4397      free(primes);
4398      free(inv_vec);
4399      free(val_vec);
4400      free(index_vec);
4401      free(prod_vec);
4402      free(rem_vec);
4403      free(coeff_vec);
4404
4405      free(c);
4406      break;
4407   }
4408
4409   default:
4410
4411      ghalt("_ntl_gcrt_struct_free: inconsistent strategy");
4412
4413   } /* end case */
4414}
4415
4416static
4417void gadd_mul_many(_ntl_gbigint *res, _ntl_gbigint *a, long *b, 
4418                      long n, long sz)
4419
4420{
4421   mp_limb_t *xx, *yy; 
4422   long i, sx;
4423   long sy;
4424   mp_limb_t carry;
4425
4426   sx = sz + 2;
4427   if (MustAlloc(*res, sx))
4428      _ntl_gsetlength(res, sx);
4429
4430   xx = DATA(*res);
4431
4432   for (i = 0; i < sx; i++)
4433      xx[i] = 0;
4434
4435   for (i = 0; i < n; i++) {
4436      if (!a[i]) continue;
4437
4438      yy = DATA(a[i]);
4439      sy = SIZE(a[i]); 
4440
4441      if (!sy || !b[i]) continue;
4442
4443      carry = mpn_addmul_1(xx, yy, sy, b[i]);
4444      yy = xx + sy;
4445      *yy += carry;
4446
4447      if (*yy < carry) { /* unsigned comparison! */
4448         do {
4449            yy++;
4450            *yy += 1;
4451         } while (*yy == 0);
4452      }
4453   }
4454
4455   while (sx > 0 && xx[sx-1] == 0) sx--;
4456   SIZE(*res) = sx;
4457}
4458
4459void _ntl_gcrt_struct_eval(void *crt_struct, _ntl_gbigint *x, const long *b)
4460{
4461   struct crt_body *c = (struct crt_body *) crt_struct;
4462
4463   switch (c->strategy) {
4464
4465   case 1: {
4466      struct crt_body_gmp *C = &c->U.G;
4467
4468      mp_limb_t *xx, *yy; 
4469      _ntl_gbigint *a;
4470      long i, sx, n;
4471      long sy;
4472      mp_limb_t carry;
4473   
4474      n = C->n;
4475      sx = C->sbuf;
4476   
4477      xx = DATA(C->buf);
4478
4479      for (i = 0; i < sx; i++)
4480         xx[i] = 0;
4481   
4482      a = C->v;
4483   
4484      for (i = 0; i < n; i++) {
4485         if (!a[i]) continue;
4486
4487         yy = DATA(a[i]);
4488         sy = SIZE(a[i]); 
4489   
4490         if (!sy || !b[i]) continue;
4491   
4492         carry = mpn_addmul_1(xx, yy, sy, b[i]);
4493         yy = xx + sy;
4494         *yy += carry;
4495
4496         if (*yy < carry) { /* unsigned comparison! */
4497            do {
4498               yy++;
4499               *yy += 1;
4500            } while (*yy == 0);
4501         }
4502      }
4503   
4504      while (sx > 0 && xx[sx-1] == 0) sx--;
4505      SIZE(C->buf) = sx;
4506      _ntl_gcopy(C->buf, x);
4507      break;
4508   }
4509
4510   case 2: {
4511      struct crt_body_gmp1 *C = &c->U.G1;
4512
4513      long n = C->n;
4514      long levels = C->levels;
4515      long *primes = C->primes;
4516      long *inv_vec = C->inv_vec;
4517      long *val_vec = C->val_vec;
4518      long *index_vec = C->index_vec;
4519      _ntl_gbigint *prod_vec = C->prod_vec;
4520      _ntl_gbigint *rem_vec = C->rem_vec;
4521      _ntl_gbigint *coeff_vec = C->coeff_vec;
4522      _ntl_gbigint *temps = C->temps;
4523      long vec_len = (1L << levels) - 1;
4524
4525      long i, j;
4526
4527      for (i = 0; i < n; i++) {
4528         SP_MUL_MOD(val_vec[i], b[i], inv_vec[i], primes[i]);
4529      }
4530
4531      for (i = (1L << (levels-1)) - 1; i < vec_len; i++) {
4532         long j1 = index_vec[i];
4533         long j2 = index_vec[i+1];
4534         gadd_mul_many(&rem_vec[i], &coeff_vec[j1], &val_vec[j1], j2-j1, 
4535                          SIZE(prod_vec[i]));
4536      }
4537
4538      for (i = (1L << (levels-1)) - 2; i >= 0; i--) {
4539         _ntl_gmul(prod_vec[2*i+1], rem_vec[2*i+2], &temps[0]);
4540         _ntl_gmul(rem_vec[2*i+1], prod_vec[2*i+2], &temps[1]);
4541         _ntl_gadd(temps[0], temps[1], &rem_vec[i]);
4542      }
4543
4544      /* temps[0] = rem_vec[0] mod prod_vec[0] (least absolute residue) */
4545      _ntl_gmod(rem_vec[0], prod_vec[0], &temps[0]);
4546      _ntl_gsub(temps[0], prod_vec[0], &temps[1]);
4547      _ntl_gnegate(&temps[1]);
4548      if (_ntl_gcompare(temps[0], temps[1]) > 0) {
4549         _ntl_gnegate(&temps[1]);
4550         _ntl_gcopy(temps[1], &temps[0]);
4551      }
4552
4553      _ntl_gmod(temps[0], C->modulus, &temps[1]);
4554      _ntl_gcopy(temps[1], x);
4555
4556      break;
4557   }
4558
4559   default:
4560
4561      ghalt("_crt_gstruct_eval: inconsistent strategy");
4562
4563   } /* end case */
4564
4565}
4566
4567
4568long _ntl_gcrt_struct_special(void *crt_struct)
4569{
4570   struct crt_body *c = (struct crt_body *) crt_struct;
4571   return (c->strategy == 2);
4572}
4573
4574
4575struct rem_body_lip {
4576   long n;
4577   long *primes;
4578};
4579
4580struct rem_body_gmp {
4581   long n;
4582   long levels;
4583   long *primes;
4584   long *index_vec;
4585   _ntl_gbigint *prod_vec;
4586   _ntl_gbigint *rem_vec;
4587};
4588
4589
4590struct rem_body_gmp1 {
4591   long n;
4592   long levels;
4593   long *primes;
4594   long *index_vec;
4595   long *len_vec;
4596   mp_limb_t *inv_vec;
4597   long *corr_vec;
4598   double *corraux_vec;
4599   _ntl_gbigint *prod_vec;
4600   _ntl_gbigint *rem_vec;
4601};
4602
4603
4604struct rem_body {
4605   long strategy;
4606
4607   union {
4608      struct rem_body_lip L;
4609      struct rem_body_gmp G;
4610      struct rem_body_gmp1 G1;
4611   } U;
4612};
4613
4614
4615
4616
4617void _ntl_grem_struct_init(void **rem_struct, long n, _ntl_gbigint modulus,
4618                          const long *p)
4619{
4620   struct rem_body *r;
4621
4622   r = (struct rem_body *) NTL_MALLOC(1, sizeof(struct rem_body), 0);
4623   if (!r) ghalt("out of memory");
4624
4625   if (n >= 32 && n <= 256) {
4626      struct rem_body_gmp1 *R = &r->U.G1;
4627
4628      long *q;
4629      long i, j;
4630      long levels, vec_len;
4631      long *index_vec;
4632      long *len_vec, *corr_vec;
4633      double *corraux_vec;
4634      mp_limb_t *inv_vec;
4635      _ntl_gbigint *prod_vec, *rem_vec;
4636   
4637      q = (long *) NTL_MALLOC(n, sizeof(long), 0);
4638      if (!q) ghalt("out of memory");
4639   
4640      for (i = 0; i < n; i++)
4641         q[i] = p[i];
4642
4643      levels = 0;
4644      while ((n >> levels) >= 4) levels++;
4645
4646      vec_len = (1L << levels) - 1;
4647
4648      index_vec = (long *) NTL_MALLOC((vec_len+1), sizeof(long), 0);
4649      if (!index_vec) ghalt("out of memory");
4650
4651      len_vec = (long *) NTL_MALLOC(vec_len, sizeof(long), 0);
4652      if (!len_vec) ghalt("out of memory");
4653
4654      inv_vec = (mp_limb_t *) NTL_MALLOC(vec_len, sizeof(mp_limb_t), 0);
4655      if (!inv_vec) ghalt("out of memory");
4656
4657      corr_vec = (long *) NTL_MALLOC(n, sizeof(long), 0);
4658      if (!corr_vec) ghalt("out of memory");
4659
4660      corraux_vec = (double *) NTL_MALLOC(n, sizeof(double), 0);
4661      if (!corraux_vec) ghalt("out of memory");
4662
4663      prod_vec = (_ntl_gbigint *) NTL_MALLOC(vec_len, sizeof(_ntl_gbigint), 0);
4664      if (!prod_vec) ghalt("out of memory");
4665
4666      rem_vec = (_ntl_gbigint *) NTL_MALLOC(vec_len, sizeof(_ntl_gbigint), 0);
4667      if (!rem_vec) ghalt("out of memory");
4668
4669      for (i = 0; i < vec_len; i++)
4670         prod_vec[i] = 0;
4671
4672      for (i = 0; i < vec_len; i++)
4673         rem_vec[i] = 0;
4674
4675      index_vec[0] = 0;
4676      index_vec[1] = n;
4677
4678      for (i = 0; i <= levels-2; i++) {
4679         long start = (1L << i) - 1;
4680         long finish = (1L << (i+1)) - 2;
4681         for (j = finish; j >= start; j--) {
4682            index_vec[2*j+2] = index_vec[j] + (index_vec[j+1] - index_vec[j])/2;
4683            index_vec[2*j+1] = index_vec[j];
4684         }
4685         index_vec[2*finish+3] = n;
4686      }
4687
4688      for (i = (1L << (levels-1)) - 1; i < vec_len; i++) {
4689         /* multiply primes index_vec[i]..index_vec[i+1]-1 into
4690          * prod_vec[i]
4691          */
4692
4693         _ntl_gone(&prod_vec[i]);
4694         for (j = index_vec[i]; j < index_vec[i+1]; j++)
4695            _ntl_gsmul(prod_vec[i], q[j], &prod_vec[i]); 
4696      }
4697
4698      for (i = (1L << (levels-1)) - 2; i >= 3; i--)
4699         _ntl_gmul(prod_vec[2*i+1], prod_vec[2*i+2], &prod_vec[i]);
4700
4701     
4702      for (i = 3; i < vec_len; i++)
4703         len_vec[i] = _ntl_gsize(prod_vec[i]);
4704
4705      /* Set len_vec[1] = len_vec[2] =
4706       *    max(_ntl_gsize(modulus), len_vec[3..6]).
4707       * This is a bit paranoid, but it makes the code
4708       * more robust. */
4709
4710      j = _ntl_gsize(modulus);
4711      for (i = 3; i <= 6; i++)
4712         if (len_vec[i] > j) j = len_vec[i];
4713
4714      len_vec[1] = len_vec[2] = j;
4715
4716      for (i = 3; i < vec_len; i++)
4717         inv_vec[i] = neg_inv_mod_limb(DATA(prod_vec[i])[0]);
4718
4719
4720      for (i = (1L << (levels-1)) - 1; i < vec_len; i++) {
4721         for (j = index_vec[i]; j < index_vec[i+1]; j++) {
4722            corr_vec[j] = SpecialPower(len_vec[1] - len_vec[i], q[j]);
4723            corraux_vec[j] = ((double) corr_vec[j])/((double) q[j]);
4724         }
4725      }
4726
4727
4728      /* allocate length in advance to streamline eval code */
4729
4730      _ntl_gsetlength(&rem_vec[0], len_vec[1]); /* a special temp */
4731
4732      for (i = 1; i < vec_len; i++)
4733         _ntl_gsetlength(&rem_vec[i], len_vec[i]);
4734
4735
4736
4737
4738      r->strategy = 2;
4739      R->n = n;
4740      R->primes = q;
4741      R->levels = levels;
4742      R->index_vec = index_vec;
4743      R->len_vec = len_vec;
4744      R->inv_vec = inv_vec;
4745      R->corr_vec = corr_vec;
4746      R->corraux_vec = corraux_vec;
4747      R->prod_vec = prod_vec;
4748      R->rem_vec = rem_vec;
4749
4750      *rem_struct = (void *) r;
4751   }
4752   else if (n >= 32) {
4753      struct rem_body_gmp *R = &r->U.G;
4754
4755      long *q;
4756      long i, j;
4757      long levels, vec_len;
4758      long *index_vec;
4759      _ntl_gbigint *prod_vec, *rem_vec;
4760   
4761      q = (long *) NTL_MALLOC(n, sizeof(long), 0);
4762      if (!q) ghalt("out of memory");
4763   
4764      for (i = 0; i < n; i++)
4765         q[i] = p[i];
4766
4767      levels = 0;
4768      while ((n >> levels) >= 4) levels++;
4769
4770      vec_len = (1L << levels) - 1;
4771
4772      index_vec = (long *) NTL_MALLOC((vec_len+1), sizeof(long), 0);
4773      if (!index_vec) ghalt("out of memory");
4774
4775      prod_vec = (_ntl_gbigint *) NTL_MALLOC(vec_len, sizeof(_ntl_gbigint), 0);
4776      if (!prod_vec) ghalt("out of memory");
4777
4778      rem_vec = (_ntl_gbigint *) NTL_MALLOC(vec_len, sizeof(_ntl_gbigint), 0);
4779      if (!rem_vec) ghalt("out of memory");
4780
4781      for (i = 0; i < vec_len; i++)
4782         prod_vec[i] = 0;
4783
4784      for (i = 0; i < vec_len; i++)
4785         rem_vec[i] = 0;
4786
4787      index_vec[0] = 0;
4788      index_vec[1] = n;
4789
4790      for (i = 0; i <= levels-2; i++) {
4791         long start = (1L << i) - 1;
4792         long finish = (1L << (i+1)) - 2;
4793         for (j = finish; j >= start; j--) {
4794            index_vec[2*j+2] = index_vec[j] + (index_vec[j+1] - index_vec[j])/2;
4795            index_vec[2*j+1] = index_vec[j];
4796         }
4797         index_vec[2*finish+3] = n;
4798      }
4799
4800      for (i = (1L << (levels-1)) - 1; i < vec_len; i++) {
4801         /* multiply primes index_vec[i]..index_vec[i+1]-1 into
4802          * prod_vec[i]
4803          */
4804
4805         _ntl_gone(&prod_vec[i]);
4806         for (j = index_vec[i]; j < index_vec[i+1]; j++)
4807            _ntl_gsmul(prod_vec[i], q[j], &prod_vec[i]); 
4808      }
4809
4810      for (i = (1L << (levels-1)) - 2; i >= 3; i--)
4811         _ntl_gmul(prod_vec[2*i+1], prod_vec[2*i+2], &prod_vec[i]);
4812
4813
4814      /* allocate length in advance to streamline eval code */
4815
4816      _ntl_gsetlength(&rem_vec[1], _ntl_gsize(modulus));
4817      _ntl_gsetlength(&rem_vec[2], _ntl_gsize(modulus));
4818
4819      for (i = 1; i < (1L << (levels-1)) - 1; i++) {
4820         _ntl_gsetlength(&rem_vec[2*i+1], _ntl_gsize(prod_vec[2*i+1]));
4821         _ntl_gsetlength(&rem_vec[2*i+2], _ntl_gsize(prod_vec[2*i+2]));
4822      }
4823
4824      r->strategy = 1;
4825      R->n = n;
4826      R->primes = q;
4827      R->levels = levels;
4828      R->index_vec = index_vec;
4829      R->prod_vec = prod_vec;
4830      R->rem_vec = rem_vec;
4831
4832      *rem_struct = (void *) r;
4833   }
4834   else
4835   {
4836      struct rem_body_lip *R = &r->U.L;
4837
4838      long *q;
4839      long i;
4840
4841      r->strategy = 0;
4842      R->n = n;
4843      q = (long *) NTL_MALLOC(n, sizeof(long), 0);
4844      if (!q) ghalt("out of memory");
4845      R->primes = q;
4846 
4847      for (i = 0; i < n; i++)
4848         q[i] = p[i];
4849 
4850      *rem_struct = (void *) r;
4851   }
4852
4853}
4854
4855
4856
4857void _ntl_grem_struct_free(void *rem_struct)
4858{
4859   struct rem_body *r = (struct rem_body *) rem_struct;
4860
4861   switch (r->strategy) {
4862
4863   case 0: {
4864      free(r->U.L.primes);
4865      free(r);
4866      break;
4867   }
4868
4869   case 1: {
4870      struct rem_body_gmp *R = &r->U.G;
4871
4872      long levels = R->levels;
4873      long vec_len = (1L << levels) - 1;
4874      long i;
4875
4876      for (i = 0; i < vec_len; i++)
4877         _ntl_gfree(&R->prod_vec[i]);
4878
4879      for (i = 0; i < vec_len; i++)
4880         _ntl_gfree(&R->rem_vec[i]);
4881
4882      free(R->primes);
4883      free(R->index_vec);
4884      free(R->prod_vec);
4885      free(R->rem_vec);
4886      free(r);
4887      break;
4888   }
4889
4890   case 2: {
4891      struct rem_body_gmp1 *R = &r->U.G1;
4892
4893      long levels = R->levels;
4894      long vec_len = (1L << levels) - 1;
4895      long i;
4896
4897      for (i = 0; i < vec_len; i++)
4898         _ntl_gfree(&R->prod_vec[i]);
4899
4900      for (i = 0; i < vec_len; i++)
4901         _ntl_gfree(&R->rem_vec[i]);
4902
4903      free(R->primes);
4904      free(R->index_vec);
4905      free(R->len_vec);
4906      free(R->corr_vec);
4907      free(R->inv_vec);
4908      free(R->corraux_vec);
4909      free(R->prod_vec);
4910      free(R->rem_vec);
4911      free(r);
4912      break;
4913   }
4914
4915
4916   default:
4917      ghalt("_ntl_grem_struct_free: inconsistent strategy");
4918
4919   } /* end switch */
4920}
4921
4922
4923
4924
4925void _ntl_grem_struct_eval(void *rem_struct, long *x, _ntl_gbigint a)
4926{
4927   struct rem_body *r = (struct rem_body *) rem_struct;
4928
4929   switch (r->strategy) {
4930
4931   case 0: {
4932      struct rem_body_lip *R = &r->U.L;
4933      long n = R->n;
4934      long *q = R->primes;
4935
4936      long j;
4937      mp_limb_t *adata;
4938      long sa;
4939
4940      if (!a) 
4941         sa = 0;
4942      else
4943         sa = SIZE(a);
4944
4945      if (sa == 0) {
4946         for (j = 0; j < n; j++)
4947            x[j] = 0;
4948
4949         break;
4950      }
4951
4952      adata = DATA(a);
4953
4954      for (j = 0; j < n; j++)
4955         x[j] = mpn_mod_1(adata, sa, q[j]);
4956
4957      break;
4958   }
4959
4960   case 1: {
4961      struct rem_body_gmp *R = &r->U.G;
4962
4963      long n = R->n;
4964      long levels = R->levels;
4965      long *q = R->primes;
4966      long *index_vec = R->index_vec;
4967      _ntl_gbigint *prod_vec = R->prod_vec;
4968      _ntl_gbigint *rem_vec = R->rem_vec;
4969      long vec_len = (1L << levels) - 1;
4970
4971      long i, j;
4972
4973      if (ZEROP(a)) {
4974         for (j = 0; j < n; j++)
4975            x[j] = 0;
4976
4977         break;
4978      }
4979
4980      _ntl_gcopy(a, &rem_vec[1]);
4981      _ntl_gcopy(a, &rem_vec[2]);
4982
4983      for (i = 1; i < (1L << (levels-1)) - 1; i++) {
4984         gmod_simple(rem_vec[i], prod_vec[2*i+1], &rem_vec[2*i+1]);
4985         gmod_simple(rem_vec[i], prod_vec[2*i+2], &rem_vec[2*i+2]);
4986      }
4987
4988      for (i = (1L << (levels-1)) - 1; i < vec_len; i++) {
4989         long lo = index_vec[i];
4990         long hi = index_vec[i+1];
4991         mp_limb_t *s1p = DATA(rem_vec[i]);
4992         long s1size = SIZE(rem_vec[i]);
4993         if (s1size == 0) {
4994            for (j = lo; j <hi; j++)
4995               x[j] = 0;
4996         }
4997         else {
4998            for (j = lo; j < hi; j++)
4999               x[j] = mpn_mod_1(s1p, s1size, q[j]);
5000         }
5001      }
5002
5003      break;
5004   }
5005
5006   case 2: {
5007      struct rem_body_gmp1 *R = &r->U.G1;
5008
5009      long n = R->n;
5010      long levels = R->levels;
5011      long *q = R->primes;
5012      long *index_vec = R->index_vec;
5013      long *len_vec = R->len_vec;
5014      long *corr_vec = R->corr_vec;
5015      double *corraux_vec = R->corraux_vec;
5016      mp_limb_t *inv_vec = R->inv_vec;
5017      _ntl_gbigint *prod_vec = R->prod_vec;
5018      _ntl_gbigint *rem_vec = R->rem_vec;
5019      long vec_len = (1L << levels) - 1;
5020
5021      long i, j;
5022
5023      if (ZEROP(a)) {
5024         for (j = 0; j < n; j++)
5025            x[j] = 0;
5026
5027         break;
5028      }
5029
5030      _ntl_gcopy(a, &rem_vec[1]);
5031      _ntl_gcopy(a, &rem_vec[2]);
5032
5033      for (i = 1; i < (1L << (levels-1)) - 1; i++) {
5034         _ntl_gcopy(rem_vec[i], &rem_vec[0]);
5035         redc(rem_vec[0], prod_vec[2*i+1], len_vec[i]-len_vec[2*i+1],
5036              inv_vec[2*i+1], rem_vec[2*i+1]);
5037         redc(rem_vec[i], prod_vec[2*i+2], len_vec[i]-len_vec[2*i+2],
5038              inv_vec[2*i+2], rem_vec[2*i+2]);
5039      }
5040
5041      for (i = (1L << (levels-1)) - 1; i < vec_len; i++) {
5042         long lo = index_vec[i];
5043         long hi = index_vec[i+1];
5044         mp_limb_t *s1p = DATA(rem_vec[i]);
5045         long s1size = SIZE(rem_vec[i]);
5046         if (s1size == 0) {
5047            for (j = lo; j <hi; j++)
5048               x[j] = 0;
5049         }
5050         else {
5051            for (j = lo; j < hi; j++) {
5052               long t = mpn_mod_1(s1p, s1size, q[j]);
5053               SP_MUL_MOD2(x[j], t, corr_vec[j], q[j], corraux_vec[j]);
5054            }
5055         }
5056      }
5057
5058      break;
5059   }
5060
5061   default:
5062      ghalt("_ntl_grem_struct_eval: inconsistent strategy");
5063
5064
5065   } /* end switch */
5066
5067
5068}
5069
5070
Note: See TracBrowser for help on using the repository browser.