source: c_lib/src/ntl_wrap.cpp @ 8423:b3d024f8f464

Revision 8423:b3d024f8f464, 35.9 KB checked in by David Roe <roed@…>, 5 years ago (diff)

A few changes to ntl_wrap.

Line 
1#include <iostream>
2#include <sstream>
3using namespace std;
4
5#include "ntl_wrap.h"
6#include <NTL/mat_poly_ZZ.h>
7#include <NTL/LLL.h>
8
9void del_charstar(char* a) {
10  delete[] a;
11}
12
13//////// ZZ //////////
14
15/* Return value is only valid if the result should fit into an int.
16   AUTHOR: David Harvey (2008-06-08) */
17int ZZ_to_int(const ZZ* x)
18{
19  return to_int(*x);
20}
21
22/* Returns a *new* ZZ object.
23   AUTHOR: David Harvey (2008-06-08) */
24struct ZZ* int_to_ZZ(int value)
25{
26  ZZ* output = new ZZ();
27  conv(*output, value);
28  return output;
29}
30
31/* Copies the ZZ into the mpz_t
32   Assumes output has been mpz_init'd.
33   AUTHOR: David Harvey
34           Joel B. Mohler moved the ZZX_getitem_as_mpz code out to this function (2007-03-13) */
35void ZZ_to_mpz(mpz_t* output, const struct ZZ* x)
36{
37    unsigned char stack_bytes[4096];
38    int use_heap;
39    unsigned long size = NumBytes(*x);
40    use_heap = (size > sizeof(stack_bytes));
41    unsigned char* bytes = use_heap ? (unsigned char*) malloc(size) : stack_bytes;
42    BytesFromZZ(bytes, *x, size);
43    mpz_import(*output, size, -1, 1, 0, 0, bytes);
44    if (sign(*x) < 0)
45        mpz_neg(*output, *output);
46    if (use_heap)
47        free(bytes);
48}
49
50// Ok, I know that this is obvious
51// I just wanted to document the appearance of the magic number 8 in the code below
52#define bits_in_byte        8
53
54/* Copies the mpz_t into the ZZ
55   AUTHOR: Joel B. Mohler (2007-03-15) */
56// This should be changed to an mpz_t not an mpz_t*
57void mpz_to_ZZ(struct ZZ* output, const mpz_t *x)
58{
59    unsigned char stack_bytes[4096];
60    int use_heap;
61    size_t size = (mpz_sizeinbase(*x, 2) + bits_in_byte-1) / bits_in_byte;
62    use_heap = (size > sizeof(stack_bytes));
63    void* bytes = use_heap ? malloc(size) : stack_bytes;
64    size_t words_written;
65    mpz_export(bytes, &words_written, -1, 1, 0, 0, *x);
66    clear(*output);
67    ZZFromBytes(*output, (unsigned char *)bytes, words_written);
68    if (mpz_sgn(*x) < 0)
69        NTL::negate(*output, *output);
70    if (use_heap)
71        free(bytes);
72}
73
74/* Sets given ZZ to value
75   AUTHOR: David Harvey (2008-06-08) */
76void ZZ_set_from_int(ZZ* x, int value)
77{
78  conv(*x, value);
79}
80
81long ZZ_remove(struct ZZ &dest, const struct ZZ &src, const struct ZZ &f)
82{
83    // Based on the code for mpz_remove
84    ZZ fpow[40];            // inexaustible...until year 2020 or so
85    ZZ x, rem;
86    long pwr;
87    int p;
88
89    if (compare(f, 1) <= 0 && compare(f, -1) >= 0)
90        Error("Division by zero");
91
92    if (compare(src, 0) == 0)
93    {
94        if (src != dest)
95           dest = src;
96        return 0;
97    }
98
99    if (compare(f, 2) == 0)
100    {
101        dest = src;
102        return MakeOdd(dest);
103    }
104
105    /* We could perhaps compute mpz_scan1(src,0)/mpz_scan1(f,0).  It is an
106     upper bound of the result we're seeking.  We could also shift down the
107     operands so that they become odd, to make intermediate values smaller.  */
108
109    pwr = 0;
110    fpow[0] = ZZ(f);
111    dest = src;
112    rem = ZZ();
113    x = ZZ();
114
115    /* Divide by f, f^2, ..., f^(2^k) until we get a remainder for f^(2^k).  */
116    for (p = 0;;p++)
117    {
118        DivRem(x, rem, dest, fpow[p]);
119        if (compare(rem, 0) != 0)
120            break;
121        fpow[p+1] = ZZ();
122        mul(fpow[p+1], fpow[p], fpow[p]);
123        dest = x;
124    }
125
126    pwr = (1 << p) - 1;
127   
128    /* Divide by f^(2^(k-1)), f^(2^(k-2)), ..., f for all divisors that give a
129       zero remainder.  */
130    while (--p >= 0)
131    {
132        DivRem(x, rem, dest, fpow[p]);
133        if (compare(rem, 0) == 0)
134        {
135            pwr += 1 << p;
136            dest = x;
137        }
138    }
139    return pwr;
140}
141
142//////// ZZ_p //////////
143
144/* Return value is only valid if the result should fit into an int.
145   AUTHOR: David Harvey (2008-06-08) */
146int ZZ_p_to_int(const ZZ_p& x )
147{
148  return ZZ_to_int(&rep(x));
149}
150
151/* Returns a *new* ZZ_p object.
152   AUTHOR: David Harvey (2008-06-08) */
153ZZ_p int_to_ZZ_p(int value)
154{
155  ZZ_p r;
156  r = value;
157  return r;
158}
159
160/* Sets given ZZ_p to value
161   AUTHOR: David Harvey (2008-06-08) */
162void ZZ_p_set_from_int(ZZ_p* x, int value)
163{
164  conv(*x, value);
165}
166
167void ZZ_p_modulus(struct ZZ* mod, const struct ZZ_p* x)
168{
169        (*mod) = x->modulus();
170}
171
172struct ZZ_p* ZZ_p_pow(const struct ZZ_p* x, long e) 
173{
174  ZZ_p *z = new ZZ_p();
175  power(*z, *x, e);
176  return z;
177}
178
179void ntl_ZZ_set_modulus(ZZ* x)
180{
181  ZZ_p::init(*x);
182}
183
184ZZ_p* ZZ_p_inv(ZZ_p* x)
185{
186  ZZ_p *z = new ZZ_p();
187  inv(*z, *x);
188  return z;
189}
190
191ZZ_p* ZZ_p_random(void)
192{
193  ZZ_p *z = new ZZ_p();
194  random(*z);
195  return z;
196}
197
198struct ZZ_p* ZZ_p_neg(struct ZZ_p* x)
199{
200  return new ZZ_p(-(*x));
201}
202
203
204
205///////////////////////////////////////////////
206//////// ZZX //////////
207///////////////////////////////////////////////
208
209char* ZZX_repr(struct ZZX* x)
210{
211  ostringstream instore;
212  instore << (*x);
213  int n = strlen(instore.str().data());
214  char* buf = new char[n+1];
215  strcpy(buf, instore.str().data());
216  return buf;
217}
218
219struct ZZX* ZZX_copy(struct ZZX* x) {
220  return new ZZX(*x);
221}
222
223/* Sets ith coefficient of x to value.
224   AUTHOR: David Harvey (2006-06-08) */
225void ZZX_setitem_from_int(struct ZZX* x, long i, int value)
226{
227  SetCoeff(*x, i, value);
228}
229
230/* Returns ith coefficient of x.
231   Return value is only valid if the result should fit into an int.
232   AUTHOR: David Harvey (2006-06-08) */
233int ZZX_getitem_as_int(struct ZZX* x, long i)
234{
235  return ZZ_to_int(&coeff(*x, i));
236}
237
238/* Copies ith coefficient of x to output.
239   Assumes output has been mpz_init'd.
240   AUTHOR: David Harvey (2007-02) */
241void ZZX_getitem_as_mpz(mpz_t* output, struct ZZX* x, long i)
242{
243    const ZZ& z = coeff(*x, i);
244    ZZ_to_mpz(output, &z);
245}
246
247struct ZZX* ZZX_div(struct ZZX* x, struct ZZX* y, int* divisible)
248{
249  struct ZZX* z = new ZZX();
250  *divisible = divide(*z, *x, *y);
251  return z;
252}
253
254
255
256void ZZX_quo_rem(struct ZZX* x, struct ZZX* other, struct ZZX** r, struct ZZX** q)
257{
258  struct ZZX *qq = new ZZX(), *rr = new ZZX();
259  DivRem(*qq, *rr, *x, *other);
260  *r = rr; *q = qq;
261}
262
263
264struct ZZX* ZZX_square(struct ZZX* x)
265{
266  struct ZZX* s = new ZZX();
267  sqr(*s, *x);
268  return s;
269}
270
271
272int ZZX_is_monic(struct ZZX* x)
273{
274  IsOne(LeadCoeff(*x));
275}
276
277
278struct ZZX* ZZX_neg(struct ZZX* x)
279{
280  struct ZZX* y = new ZZX();
281  *y = -*x;
282  return y;
283}
284
285
286struct ZZX* ZZX_left_shift(struct ZZX* x, long n)
287{
288  struct ZZX* y = new ZZX();
289  LeftShift(*y, *x, n);
290  return y;
291}
292
293
294struct ZZX* ZZX_right_shift(struct ZZX* x, long n)
295{
296  struct ZZX* y = new ZZX();
297  RightShift(*y, *x, n);
298  return y;
299}
300
301struct ZZX* ZZX_primitive_part(struct ZZX* x)
302{
303  struct ZZX* p = new ZZX();
304  PrimitivePart(*p, *x);
305  return p;
306}
307
308
309void ZZX_pseudo_quo_rem(struct ZZX* x, struct ZZX* y, struct ZZX** r, struct ZZX** q)
310{
311  *r = new ZZX();
312  *q = new ZZX();
313  PseudoDivRem(**q, **r, *x, *y);
314}
315
316
317struct ZZX* ZZX_gcd(struct ZZX* x, struct ZZX* y)
318{
319  struct ZZX* g = new ZZX();
320  GCD(*g, *x, *y);
321  return g;
322}
323
324
325void ZZX_xgcd(struct ZZX* x, struct ZZX* y, struct ZZ** r, struct ZZX** s, \
326              struct ZZX** t, int proof)
327{
328  *r = new ZZ();
329  *s = new ZZX();
330  *t = new ZZX();
331  XGCD(**r, **s, **t, *x, *y, proof);
332}
333
334
335long ZZX_degree(struct ZZX* x)
336{
337  return deg(*x);
338}
339
340void ZZX_set_x(struct ZZX* x)
341{
342  SetX(*x);
343}
344
345
346int ZZX_is_x(struct ZZX* x)
347{
348  return IsX(*x);
349}
350
351
352struct ZZX* ZZX_derivative(struct ZZX* x)
353{
354  ZZX* d = new ZZX();
355  diff(*d, *x);
356  return d;
357}
358
359
360struct ZZX* ZZX_reverse(struct ZZX* x)
361{
362  ZZX* r = new ZZX();
363  reverse(*r, *x);
364  return r;
365}
366
367struct ZZX* ZZX_reverse_hi(struct ZZX* x, int hi)
368{
369  ZZX* r = new ZZX();
370  reverse(*r, *x, hi);
371  return r;
372}
373
374
375struct ZZX* ZZX_truncate(struct ZZX* x, long m)
376{
377  ZZX* t = new ZZX();
378  trunc(*t, *x, m);
379  return t;
380}
381
382
383struct ZZX* ZZX_multiply_and_truncate(struct ZZX* x, struct ZZX* y, long m)
384{
385  ZZX* t = new ZZX();
386  MulTrunc(*t, *x, *y, m);
387  return t;
388}
389
390
391struct ZZX* ZZX_square_and_truncate(struct ZZX* x, long m)
392{
393  ZZX* t = new ZZX();
394  SqrTrunc(*t, *x, m);
395  return t;
396}
397
398
399struct ZZX* ZZX_invert_and_truncate(struct ZZX* x, long m)
400{
401  ZZX* t = new ZZX();
402  InvTrunc(*t, *x, m);
403  return t;
404}
405
406
407struct ZZX* ZZX_multiply_mod(struct ZZX* x, struct ZZX* y,  struct ZZX* modulus)
408{
409  ZZX* p = new ZZX();
410  MulMod(*p, *x, *y, *modulus);
411  return p;
412}
413
414
415struct ZZ* ZZX_trace_mod(struct ZZX* x, struct ZZX* y)
416{
417  ZZ* p = new ZZ();
418  TraceMod(*p, *x, *y);
419  return p;
420}
421
422
423char* ZZX_trace_list(struct ZZX* x)
424{
425  vec_ZZ v;
426  TraceVec(v, *x);
427  ostringstream instore;
428  instore << v;
429  int n = strlen(instore.str().data());
430  char* buf = new char[n+1];
431  strcpy(buf, instore.str().data());
432  return buf;
433}
434
435
436struct ZZ* ZZX_resultant(struct ZZX* x, struct ZZX* y, int proof)
437{
438  ZZ* res = new ZZ();
439  resultant(*res, *x, *y, proof);
440  return res;
441}
442
443
444struct ZZ* ZZX_norm_mod(struct ZZX* x, struct ZZX* y, int proof)
445{
446  ZZ* res = new ZZ();
447  NormMod(*res, *x, *y, proof);
448  return res;
449}
450
451
452struct ZZ* ZZX_discriminant(struct ZZX* x, int proof)
453{
454  ZZ* d = new ZZ();
455  discriminant(*d, *x, proof);
456  return d;
457}
458
459
460struct ZZX* ZZX_charpoly_mod(struct ZZX* x, struct ZZX* y, int proof)
461{
462  ZZX* f = new ZZX();
463  CharPolyMod(*f, *x, *y, proof);
464  return f;
465}
466
467
468struct ZZX* ZZX_minpoly_mod(struct ZZX* x, struct ZZX* y)
469{
470  ZZX* f = new ZZX();
471  MinPolyMod(*f, *x, *y);
472  return f;
473}
474
475
476void ZZX_clear(struct ZZX* x)
477{
478  clear(*x);
479}
480
481
482void ZZX_preallocate_space(struct ZZX* x, long n)
483{
484  x->SetMaxLength(n);
485}
486
487/*
488EXTERN struct ZZ* ZZX_polyeval(struct ZZX* f, struct ZZ* a)
489{
490  ZZ* b = new ZZ();
491  *b = PolyEval(*f, *a);
492  return b;
493}
494*/
495
496void ZZX_squarefree_decomposition(struct ZZX*** v, long** e, long* n, struct ZZX* x)
497{
498  vec_pair_ZZX_long factors;
499  SquareFreeDecomp(factors, *x);
500  *n = factors.length();
501  *v = (ZZX**) malloc(sizeof(ZZX*) * (*n));
502  *e = (long*) malloc(sizeof(long) * (*n));
503  for (long i = 0; i < (*n); i++) {
504    (*v)[i] = new ZZX(factors[i].a);
505    (*e)[i] = factors[i].b;
506  }
507}
508
509///////////////////////////////////////////////
510//////// ZZ_pX //////////
511///////////////////////////////////////////////
512
513// char* ZZ_pX_repr(struct ZZ_pX* x)
514// {
515//   ostringstream instore;
516//   instore << (*x);
517//   int n = strlen(instore.str().data());
518//   char* buf = new char[n+1];
519//   strcpy(buf, instore.str().data());
520//   return buf;
521// }
522
523// void ZZ_pX_dealloc(struct ZZ_pX* x) {
524//   delete x;
525// }
526
527// struct ZZ_pX* ZZ_pX_copy(struct ZZ_pX* x) {
528//   return new ZZ_pX(*x);
529// }
530
531// /* Sets ith coefficient of x to value.
532//    AUTHOR: David Harvey (2008-06-08) */
533// void ZZ_pX_setitem_from_int(struct ZZ_pX* x, long i, int value)
534// {
535//   SetCoeff(*x, i, value);
536// }
537
538// /* Returns ith coefficient of x.
539//    Return value is only valid if the result should fit into an int.
540//    AUTHOR: David Harvey (2008-06-08) */
541// int ZZ_pX_getitem_as_int(struct ZZ_pX* x, long i)
542// {
543//     return ZZ_to_int(&rep(coeff(*x, i)));
544// }
545
546// struct ZZ_pX* ZZ_pX_add(struct ZZ_pX* x, struct ZZ_pX* y)
547// {
548//   ZZ_pX *z = new ZZ_pX();
549//   add(*z, *x, *y);
550//   return z;
551// }
552
553// struct ZZ_pX* ZZ_pX_sub(struct ZZ_pX* x, struct ZZ_pX* y)
554// {
555//   ZZ_pX *z = new ZZ_pX();
556//   sub(*z, *x, *y);
557//   return z;
558// }
559
560// struct ZZ_pX* ZZ_pX_mul(struct ZZ_pX* x, struct ZZ_pX* y)
561// {
562//   ZZ_pX *z = new ZZ_pX();
563//   mul(*z, *x, *y);
564//   return z;
565// }
566
567
568// struct ZZ_pX* ZZ_pX_div(struct ZZ_pX* x, struct ZZ_pX* y, int* divisible)
569// {
570//   struct ZZ_pX* z = new ZZ_pX();
571//   *divisible = divide(*z, *x, *y);
572//   return z;
573// }
574
575
576// struct ZZ_pX* ZZ_pX_mod(struct ZZ_pX* x, struct ZZ_pX* y)
577// {
578//   struct ZZ_pX* z = new ZZ_pX();
579//   rem(*z, *x, *y);
580//   return z;
581// }
582
583
584
585// void ZZ_pX_quo_rem(struct ZZ_pX* x, struct ZZ_pX* y, struct ZZ_pX** r, struct ZZ_pX** q)
586// {
587//   *r = new ZZ_pX();
588//   *q = new ZZ_pX();
589//   DivRem(**q, **r, *x, *y);
590// }
591
592
593// struct ZZ_pX* ZZ_pX_square(struct ZZ_pX* x)
594// {
595//   struct ZZ_pX* s = new ZZ_pX();
596//   sqr(*s, *x);
597//   return s;
598// }
599
600
601
602// int ZZ_pX_is_monic(struct ZZ_pX* x)
603// {
604//   IsOne(LeadCoeff(*x));
605// }
606
607
608// struct ZZ_pX* ZZ_pX_neg(struct ZZ_pX* x)
609// {
610//   struct ZZ_pX* y = new ZZ_pX();
611//   *y = -*x;
612//   return y;
613// }
614
615
616// struct ZZ_pX* ZZ_pX_left_shift(struct ZZ_pX* x, long n)
617// {
618//   struct ZZ_pX* y = new ZZ_pX();
619//   LeftShift(*y, *x, n);
620//   return y;
621// }
622
623
624// struct ZZ_pX* ZZ_pX_right_shift(struct ZZ_pX* x, long n)
625// {
626//   struct ZZ_pX* y = new ZZ_pX();
627//   RightShift(*y, *x, n);
628//   return y;
629// }
630
631
632
633// struct ZZ_pX* ZZ_pX_gcd(struct ZZ_pX* x, struct ZZ_pX* y)
634// {
635//   struct ZZ_pX* g = new ZZ_pX();
636//   GCD(*g, *x, *y);
637//   return g;
638// }
639
640
641// void ZZ_pX_xgcd(struct ZZ_pX** d, struct ZZ_pX** s, struct ZZ_pX** t, struct ZZ_pX* a, struct ZZ_pX* b)
642// {
643//   *d = new ZZ_pX();
644//   *s = new ZZ_pX();
645//   *t = new ZZ_pX();
646//   XGCD(**d, **s, **t, *a, *b);
647// }
648
649// void ZZ_pX_plain_xgcd(struct ZZ_pX** d, struct ZZ_pX** s, struct ZZ_pX** t, struct ZZ_pX* a, struct ZZ_pX* b)
650// {
651//   *d = new ZZ_pX();
652//   *s = new ZZ_pX();
653//   *t = new ZZ_pX();
654//   PlainXGCD(**d, **s, **t, *a, *b);
655// }
656
657// ZZ_p* ZZ_pX_leading_coefficient(struct ZZ_pX* x)
658// {
659//   return new ZZ_p(LeadCoeff(*x));
660// }
661
662
663// void ZZ_pX_set_x(struct ZZ_pX* x)
664// {
665//   SetX(*x);
666// }
667
668
669// int ZZ_pX_is_x(struct ZZ_pX* x)
670// {
671//   return IsX(*x);
672// }
673
674
675// struct ZZ_pX* ZZ_pX_derivative(struct ZZ_pX* x)
676// {
677//   ZZ_pX* d = new ZZ_pX();
678//   diff(*d, *x);
679//   return d;
680// }
681
682
683// struct ZZ_pX* ZZ_pX_reverse(struct ZZ_pX* x)
684// {
685//   ZZ_pX* r = new ZZ_pX();
686//   reverse(*r, *x);
687//   return r;
688// }
689
690// struct ZZ_pX* ZZ_pX_reverse_hi(struct ZZ_pX* x, int hi)
691// {
692//   ZZ_pX* r = new ZZ_pX();
693//   reverse(*r, *x, hi);
694//   return r;
695// }
696
697
698// struct ZZ_pX* ZZ_pX_truncate(struct ZZ_pX* x, long m)
699// {
700//   ZZ_pX* t = new ZZ_pX();
701//   trunc(*t, *x, m);
702//   return t;
703// }
704
705
706// struct ZZ_pX* ZZ_pX_multiply_and_truncate(struct ZZ_pX* x, struct ZZ_pX* y, long m)
707// {
708//   ZZ_pX* t = new ZZ_pX();
709//   MulTrunc(*t, *x, *y, m);
710//   return t;
711// }
712
713
714// struct ZZ_pX* ZZ_pX_square_and_truncate(struct ZZ_pX* x, long m)
715// {
716//   ZZ_pX* t = new ZZ_pX();
717//   SqrTrunc(*t, *x, m);
718//   return t;
719// }
720
721
722// struct ZZ_pX* ZZ_pX_invert_and_truncate(struct ZZ_pX* x, long m)
723// {
724//   ZZ_pX* t = new ZZ_pX();
725//   InvTrunc(*t, *x, m);
726//   return t;
727// }
728
729
730// struct ZZ_pX* ZZ_pX_multiply_mod(struct ZZ_pX* x, struct ZZ_pX* y,  struct ZZ_pX* modulus)
731// {
732//   ZZ_pX* p = new ZZ_pX();
733//   MulMod(*p, *x, *y, *modulus);
734//   return p;
735// }
736
737
738// struct ZZ_p* ZZ_pX_trace_mod(struct ZZ_pX* x, struct ZZ_pX* y)
739// {
740//   ZZ_p* p = new ZZ_p();
741//   TraceMod(*p, *x, *y);
742//   return p;
743// }
744
745
746char* ZZ_pX_trace_list(struct ZZ_pX* x)
747{
748  vec_ZZ_p v;
749  TraceVec(v, *x);
750  ostringstream instore;
751  instore << v;
752  int n = strlen(instore.str().data());
753  char* buf = new char[n+1];
754  strcpy(buf, instore.str().data());
755  return buf;
756}
757
758
759// struct ZZ_p* ZZ_pX_resultant(struct ZZ_pX* x, struct ZZ_pX* y)
760// {
761//   ZZ_p* res = new ZZ_p();
762//   resultant(*res, *x, *y);
763//   return res;
764// }
765
766
767// struct ZZ_p* ZZ_pX_norm_mod(struct ZZ_pX* x, struct ZZ_pX* y)
768// {
769//   ZZ_p* res = new ZZ_p();
770//   NormMod(*res, *x, *y);
771//   return res;
772// }
773
774
775
776// struct ZZ_pX* ZZ_pX_charpoly_mod(struct ZZ_pX* x, struct ZZ_pX* y)
777// {
778//   ZZ_pX* f = new ZZ_pX();
779//   CharPolyMod(*f, *x, *y);
780//   return f;
781// }
782
783
784// struct ZZ_pX* ZZ_pX_minpoly_mod(struct ZZ_pX* x, struct ZZ_pX* y)
785// {
786//   ZZ_pX* f = new ZZ_pX();
787//   MinPolyMod(*f, *x, *y);
788//   return f;
789// }
790
791
792// void ZZ_pX_clear(struct ZZ_pX* x)
793// {
794//   clear(*x);
795// }
796
797
798// void ZZ_pX_preallocate_space(struct ZZ_pX* x, long n)
799// {
800//   x->SetMaxLength(n);
801// }
802
803void ZZ_pX_factor(struct ZZ_pX*** v, long** e, long* n, struct ZZ_pX* x, long verbose)
804{
805  long i;
806  vec_pair_ZZ_pX_long factors;
807  berlekamp(factors, *x, verbose);
808  *n = factors.length();
809  *v = (ZZ_pX**) malloc(sizeof(ZZ_pX*) * (*n));
810  *e = (long*) malloc(sizeof(long)*(*n));
811  for (i=0; i<(*n); i++) {
812    (*v)[i] = new ZZ_pX(factors[i].a);
813    (*e)[i] = factors[i].b;
814  }
815}
816
817void ZZ_pX_linear_roots(struct ZZ_p*** v, long* n, struct ZZ_pX* f)
818{
819  long i;
820  // printf("1\n");
821  vec_ZZ_p w;
822  FindRoots(w, *f);
823  // printf("2\n");
824  *n = w.length();
825  //   printf("3 %d\n",*n);
826  (*v) = (ZZ_p**) malloc(sizeof(ZZ_p*)*(*n));
827  for (i=0; i<(*n); i++) {
828    (*v)[i] = new ZZ_p(w[i]);
829  }
830}
831
832/////////// ZZ_pE //////////////
833
834struct ZZ_pX ZZ_pE_to_ZZ_pX(struct ZZ_pE x)
835{
836  return ZZ_pX(rep(x));
837}
838
839
840
841//////// mat_ZZ //////////
842
843void mat_ZZ_SetDims(struct mat_ZZ* mZZ, long nrows, long ncols){
844  mZZ->SetDims(nrows, ncols);
845}
846
847struct mat_ZZ* mat_ZZ_pow(const struct mat_ZZ* x, long e) 
848{
849  mat_ZZ *z = new mat_ZZ();
850  power(*z, *x, e);
851  return z;
852}
853
854long mat_ZZ_nrows(const struct mat_ZZ* x)
855{
856  return x->NumRows();
857}
858
859
860long mat_ZZ_ncols(const struct mat_ZZ* x)
861{
862  return x->NumCols();
863}
864
865void mat_ZZ_setitem(struct mat_ZZ* x, int i, int j, const struct ZZ* z)
866{
867  (*x)[i][j] = *z;
868 
869}
870
871struct ZZ* mat_ZZ_getitem(const struct mat_ZZ* x, int i, int j)
872{
873  return new ZZ((*x)(i,j));
874}
875
876struct ZZ* mat_ZZ_determinant(const struct mat_ZZ* x, long deterministic)
877{
878  ZZ* d = new ZZ();
879  determinant(*d, *x, deterministic);
880  return d;
881}
882
883struct mat_ZZ* mat_ZZ_HNF(const struct mat_ZZ* A, const struct ZZ* D)
884{
885  struct mat_ZZ* W = new mat_ZZ();
886  HNF(*W, *A, *D);
887  return W;
888}
889
890long mat_ZZ_LLL(struct ZZ **det, struct mat_ZZ *x, long a, long b, long verbose)
891{
892  *det = new ZZ();
893  return LLL(**det,*x,a,b,verbose);
894}
895
896long mat_ZZ_LLL_U(struct ZZ **det, struct mat_ZZ *x, struct mat_ZZ *U, long a, long b, long verbose)
897{
898  *det = new ZZ();
899  return LLL(**det,*x,*U,a,b,verbose);
900}
901
902
903struct ZZX* mat_ZZ_charpoly(const struct mat_ZZ* A)
904{
905  ZZX* f = new ZZX();
906  CharPoly(*f, *A);
907  return f;
908}
909
910
911
912/**
913 * GF2X
914 *
915 * @author Martin Albrecht <malb@informatik.uni-bremen.de>
916 *
917 * @versions 2006-01 malb
918 *           initial version (based on code by William Stein)
919 */
920
921struct GF2X* GF2X_pow(const struct GF2X* x, long e) 
922{
923  GF2X *z = new GF2X();
924  power(*z, *x, e);
925  return z;
926}
927
928struct GF2X* GF2X_neg(struct GF2X* x)
929{
930  return new GF2X(-(*x));
931}
932
933struct GF2X* GF2X_copy(struct GF2X* x)
934{
935  GF2X *z = new GF2X(*x);
936  return z;
937}
938
939long GF2X_deg(struct GF2X* x)
940{
941  return deg(*x);
942}
943
944void GF2X_hex(long h)
945{
946  GF2X::HexOutput=h;
947}
948
949
950
951PyObject* GF2X_to_bin(const struct GF2X* x) 
952{
953  long hex;
954  hex = GF2X::HexOutput;
955  GF2X::HexOutput=0;
956  std::ostringstream instore;
957  instore << (*x);
958  GF2X::HexOutput=hex;
959  return PyString_FromString(instore.str().data());
960}
961
962PyObject* GF2X_to_hex(const struct GF2X* x)
963{
964  long hex;
965  hex = GF2X::HexOutput;
966  GF2X::HexOutput=1;
967  std::ostringstream instore;
968  instore << (*x);
969  GF2X::HexOutput=hex;
970  return PyString_FromString(instore.str().data());
971}
972
973
974
975/**
976 * GF2E
977 *
978 * @author Martin Albrecht <malb@informatik.uni-bremen.de>
979 *
980 * @versions 2006-01 malb
981 *           initial version (based on code by William Stein)
982 */
983
984
985void ntl_GF2E_set_modulus(GF2X* x)
986{
987  GF2E::init(*x);
988}
989
990
991struct GF2E* GF2E_pow(const struct GF2E* x, long e) 
992{
993  GF2E *z = new GF2E();
994  power(*z, *x, e);
995  return z;
996}
997
998
999struct GF2E* GF2E_neg(struct GF2E* x)
1000{
1001  return new GF2E(-(*x));
1002}
1003
1004struct GF2E* GF2E_copy(struct GF2E* x)
1005{
1006  GF2E *z = new GF2E(*x);
1007  return z;
1008}
1009
1010long GF2E_trace(struct GF2E* x)
1011{
1012  return rep(trace(*x));
1013}
1014
1015
1016long GF2E_degree()
1017{
1018  return GF2E::degree();
1019}
1020
1021const struct GF2X* GF2E_modulus()
1022{
1023  GF2XModulus mod = GF2E::modulus();
1024  GF2X *z = new GF2X(mod.val());
1025  return z;
1026}
1027
1028struct GF2E *GF2E_random(void)
1029{
1030  GF2E *z = new GF2E();
1031  random(*z);
1032  return z;
1033}
1034
1035const struct GF2X *GF2E_ntl_GF2X(struct GF2E *x) {
1036  GF2X *r = new GF2X(rep(*x));
1037  return r;
1038}
1039
1040
1041/**
1042 * mat_GF2E
1043 *
1044 * @author Martin Albrecht <malb@informatik.uni-bremen.de>
1045 *
1046 * @versions 2006-01 malb
1047 *           initial version (based on code by William Stein)
1048 */
1049
1050void mat_GF2E_SetDims(struct mat_GF2E* m, long nrows, long ncols){
1051  m->SetDims(nrows, ncols);
1052}
1053
1054struct mat_GF2E* mat_GF2E_pow(const struct mat_GF2E* x, long e) 
1055{
1056  mat_GF2E *z = new mat_GF2E();
1057  power(*z, *x, e);
1058  return z;
1059}
1060
1061long mat_GF2E_nrows(const struct mat_GF2E* x)
1062{
1063  return x->NumRows();
1064}
1065
1066
1067long mat_GF2E_ncols(const struct mat_GF2E* x)
1068{
1069  return x->NumCols();
1070}
1071
1072void mat_GF2E_setitem(struct mat_GF2E* x, int i, int j, const struct GF2E* z)
1073{
1074  (*x)[i][j] = *z;
1075}
1076
1077struct GF2E* mat_GF2E_getitem(const struct mat_GF2E* x, int i, int j)
1078{
1079  return new GF2E((*x)(i,j));
1080}
1081 
1082struct GF2E* mat_GF2E_determinant(const struct mat_GF2E* x)
1083{
1084  GF2E* d = new GF2E();
1085  determinant(*d, *x);
1086  return d;
1087}
1088
1089long mat_GF2E_gauss(struct mat_GF2E *x, long w)
1090{
1091  if(w==0) {
1092    return gauss(*x);
1093  } else {
1094    return gauss(*x, w);
1095  }
1096}
1097
1098struct mat_GF2E* mat_GF2E_transpose(const struct mat_GF2E* x) {
1099  mat_GF2E *y = new mat_GF2E();
1100  transpose(*y,*x);
1101  return y;
1102}
1103
1104
1105
1106ZZ_pContext* ZZ_pContext_new(ZZ *p)
1107{
1108        return new ZZ_pContext(*p);
1109}
1110
1111ZZ_pContext* ZZ_pContext_construct(void *mem, ZZ *p)
1112{
1113        return new(mem) ZZ_pContext(*p);
1114}
1115
1116void ZZ_pContext_restore(ZZ_pContext *ctx)
1117{
1118        ctx->restore();
1119}
1120
1121// Functions for using ZZ_pX's for p-adic extensions
1122
1123void ZZ_pX_conv_modulus(ZZ_pX &fout, const ZZ_pX &fin, const ZZ_pContext &modout)
1124{ 
1125    // Changes the modulus of fin to modout, and puts the result in fout.
1126    long i, n;
1127
1128    n = fin.rep.length();
1129    fout.rep.SetLength(n);
1130
1131    ZZ_p* xp = fout.rep.elts();
1132    const ZZ_p* ap = fin.rep.elts();
1133
1134    // I think it's enough to just restore modout once.
1135    // This should be true as long as the function rep taking a ZZ_p as an argument
1136    // and returning a ZZ works when the ZZ_p::modulus is incorrect.
1137    modout.restore();
1138
1139    for (i = 0; i < n; i++)
1140    {
1141        conv(xp[i], rep(ap[i]));
1142    }
1143   
1144    // We may have set a leading coefficient to 0, so we have to normalize
1145    fout.normalize();
1146}
1147
1148void ZZ_pEX_conv_modulus(ZZ_pEX &fout, const ZZ_pEX &fin, const ZZ_pContext &modout)
1149{
1150    // Changes the modulus of fin to modout, and puts the result in fout.
1151    long i, n, j, m;
1152
1153    n = fin.rep.length();
1154    fout.rep.SetLength(n);
1155
1156    ZZ_pE* outpe = fout.rep.elts();
1157    const ZZ_pE* inpe = fin.rep.elts();
1158
1159    ZZ_p* xp;
1160    const ZZ_p* ap;
1161    // I think it's enough to just restore modout once
1162    // This should be true as long as Loophole() offers access to
1163    // the underlying ZZ_pX representations of ZZ_pEs,
1164    // and rep of a ZZ_p (giving a ZZ) works even if the ZZ_p::modulus is
1165    // incorrect
1166    modout.restore();
1167
1168    for (i = 0; i < n; i++)
1169    {
1170        m = rep(inpe[i]).rep.length();
1171        outpe[i]._ZZ_pE__rep.rep.SetLength(m);
1172
1173        xp = outpe[i]._ZZ_pE__rep.rep.elts();
1174        ap = rep(inpe[i]).rep.elts();
1175
1176        for (j = 0; j < m; j++)
1177            conv(xp[j], rep(ap[j]));
1178
1179        // We may have set a leading coefficient to 0, so we have to normalize
1180        outpe[i]._ZZ_pE__rep.normalize();
1181    }
1182    // We may have set a leading coefficient to 0, so we have to normalize
1183    fout.normalize();
1184}
1185
1186void ZZ_pX_min_val_coeff(long & valuation, long &index, const struct ZZ_pX &f, const struct ZZ &p)
1187{
1188    // Sets index, where the indexth coefficient of f has the minimum p-adic valuation.
1189    // Sets valuation to be this valuation.
1190    // If there are ties, index will be the lowest of the tied indices
1191    // This only makes mathematical sense when p divides the modulus of f.
1192    long i, n, v;
1193
1194    n = f.rep.length();
1195    if (n == 0)
1196    {
1197        index = -1;
1198        return;
1199    }
1200
1201    const ZZ_p* fp = f.rep.elts();
1202    ZZ *u = new ZZ();
1203
1204    valuation = -1;
1205    i = 0;
1206
1207    while (valuation == -1)
1208    {
1209        if (rep(fp[i]) != 0)
1210        {
1211            index = i;
1212            valuation = ZZ_remove(*u, rep(fp[i]), p);
1213        }
1214        i++;
1215    }
1216    for (; i < n; i++)
1217    {
1218        if (rep(fp[i]) != 0)
1219        {
1220            v = ZZ_remove(*u, rep(fp[i]), p);
1221            if (v < valuation)
1222            {
1223                valuation = v;
1224                index = i;
1225            }
1226        }
1227    }
1228    delete u;
1229}
1230
1231long ZZ_pX_get_val_coeff(const struct ZZ_pX &f, const struct ZZ &p, long i)
1232{
1233    // Gets the p-adic valuation of the ith coefficient of f.
1234    ZZ *u = new ZZ();
1235    long ans = ZZ_remove(*u, rep(coeff(f, i)), p);
1236    delete u;
1237}
1238
1239void ZZ_pX_left_pshift(struct ZZ_pX &x, const struct ZZ_pX &a, const struct ZZ &pn, const struct ZZ_pContext &c)
1240{
1241    // Multiplies each coefficient by pn, and sets the context of the answer to c.
1242
1243    long i, n;
1244
1245    n = a.rep.length();
1246    x.rep.SetLength(n);
1247
1248    ZZ_p* xp = x.rep.elts();
1249    const ZZ_p* ap = a.rep.elts();
1250
1251    // I think it's enough to just restore modout once.
1252    // This should be true as long as the function rep taking a ZZ_p as an argument
1253    // and returning a ZZ works when the ZZ_p::modulus is incorrect.
1254    c.restore();
1255
1256    for (i = 0; i < n; i++)
1257    {
1258        conv(xp[i], rep(ap[i]) * pn);
1259    }
1260   
1261    // We may have set a leading coefficient to 0, so we have to normalize
1262    x.normalize();   
1263}
1264
1265void ZZ_pX_right_pshift(struct ZZ_pX &x, const struct ZZ_pX &a, const struct ZZ &pn, const struct ZZ_pContext &c)
1266{
1267    // Divides each coefficient by pn, and sets the context of the answer to c.
1268
1269    long i, n;
1270
1271    n = a.rep.length();
1272    x.rep.SetLength(n);
1273
1274    ZZ_p* xp = x.rep.elts();
1275    const ZZ_p* ap = a.rep.elts();
1276
1277    // I think it's enough to just restore modout once.
1278    // This should be true as long as the function rep taking a ZZ_p as an argument
1279    // and returning a ZZ works when the ZZ_p::modulus is incorrect.
1280    c.restore();
1281
1282    for (i = 0; i < n; i++)
1283    {
1284        conv(xp[i], rep(ap[i]) / pn);
1285    }
1286   
1287    // We may have set a leading coefficient to 0, so we have to normalize
1288    x.normalize();   
1289}
1290
1291void ZZ_pX_InvMod_newton(struct ZZ_pX &x, const struct ZZ_pX &a, const struct ZZ_pXModulus &F, const struct ZZ_pContext &cpn, const struct ZZ_pContext &cp)
1292{
1293    int j;
1294    cp.restore();
1295    ZZ_pX *amodp = new ZZ_pX();
1296    ZZ_pX *xmodp = new ZZ_pX();
1297    ZZ_pX *fmodp = new ZZ_pX();
1298    ZZ_pX_conv_modulus(*amodp, a, cp);
1299    ZZ_pX_conv_modulus(*fmodp, F.val(), cp);
1300    InvMod(*xmodp, *amodp, *fmodp);
1301    //cout << "xmodp: " << *xmodp << "\namodp: " << *amodp << "\nfmodp: " << *fmodp << "\n";
1302    cpn.restore();
1303    ZZ_pX *minusa = new ZZ_pX();
1304    ZZ_pX *xn = new ZZ_pX();
1305    ZZ_pX_conv_modulus(*xn, *xmodp, cpn);
1306    negate(*minusa, a);
1307    do
1308    {
1309        *xn = x;
1310        // x_n = 2*x_{n-1} - a*x_{n-1}^2 = (2 - a*x_{n-1})*x_{n-1}
1311        MulMod(x, *minusa, *xn, F);
1312        SetCoeff(x, 0, ConstTerm(x) + 2);
1313        MulMod(x, x, *xn, F);
1314        //cout << "x: " << x << "\nxn: " << *xn << "\n";
1315        //cin >> j;
1316    } while (x != (*xn));
1317    delete amodp;
1318    delete xmodp;
1319    delete fmodp;
1320    delete minusa;
1321    delete xn;
1322}
1323
1324void ZZ_pX_eis_shift(struct ZZ_pX &x, const struct ZZ_pX &a, long n, const struct ZZ_pXMultiplier* low_shifter, const struct ZZ_pXMultiplier* high_shifter, const struct ZZ_pXModulus &modulus, const struct ZZ &p, const struct ZZ_pContext &cupper, const struct ZZ_pContext &clower)
1325{
1326    long degree = deg(modulus);
1327    long pshift = n / degree;
1328    long eis_part = n % degree;
1329    long two_shift = 1;
1330    int i;
1331
1332    cupper.restore();
1333    //cout << "eis_part: " << eis_part << "\n";
1334    //cout << "pshift: " << pshift << "\n";
1335    ZZ_pX low_part; // = new ZZ_pX();
1336    ZZ_pX shifted_high_part; // = new ZZ_pX();
1337    x = a;
1338    //cout << "beginning: a = " << a << "\n";
1339    if (pshift)
1340    {
1341        i = 0;
1342        two_shift = 1;
1343        ZZ *pn = new ZZ();
1344        power(*pn, p, pshift);
1345        ZZ_pX_right_pshift(x, x, *pn, clower);
1346        delete pn;
1347        while (pshift > 0)
1348        {
1349            if (pshift & 1)
1350            {
1351                MulMod(x, x, high_shifter[i], modulus);
1352            }
1353            i++;
1354            two_shift <<= 1;
1355            pshift >>= 1;
1356        }
1357    }
1358    i = 0;
1359    two_shift = 1;
1360    while (eis_part > 0)
1361    {
1362        //cout << "eis_part = " << eis_part << "\n";
1363        if (eis_part & 1)
1364        {
1365            //cout << "i = " << i << "\n";
1366            //cout << "two_shift = " << two_shift << "\n";
1367            shifted_high_part = x >> two_shift;
1368            //cout << "shifted_high_part = " << shifted_high_part << "\n";
1369            low_part = x - (shifted_high_part << two_shift);
1370            //cout << "low_part = " << low_part << "\n";
1371            ZZ_pX_right_pshift(low_part, low_part, p, cupper);
1372            //cout << "low_part = " << low_part << "\n";
1373            MulMod(low_part, low_part, low_shifter[i], modulus);
1374            //cout << "low_part = " << low_part << "\n";
1375            x = low_part + shifted_high_part;
1376            //cout << "x = " << x << "\n";
1377        }
1378        i++;
1379        two_shift <<= 1;
1380        eis_part >>= 1;
1381    }
1382    //delete low_part;
1383    //delete shifted_high_part;
1384}
1385
1386// Functions for using ZZ_pX's for p-adic extensions
1387
1388void ZZ_pX_conv_modulus(ZZ_pX &fout, const ZZ_pX &fin, const ZZ_pContext &modout)
1389{ 
1390    // Changes the modulus of fin to modout, and puts the result in fout.
1391    long i, n;
1392
1393    n = fin.rep.length();
1394    fout.rep.SetLength(n);
1395
1396    ZZ_p* xp = fout.rep.elts();
1397    const ZZ_p* ap = fin.rep.elts();
1398
1399    // I think it's enough to just restore modout once.
1400    // This should be true as long as the function rep taking a ZZ_p as an argument
1401    // and returning a ZZ works when the ZZ_p::modulus is incorrect.
1402    modout.restore();
1403
1404    for (i = 0; i < n; i++)
1405    {
1406        conv(xp[i], rep(ap[i]));
1407    }
1408   
1409    // We may have set a leading coefficient to 0, so we have to normalize
1410    fout.normalize();
1411}
1412
1413void ZZ_pEX_conv_modulus(ZZ_pEX &fout, const ZZ_pEX &fin, const ZZ_pContext &modout)
1414{
1415    // Changes the modulus of fin to modout, and puts the result in fout.
1416    long i, n, j, m;
1417
1418    n = fin.rep.length();
1419    fout.rep.SetLength(n);
1420
1421    ZZ_pE* outpe = fout.rep.elts();
1422    const ZZ_pE* inpe = fin.rep.elts();
1423
1424    ZZ_p* xp;
1425    const ZZ_p* ap;
1426    // I think it's enough to just restore modout once
1427    // This should be true as long as Loophole() offers access to
1428    // the underlying ZZ_pX representations of ZZ_pEs,
1429    // and rep of a ZZ_p (giving a ZZ) works even if the ZZ_p::modulus is
1430    // incorrect
1431    modout.restore();
1432
1433    for (i = 0; i < n; i++)
1434    {
1435        m = rep(inpe[i]).rep.length();
1436        outpe[i]._ZZ_pE__rep.rep.SetLength(m);
1437
1438        xp = outpe[i]._ZZ_pE__rep.rep.elts();
1439        ap = rep(inpe[i]).rep.elts();
1440
1441        for (j = 0; j < m; j++)
1442            conv(xp[j], rep(ap[j]));
1443
1444        // We may have set a leading coefficient to 0, so we have to normalize
1445        outpe[i]._ZZ_pE__rep.normalize();
1446    }
1447    // We may have set a leading coefficient to 0, so we have to normalize
1448    fout.normalize();
1449}
1450
1451void ZZ_pX_min_val_coeff(long & valuation, long &index, const struct ZZ_pX &f, const struct ZZ &p)
1452{
1453    // Sets index, where the indexth coefficient of f has the minimum p-adic valuation.
1454    // Sets valuation to be this valuation.
1455    // If there are ties, index will be the lowest of the tied indices
1456    // This only makes mathematical sense when p divides the modulus of f.
1457    long i, n, v;
1458
1459    n = f.rep.length();
1460    if (n == 0)
1461    {
1462        index = -1;
1463        return;
1464    }
1465
1466    const ZZ_p* fp = f.rep.elts();
1467    ZZ *u = new ZZ();
1468
1469    valuation = -1;
1470    i = 0;
1471
1472    while (valuation == -1)
1473    {
1474        if (rep(fp[i]) != 0)
1475        {
1476            index = i;
1477            valuation = ZZ_remove(*u, rep(fp[i]), p);
1478        }
1479        i++;
1480    }
1481    for (; i < n; i++)
1482    {
1483        if (rep(fp[i]) != 0)
1484        {
1485            v = ZZ_remove(*u, rep(fp[i]), p);
1486            if (v < valuation)
1487            {
1488                valuation = v;
1489                index = i;
1490            }
1491        }
1492    }
1493    delete u;
1494}
1495
1496long ZZ_pX_get_val_coeff(const struct ZZ_pX &f, const struct ZZ &p, long i)
1497{
1498    // Gets the p-adic valuation of the ith coefficient of f.
1499    ZZ *u = new ZZ();
1500    long ans = ZZ_remove(*u, rep(coeff(f, i)), p);
1501    delete u;
1502}
1503
1504void ZZ_pX_left_pshift(struct ZZ_pX &x, const struct ZZ_pX &a, const struct ZZ &pn, const struct ZZ_pContext &c)
1505{
1506    // Multiplies each coefficient by pn, and sets the context of the answer to c.
1507
1508    long i, n;
1509
1510    n = a.rep.length();
1511    x.rep.SetLength(n);
1512
1513    ZZ_p* xp = x.rep.elts();
1514    const ZZ_p* ap = a.rep.elts();
1515
1516    // I think it's enough to just restore modout once.
1517    // This should be true as long as the function rep taking a ZZ_p as an argument
1518    // and returning a ZZ works when the ZZ_p::modulus is incorrect.
1519    c.restore();
1520
1521    for (i = 0; i < n; i++)
1522    {
1523        conv(xp[i], rep(ap[i]) * pn);
1524    }
1525   
1526    // We may have set a leading coefficient to 0, so we have to normalize
1527    x.normalize();   
1528}
1529
1530void ZZ_pX_right_pshift(struct ZZ_pX &x, const struct ZZ_pX &a, const struct ZZ &pn, const struct ZZ_pContext &c)
1531{
1532    // Divides each coefficient by pn, and sets the context of the answer to c.
1533
1534    long i, n;
1535
1536    n = a.rep.length();
1537    x.rep.SetLength(n);
1538
1539    ZZ_p* xp = x.rep.elts();
1540    const ZZ_p* ap = a.rep.elts();
1541
1542    // I think it's enough to just restore modout once.
1543    // This should be true as long as the function rep taking a ZZ_p as an argument
1544    // and returning a ZZ works when the ZZ_p::modulus is incorrect.
1545    c.restore();
1546
1547    for (i = 0; i < n; i++)
1548    {
1549        conv(xp[i], rep(ap[i]) / pn);
1550    }
1551   
1552    // We may have set a leading coefficient to 0, so we have to normalize
1553    x.normalize();   
1554}
1555
1556void ZZ_pX_InvMod_newton(struct ZZ_pX &x, const struct ZZ_pX &a, const struct ZZ_pXModulus &F, const struct ZZ_pContext &cpn, const struct ZZ_pContext &cp)
1557{
1558    int j;
1559    cp.restore();
1560    ZZ_pX *amodp = new ZZ_pX();
1561    ZZ_pX *xmodp = new ZZ_pX();
1562    ZZ_pX *fmodp = new ZZ_pX();
1563    ZZ_pX_conv_modulus(*amodp, a, cp);
1564    ZZ_pX_conv_modulus(*fmodp, F.val(), cp);
1565    InvMod(*xmodp, *amodp, *fmodp);
1566    //cout << "xmodp: " << *xmodp << "\namodp: " << *amodp << "\nfmodp: " << *fmodp << "\n";
1567    cpn.restore();
1568    ZZ_pX *minusa = new ZZ_pX();
1569    ZZ_pX *xn = new ZZ_pX();
1570    ZZ_pX_conv_modulus(*xn, *xmodp, cpn);
1571    negate(*minusa, a);
1572    do
1573    {
1574        *xn = x;
1575        // x_n = 2*x_{n-1} - a*x_{n-1}^2 = (2 - a*x_{n-1})*x_{n-1}
1576        MulMod(x, *minusa, *xn, F);
1577        SetCoeff(x, 0, ConstTerm(x) + 2);
1578        MulMod(x, x, *xn, F);
1579        //cout << "x: " << x << "\nxn: " << *xn << "\n";
1580        //cin >> j;
1581    } while (x != (*xn));
1582    delete amodp;
1583    delete xmodp;
1584    delete fmodp;
1585    delete minusa;
1586    delete xn;
1587}
1588
1589void ZZ_pX_eis_shift(struct ZZ_pX &x, const struct ZZ_pX &a, long n, const struct ZZ_pXMultiplier* low_shifter, const struct ZZ_pXMultiplier* high_shifter, const struct ZZ_pXModulus &modulus, const struct ZZ &p, const struct ZZ_pContext &cupper, const struct ZZ_pContext &clower)
1590{
1591    long degree = deg(modulus);
1592    long pshift = n / degree;
1593    long eis_part = n % degree;
1594    long two_shift = 1;
1595    int i;
1596
1597    cupper.restore();
1598    //cout << "eis_part: " << eis_part << "\n";
1599    //cout << "pshift: " << pshift << "\n";
1600    ZZ_pX low_part; // = new ZZ_pX();
1601    ZZ_pX shifted_high_part; // = new ZZ_pX();
1602    x = a;
1603    //cout << "beginning: a = " << a << "\n";
1604    if (pshift)
1605    {
1606        i = 0;
1607        two_shift = 1;
1608        ZZ *pn = new ZZ();
1609        power(*pn, p, pshift);
1610        ZZ_pX_right_pshift(x, x, *pn, clower);
1611        delete pn;
1612        while (pshift > 0)
1613        {
1614            if (pshift & 1)
1615            {
1616                MulMod(x, x, high_shifter[i], modulus);
1617            }
1618            i++;
1619            two_shift <<= 1;
1620            pshift >>= 1;
1621        }
1622    }
1623    i = 0;
1624    two_shift = 1;
1625    while (eis_part > 0)
1626    {
1627        //cout << "eis_part = " << eis_part << "\n";
1628        if (eis_part & 1)
1629        {
1630            //cout << "i = " << i << "\n";
1631            //cout << "two_shift = " << two_shift << "\n";
1632            shifted_high_part = x >> two_shift;
1633            //cout << "shifted_high_part = " << shifted_high_part << "\n";
1634            low_part = x - (shifted_high_part << two_shift);
1635            //cout << "low_part = " << low_part << "\n";
1636            ZZ_pX_right_pshift(low_part, low_part, p, cupper);
1637            //cout << "low_part = " << low_part << "\n";
1638            MulMod(low_part, low_part, low_shifter[i], modulus);
1639            //cout << "low_part = " << low_part << "\n";
1640            x = low_part + shifted_high_part;
1641            //cout << "x = " << x << "\n";
1642        }
1643        i++;
1644        two_shift <<= 1;
1645        eis_part >>= 1;
1646    }
1647    //delete low_part;
1648    //delete shifted_high_part;
1649}
1650
1651ZZ_pEContext* ZZ_pEContext_new(ZZ_pX *f)
1652{
1653        return new ZZ_pEContext(*f);
1654}
1655
1656ZZ_pEContext* ZZ_pEContext_construct(void *mem, ZZ_pX *f)
1657{
1658        return new(mem) ZZ_pEContext(*f);
1659}
1660
1661void ZZ_pEContext_restore(ZZ_pEContext *ctx)
1662{
1663        ctx->restore();
1664}
1665
1666zz_pContext* zz_pContext_new(long p)
1667{
1668        return new zz_pContext(p);
1669}
1670
1671zz_pContext* zz_pContext_construct(void *mem, long p)
1672{
1673        return new(mem) zz_pContext(p);
1674}
1675
1676void zz_pContext_restore(zz_pContext *ctx)
1677{
1678        ctx->restore();
1679}
Note: See TracBrowser for help on using the repository browser.