54poly::poly (PHEAD
int a, WORD modp, WORD modn):
55 size_of_terms(AM.MaxTer/(LONG)sizeof(WORD)),
61 terms = TermMalloc(
"poly::poly(int)");
67 terms[0] = 4 + AN.poly_num_vars;
68 terms[1] = 3 + AN.poly_num_vars;
69 for (
int i=0; i<AN.poly_num_vars; i++) terms[2+i] = 0;
70 terms[2+AN.poly_num_vars] = ABS(a);
71 terms[3+AN.poly_num_vars] = a>0 ? 1 : -1;
74 if (modp!=-1) setmod(modp,modn);
83poly::poly (PHEAD
const UWORD *a, WORD na, WORD modp, WORD modn):
84 size_of_terms(AM.MaxTer/(LONG)sizeof(WORD)),
90 terms = TermMalloc(
"poly::poly(UWORD*,WORD)");
93 while (*(a+ABS(na)-1)==0)
96 terms[0] = 3 + AN.poly_num_vars + ABS(na);
97 terms[1] = terms[0] - 1;
98 for (
int i=0; i<AN.poly_num_vars; i++) terms[2+i] = 0;
99 termscopy((WORD *)a, 2+AN.poly_num_vars, ABS(na));
100 terms[2+AN.poly_num_vars+ABS(na)] = na;
102 if (modp!=-1) setmod(modp,modn);
111poly::poly (
const poly &a, WORD modp, WORD modn):
112 size_of_terms(AM.MaxTer/(LONG)sizeof(WORD))
114#ifdef POLY_MOVE_DEBUG
115 std::cout <<
"poly copy ctor" << std::endl;
120 terms = TermMalloc(
"poly::poly(poly&)");
124 if (modp!=-1) setmod(modp,modn);
135 POLY_GETIDENTITY(*
this);
137 if (size_of_terms == AM.MaxTer/(LONG)
sizeof(WORD))
138 TermFree(terms,
"poly::~poly");
140 M_free(terms,
"poly::~poly");
149void poly::expand_memory (
int i) {
151 POLY_GETIDENTITY(*
this);
153 LONG new_size_of_terms = MaX(2*size_of_terms, i);
154 if (new_size_of_terms > MAXPOSITIVE) {
155 MLOCK(ErrorMessageLock);
156 MesPrint ((
char*)
"ERROR: polynomials too large (> WORDSIZE)");
157 MUNLOCK(ErrorMessageLock);
161 WORD *newterms = (WORD *)Malloc1(new_size_of_terms *
sizeof(WORD),
"poly::expand_memory");
162 WCOPY(newterms, terms, size_of_terms);
164 if (size_of_terms == AM.MaxTer/(LONG)
sizeof(WORD))
165 TermFree(terms,
"poly::expand_memory");
167 M_free(terms,
"poly::expand_memory");
170 size_of_terms = new_size_of_terms;
179void poly::setmod(WORD _modp, WORD _modn) {
181 POLY_GETIDENTITY(*
this);
183 if (_modp>0 && (_modp!=modp || _modn<modn)) {
192 modq = (UWORD *)&modp;
201 coefficients_modulo(modq,nmodq,smallq);
215void poly::coefficients_modulo (UWORD *a, WORD na,
bool small) {
217 POLY_GETIDENTITY(*
this);
220 for (
int i=1, di; i<terms[0]; i+=di) {
224 for (
int k=0; k<di; k++)
225 terms[j+k] = terms[i+k];
227 WORD n = terms[j+terms[j]-1];
229 if (ABS(n)==1 && small) {
231 terms[j+1+AN.poly_num_vars] = n*((UWORD)terms[j+1+AN.poly_num_vars] % a[0]);
232 if (terms[j+1+AN.poly_num_vars] == 0)
235 if (terms[j+1+AN.poly_num_vars] > +(WORD)a[0]/2) terms[j+1+AN.poly_num_vars]-=a[0];
236 if (terms[j+1+AN.poly_num_vars] < -(WORD)a[0]/2) terms[j+1+AN.poly_num_vars]+=a[0];
237 n = SGN(terms[j+1+AN.poly_num_vars]);
238 terms[j+1+AN.poly_num_vars] = ABS(terms[j+1+AN.poly_num_vars]);
242 TakeNormalModulus((UWORD *)&terms[j+1+AN.poly_num_vars], &n, a, na, NOUNPACK);
245 terms[j] = 2+AN.poly_num_vars+ABS(n);
246 terms[j+terms[j]-1] = n;
260const string int_to_string (WORD x) {
262 snprintf (res, 41,
"%i",x);
267const string poly::to_string()
const {
269 POLY_GETIDENTITY(*
this);
274 UBYTE *scoeff = (UBYTE *)NumberMalloc(
"poly::to_string");
280 for (
int i=1; i<terms[0]; i+=terms[i]) {
283 WORD ncoeff = terms[i+terms[i]-1];
292 if (ncoeff==1 && terms[i+terms[i]-1-ncoeff]==1) {
298 PrtLong((UWORD*)&terms[i+terms[i]-1-ncoeff], ncoeff, scoeff);
299 res += string((
char *)scoeff);
304 for (
int j=0; j<AN.poly_num_vars; j++) {
305 if (terms[i+1+j] > 0) {
306 if (printtimes) res +=
"*";
307 res += string(1,
'a'+j);
308 if (terms[i+1+j] > 1) res +=
"^" + int_to_string(terms[i+1+j]);
314 if (!printtimes) res +=
"1";
321 res += int_to_string(modp);
324 res += int_to_string(modn);
329 NumberFree(scoeff,
"poly::to_string");
340ostream& operator<< (ostream &out,
const poly &a) {
341 return out << a.to_string();
350int poly::monomial_compare (PHEAD
const WORD *a,
const WORD *b) {
351 for (
int i=0; i<AN.poly_num_vars; i++)
352 if (a[i+1]!=b[i+1])
return a[i+1]-b[i+1];
362const poly & poly::normalize() {
364 POLY_GETIDENTITY(*
this);
371 modq = (UWORD *)&modp;
382 LONG poffset = AT.pWorkPointer;
383 WantAddPointers((terms[0]/(AN.poly_num_vars+3)));
384 AT.pWorkPointer += terms[0]/(AN.poly_num_vars+3);
385 #define p (&(AT.pWorkSpace[poffset]))
390 for (
int i=1; i<terms[0]; i+=terms[i])
391 p[nterms++] = terms + i;
396 if (size_of_terms == AM.MaxTer/(LONG)
sizeof(WORD)) {
397 tmp = (WORD *)TermMalloc(
"poly::normalize");
400 tmp = (WORD *)Malloc1(size_of_terms *
sizeof(WORD),
"poly::normalize");
407 for (
int i=0; i<nterms; i++) {
408 if (i>0 && monomial_compare(BHEAD &tmp[j], p[i])==0) {
410 WORD ncoeff = tmp[j+tmp[j]-1];
411 AddLong((UWORD *)&tmp[j+1+AN.poly_num_vars], ncoeff,
412 (UWORD *)&p[i][1+AN.poly_num_vars], p[i][p[i][0]-1],
413 (UWORD *)&tmp[j+1+AN.poly_num_vars], &ncoeff);
415 tmp[j+1+AN.poly_num_vars+ABS(ncoeff)] = ncoeff;
416 tmp[j] = 2+AN.poly_num_vars+ABS(ncoeff);
422 WCOPY(&tmp[j],p[i],p[i][0]);
427 WORD ntmp = tmp[j+tmp[j]-1];
428 TakeNormalModulus((UWORD *)&tmp[j+1+AN.poly_num_vars], &ntmp,
429 modq,nmodq, NOUNPACK);
430 tmp[j] = 2+AN.poly_num_vars+ABS(ntmp);
431 tmp[j+tmp[j]-1] = ntmp;
435 if (tmp[j+tmp[j]-1]==0) {
444 WCOPY(terms,tmp,tmp[0]);
448 if (size_of_terms == AM.MaxTer/(LONG)
sizeof(WORD))
449 TermFree(tmp,
"poly::normalize");
451 M_free(tmp,
"poly::normalize");
453 AT.pWorkPointer = poffset;
465WORD poly::last_monomial_index ()
const {
466 POLY_GETIDENTITY(*
this);
467 return terms[0] - ABS(terms[terms[0]-1]) - AN.poly_num_vars - 2;
472WORD * poly::last_monomial ()
const {
473 return &terms[last_monomial_index()];
481int poly::compare_degree_vector(
const poly & b)
const {
482 POLY_GETIDENTITY(*
this);
485 if (terms[0] == 1 && b[0] == 1)
return 0;
486 if (terms[0] == 1)
return -1;
487 if (b[0] == 1)
return 1;
489 for (
int i = 0; i < AN.poly_num_vars; i++) {
491 int d2 = b.degree(i);
492 if (d1 != d2)
return d1 - d2;
503std::vector<int> poly::degree_vector()
const {
504 POLY_GETIDENTITY(*
this);
506 std::vector<int> degrees(AN.poly_num_vars);
507 for (
int i = 0; i < AN.poly_num_vars; i++) {
508 degrees[i] = degree(i);
519int poly::compare_degree_vector(
const vector<int> & b)
const {
520 POLY_GETIDENTITY(*
this);
522 if (terms[0] == 1)
return -1;
524 for (
int i = 0; i < AN.poly_num_vars; i++) {
526 if (d1 != b[i])
return d1 - b[i];
548 bool both_mod_small=
false;
552 modq = (UWORD *)&c.modp;
554 if (a.modp>0 && b.modp>0 && a.modn==1 && b.modn==1)
564 while (ai<a[0] || bi<b[0]) {
568 int cmp = ai<a[0] && bi<b[0] ? monomial_compare(BHEAD &a[ai],&b[bi]) : 0;
570 if (bi==b[0] || cmp>0) {
572 c.termscopy(&a[ai],ci,a[ai]);
576 else if (ai==a[0] || cmp<0) {
578 c.termscopy(&b[bi],ci,b[bi]);
584 c.termscopy(&a[ai],ci,MaX(a[ai],b[bi]));
586 if (both_mod_small) {
587 c[ci+1+AN.poly_num_vars] = ((LONG)a[ai+1+AN.poly_num_vars]*a[ai+a[ai]-1]+
588 (LONG)b[bi+1+AN.poly_num_vars]*b[bi+b[bi]-1]) % c.modp;
589 if ((WORD)c[ci+1+AN.poly_num_vars] > +c.modp/2) c[ci+1+AN.poly_num_vars] -= c.modp;
590 if ((WORD)c[ci+1+AN.poly_num_vars] < -c.modp/2) c[ci+1+AN.poly_num_vars] += c.modp;
591 nc = (c[ci+1+AN.poly_num_vars]==0 ? 0 : SGN((WORD)c[ci+1+AN.poly_num_vars]));
592 c[ci+1+AN.poly_num_vars] = ABS((WORD)c[ci+1+AN.poly_num_vars]);
595 AddLong((UWORD *)&a[ai+1+AN.poly_num_vars], a[ai+a[ai]-1],
596 (UWORD *)&b[bi+1+AN.poly_num_vars], b[bi+b[bi]-1],
597 (UWORD *)&c[ci+1+AN.poly_num_vars], &nc);
598 if (c.modp!=0) TakeNormalModulus((UWORD *)&c[ci+1+AN.poly_num_vars], &nc,
599 modq, nmodq, NOUNPACK);
603 c[ci] = 2+AN.poly_num_vars+ABS(nc);
632 bool both_mod_small=
false;
636 modq = (UWORD *)&c.modp;
638 if (a.modp>0 && b.modp>0 && a.modn==1 && b.modn==1)
648 while (ai<a[0] || bi<b[0]) {
652 int cmp = ai<a[0] && bi<b[0] ? monomial_compare(BHEAD &a[ai],&b[bi]) : 0;
654 if (bi==b[0] || cmp>0) {
656 c.termscopy(&a[ai],ci,a[ai]);
660 else if (ai==a[0] || cmp<0) {
662 c.termscopy(&b[bi],ci,b[bi]);
669 c.termscopy(&a[ai],ci,MaX(a[ai],b[bi]));
671 if (both_mod_small) {
672 c[ci+1+AN.poly_num_vars] = ((LONG)a[ai+1+AN.poly_num_vars]*a[ai+a[ai]-1]-
673 (LONG)b[bi+1+AN.poly_num_vars]*b[bi+b[bi]-1]) % c.modp;
674 if ((WORD)c[ci+1+AN.poly_num_vars] > +c.modp/2) c[ci+1+AN.poly_num_vars] -= c.modp;
675 if ((WORD)c[ci+1+AN.poly_num_vars] < -c.modp/2) c[ci+1+AN.poly_num_vars] += c.modp;
676 nc = (c[ci+1+AN.poly_num_vars]==0 ? 0 : SGN((WORD)c[ci+1+AN.poly_num_vars]));
677 c[ci+1+AN.poly_num_vars] = ABS((WORD)c[ci+1+AN.poly_num_vars]);
680 AddLong((UWORD *)&a[ai+1+AN.poly_num_vars], a[ai+a[ai]-1],
681 (UWORD *)&b[bi+1+AN.poly_num_vars],-b[bi+b[bi]-1],
682 (UWORD *)&c[ci+1+AN.poly_num_vars], &nc);
683 if (c.modp!=0) TakeNormalModulus((UWORD *)&c[ci+1+AN.poly_num_vars], &nc,
684 modq, nmodq, NOUNPACK);
688 c[ci] = 2+AN.poly_num_vars+ABS(nc);
707void poly::pop_heap (PHEAD WORD **heap,
int n) {
714 while (2*i+2<n && (monomial_compare(BHEAD heap[2*i+1]+3, heap[i]+3)>0 ||
715 monomial_compare(BHEAD heap[2*i+2]+3, heap[i]+3)>0)) {
717 if (monomial_compare(BHEAD heap[2*i+1]+3, heap[2*i+2]+3)>0) {
718 swap(heap[i], heap[2*i+1]);
722 swap(heap[i], heap[2*i+2]);
727 if (2*i+1<n && monomial_compare(BHEAD heap[2*i+1]+3, heap[i]+3)>0)
728 swap(heap[i], heap[2*i+1]);
739void poly::push_heap (PHEAD WORD **heap,
int n) {
743 while (i>0 && monomial_compare(BHEAD heap[i]+3, heap[(i-1)/2]+3) > 0) {
744 swap(heap[(i-1)/2], heap[i]);
755void poly::mul_one_term (
const poly &a,
const poly &b,
poly &c) {
764 bool both_mod_small=
false;
768 modq = (UWORD *)&c.modp;
770 if (a.modp>0 && b.modp>0 && a.modn==1 && b.modn==1)
778 for (
int ai=1; ai<a[0]; ai+=a[ai])
779 for (
int bi=1; bi<b[0]; bi+=b[bi]) {
783 for (
int i=0; i<AN.poly_num_vars; i++)
784 c[ci+1+i] = a[ai+1+i] + b[bi+1+i];
788 if (both_mod_small) {
789 c[ci+1+AN.poly_num_vars] =
790 ((LONG)a[ai+1+AN.poly_num_vars] * a[ai+2+AN.poly_num_vars] *
791 b[bi+1+AN.poly_num_vars] * b[bi+2+AN.poly_num_vars]) % c.modp;
792 nc = (c[ci+1+AN.poly_num_vars]==0 ? 0 : 1);
796 MulLong((UWORD *)&a[ai+1+AN.poly_num_vars], a[ai+a[ai]-1],
797 (UWORD *)&b[bi+1+AN.poly_num_vars], b[bi+b[bi]-1],
798 (UWORD *)&c[ci+1+AN.poly_num_vars], &nc);
799 if (c.modp!=0) TakeNormalModulus((UWORD *)&c[ci+1+AN.poly_num_vars], &nc,
800 modq, nmodq, NOUNPACK);
804 c[ci] = 2+AN.poly_num_vars+ABS(nc);
807 if (both_mod_small) {
808 if (c[ci-2] > +c.modp/2) c[ci-2] -= c.modp;
809 if (c[ci-2] < -c.modp/2) c[ci-2] += c.modp;
810 c[ci-1] = SGN(c[ci-2]);
811 c[ci-2] = ABS(c[ci-2]);
829void poly::mul_univar (
const poly &a,
const poly &b,
poly &c,
int var) {
836 bool both_mod_small=
false;
840 modq = (UWORD *)&c.modp;
842 if (a.modp>0 && b.modp>0 && a.modn==1 && b.modn==1)
856 int minpow = AN.poly_num_vars==0 ? 0 : a.last_monomial()[1+var] + b.last_monomial()[1+var];
857 int maxpow = AN.poly_num_vars==0 ? 0 : a[2+var]+b[2+var];
858 int afirst=1, blast=1;
860 for (
int pow=maxpow; pow>=minpow; pow--) {
867 if (a[afirst+1+var] + b[blast+1+var] > pow) {
868 if (blast+b[blast] < b[0])
875 for (
int ai=afirst, bi=blast; ai<a[0] && bi>=1;) {
877 int thispow = AN.poly_num_vars==0 ? 0 : a[ai+1+var] + b[bi+1+var];
879 if (thispow == pow) {
882 if (both_mod_small) {
883 c[ci+1+AN.poly_num_vars] =
884 ((nc==0 ? 0 : (LONG)c[ci+1+AN.poly_num_vars] * nc) +
885 (LONG)a[ai+1+AN.poly_num_vars] * a[ai+2+AN.poly_num_vars] *
886 b[bi+1+AN.poly_num_vars] * b[bi+2+AN.poly_num_vars]) % c.modp;
887 nc = (c[ci+1+AN.poly_num_vars]==0 ? 0 : 1);
892 MulLong((UWORD *)&a[ai+1+AN.poly_num_vars], a[ai+a[ai]-1],
893 (UWORD *)&b[bi+1+AN.poly_num_vars], b[bi+b[bi]-1],
894 (UWORD *)&t[0], &nt);
896 AddLong ((UWORD *)&t[0], nt,
897 (UWORD *)&c[ci+1+AN.poly_num_vars], nc,
898 (UWORD *)&c[ci+1+AN.poly_num_vars], &nc);
900 if (c.modp!=0) TakeNormalModulus((UWORD *)&c[ci+1+AN.poly_num_vars], &nc,
901 modq, nmodq, NOUNPACK);
905 bi -= ABS(b[bi-1]) + 2 + AN.poly_num_vars;
907 else if (thispow > pow)
910 bi -= ABS(b[bi-1]) + 2 + AN.poly_num_vars;
915 for (
int j=0; j<AN.poly_num_vars; j++)
917 if (AN.poly_num_vars > 0)
920 c[ci] = 2+AN.poly_num_vars+ABS(nc);
924 if (both_mod_small) {
925 if (c[ci-2] > +c.modp/2) c[ci-2] -= c.modp;
926 if (c[ci-2] < -c.modp/2) c[ci-2] += c.modp;
927 c[ci-1] = SGN(c[ci-2]);
928 c[ci-2] = ABS(c[ci-2]);
968 bool both_mod_small=
false;
972 modq = (UWORD *)&c.modp;
974 if (a.modp>0 && b.modp>0 && a.modn==1 && b.modn==1)
983 WORD *maxpower = AT.WorkPointer;
984 AT.WorkPointer += AN.poly_num_vars;
985 WORD *maxpowera = AT.WorkPointer;
986 AT.WorkPointer += AN.poly_num_vars;
987 WORD *maxpowerb = AT.WorkPointer;
988 AT.WorkPointer += AN.poly_num_vars;
990 for (
int i=0; i<AN.poly_num_vars; i++)
991 maxpowera[i] = maxpowerb[i] = 0;
993 for (
int ai=1; ai<a[0]; ai+=a[ai])
994 for (
int j=0; j<AN.poly_num_vars; j++)
995 maxpowera[j] = MaX(maxpowera[j], a[ai+1+j]);
997 for (
int bi=1; bi<b[0]; bi+=b[bi])
998 for (
int j=0; j<AN.poly_num_vars; j++)
999 maxpowerb[j] = MaX(maxpowerb[j], b[bi+1+j]);
1001 for (
int i=0; i<AN.poly_num_vars; i++)
1002 maxpower[i] = maxpowera[i] + maxpowerb[i];
1005 bool use_hash =
true;
1008 for (
int i=0; i<AN.poly_num_vars; i++) {
1009 if (nhash > POLY_MAX_HASH_SIZE / (maxpower[i]+1)) {
1014 nhash *= maxpower[i]+1;
1018 int nheap=a.number_of_terms();
1020 WantAddPointers(nheap+nhash);
1021 WORD **heap = AT.pWorkSpace + AT.pWorkPointer;
1023 for (
int ai=1, i=0; ai<a[0]; ai+=a[ai], i++) {
1024 heap[i] = (WORD *) NumberMalloc(
"poly::mul_heap");
1029 for (
int j=0; j<AN.poly_num_vars; j++)
1030 heap[i][4+j] = MAXPOSITIVE;
1033 WORD **hash = AT.pWorkSpace + AT.pWorkPointer + nheap;
1034 for (
int i=0; i<nhash; i++)
1044 pop_heap(BHEAD heap, nheap--);
1045 WORD *p = heap[nheap];
1049 if (use_hash) hash[p[2]] = NULL;
1054 if (use_hash || ci==1 || monomial_compare(BHEAD p+3, c.last_monomial())!=0) {
1055 p[4 + AN.poly_num_vars + ABS(p[3])] = p[3];
1056 p[3] = 2 + AN.poly_num_vars + ABS(p[3]);
1057 c.termscopy(&p[3],ci,p[3]);
1062 ci = c.last_monomial_index();
1063 WORD nc = c[ci+c[ci]-1];
1066 if (both_mod_small) {
1067 c[ci+AN.poly_num_vars+1] = ((LONG)c[ci+AN.poly_num_vars+1]*nc + p[4+AN.poly_num_vars]*p[3]) % c.modp;
1068 if (c[ci+1+AN.poly_num_vars]==0)
1071 if (c[ci+1+AN.poly_num_vars] > +c.modp/2) c[ci+1+AN.poly_num_vars] -= c.modp;
1072 if (c[ci+1+AN.poly_num_vars] < -c.modp/2) c[ci+1+AN.poly_num_vars] += c.modp;
1073 nc = SGN(c[ci+1+AN.poly_num_vars]);
1074 c[ci+1+AN.poly_num_vars] = ABS(c[ci+1+AN.poly_num_vars]);
1079 AddLong ((UWORD *)&p[4+AN.poly_num_vars], p[3],
1080 (UWORD *)&c[ci+AN.poly_num_vars+1], nc,
1081 (UWORD *)&c[ci+AN.poly_num_vars+1],&nc);
1083 if (c.modp!=0) TakeNormalModulus((UWORD *)&c[ci+1+AN.poly_num_vars], &nc,
1084 modq, nmodq, NOUNPACK);
1088 c[ci] = 2 + AN.poly_num_vars + ABS(nc);
1096 while (p[1] < b[0]) {
1098 for (
int j=0; j<AN.poly_num_vars; j++)
1099 p[4+j] = a[p[0]+1+j] + b[p[1]+1+j];
1102 if (both_mod_small) {
1103 p[4+AN.poly_num_vars] = ((LONG)a[p[0]+1+AN.poly_num_vars]*a[p[0]+a[p[0]]-1]*
1104 b[p[1]+1+AN.poly_num_vars]*b[p[1]+b[p[1]]-1]) % c.modp;
1105 if (p[4+AN.poly_num_vars]==0)
1108 if (p[4+AN.poly_num_vars] > +c.modp/2) p[4+AN.poly_num_vars] -= c.modp;
1109 if (p[4+AN.poly_num_vars] < -c.modp/2) p[4+AN.poly_num_vars] += c.modp;
1110 p[3] = SGN(p[4+AN.poly_num_vars]);
1111 p[4+AN.poly_num_vars] = ABS(p[4+AN.poly_num_vars]);
1116 MulLong((UWORD *)&a[p[0]+1+AN.poly_num_vars], a[p[0]+a[p[0]]-1],
1117 (UWORD *)&b[p[1]+1+AN.poly_num_vars], b[p[1]+b[p[1]]-1],
1118 (UWORD *)&p[4+AN.poly_num_vars], &p[3]);
1120 if (c.modp!=0) TakeNormalModulus((UWORD *)&p[4+AN.poly_num_vars], &p[3],
1121 modq, nmodq, NOUNPACK);
1128 for (
int i=0; i<AN.poly_num_vars; i++)
1129 ID = (maxpower[i]+1)*ID + p[4+i];
1132 if (hash[ID] == NULL) {
1135 push_heap(BHEAD heap, ++nheap);
1142 if (both_mod_small) {
1143 h[4+AN.poly_num_vars] = ((LONG)p[4+AN.poly_num_vars]*p[3] + h[4+AN.poly_num_vars]*h[3]) % c.modp;
1144 if (h[4+AN.poly_num_vars]==0)
1147 if (h[4+AN.poly_num_vars] > +c.modp/2) h[4+AN.poly_num_vars] -= c.modp;
1148 if (h[4+AN.poly_num_vars] < -c.modp/2) h[4+AN.poly_num_vars] += c.modp;
1149 h[3] = SGN(h[4+AN.poly_num_vars]);
1150 h[4+AN.poly_num_vars] = ABS(h[4+AN.poly_num_vars]);
1155 AddLong ((UWORD *)&p[4+AN.poly_num_vars], p[3],
1156 (UWORD *)&h[4+AN.poly_num_vars], h[3],
1157 (UWORD *)&h[4+AN.poly_num_vars], &h[3]);
1159 if (c.modp!=0) TakeNormalModulus((UWORD *)&h[4+AN.poly_num_vars], &h[3],
1160 modq, nmodq, NOUNPACK);
1167 push_heap(BHEAD heap, ++nheap);
1175 for (
int ai=1, i=0; ai<a[0]; ai+=a[ai], i++)
1176 NumberFree(heap[i],
"poly::mul_heap");
1177 AT.WorkPointer -= 3 * AN.poly_num_vars;
1200 if (a.is_zero() || b.is_zero()) { c[0]=1;
return; }
1202 c.check_memory(b[0]);
1203 c.termscopy(b.terms,0,b[0]);
1205 if (a.modp!=b.modp || a.modn!=b.modn) {
1207 c.setmod(a.modp,a.modn);
1212 c.check_memory(a[0]);
1213 c.termscopy(a.terms,0,a[0]);
1217 int na=a.number_of_terms();
1218 int nb=b.number_of_terms();
1220 if (na==1 || nb==1) {
1221 mul_one_term(a,b,c);
1228 if (vara!=-2 && varb!=-2 && vara==varb) {
1229 mul_univar(a,b,c,vara);
1245void poly::divmod_one_term (
const poly &a,
const poly &b,
poly &q,
poly &r,
bool only_divides) {
1247 POLY_GETIDENTITY(a);
1257 bool both_mod_small=
false;
1261 modq = (UWORD *)&q.modp;
1263 if (a.modp>0 && b.modp>0 && a.modn==1 && b.modn==1)
1264 both_mod_small=
true;
1270 ltbinv = NumberMalloc(
"poly::div_one_term");
1272 if (both_mod_small) {
1273 WORD ltb = b[b[1]]*b[2+AN.poly_num_vars];
1274 GetModInverses(ltb + (ltb<0?q.modp:0), q.modp, (WORD*)ltbinv, NULL);
1278 GetLongModInverses(BHEAD (UWORD *)&b[2+AN.poly_num_vars], b[b[1]], modq, nmodq, ltbinv, &nltbinv, NULL, NULL);
1281 for (
int ai=1; ai<a[0]; ai+=a[ai]) {
1288 for (
int j=0; j<AN.poly_num_vars; j++) {
1289 q[qi+1+j] = a[ai+1+j]-b[2+j];
1290 r[ri+1+j] = a[ai+1+j];
1291 if (q[qi+1+j] < 0) div=
false;
1299 DivLong((UWORD *)&a[ai+1+AN.poly_num_vars], a[ai+a[ai]-1],
1300 (UWORD *)&b[2+AN.poly_num_vars], b[b[1]],
1301 (UWORD *)&q[qi+1+AN.poly_num_vars], &nq,
1302 (UWORD *)&r[ri+1+AN.poly_num_vars], &nr);
1306 if (both_mod_small) {
1307 q[qi+1+AN.poly_num_vars] =
1308 ((LONG)a[ai+1+AN.poly_num_vars] * a[ai+a[ai]-1] * ltbinv[0] * nltbinv) % q.modp;
1309 nq = (q[qi+1+AN.poly_num_vars]==0 ? 0 : 1);
1313 MulLong((UWORD *)&a[ai+1+AN.poly_num_vars], a[ai+a[ai]-1],
1315 (UWORD *)&q[qi+1+AN.poly_num_vars], &nq);
1316 TakeNormalModulus((UWORD *)&q[qi+1+AN.poly_num_vars], &nq,
1317 modq,nmodq, NOUNPACK);
1327 r.termscopy(&a[ai+1+AN.poly_num_vars], ri+1+AN.poly_num_vars, ABS(nr));
1332 q[qi] = 2+AN.poly_num_vars+ABS(nq);
1336 if (both_mod_small) {
1337 if (q[qi-2] > +q.modp/2) q[qi-2] -= q.modp;
1338 if (q[qi-2] < -q.modp/2) q[qi-2] += q.modp;
1339 q[qi-1] = SGN(q[qi-2]);
1340 q[qi-2] = ABS(q[qi-2]);
1348 if (only_divides) { r =
poly(BHEAD 1); ri=r[0];
break; }
1349 r[ri] = 2+AN.poly_num_vars+ABS(nr);
1358 if (q.modp!=0 || ltbinv != NULL) NumberFree(ltbinv,
"poly::div_one_term");
1378 POLY_GETIDENTITY(a);
1386 bool both_mod_small=
false;
1390 modq = (UWORD *)&q.modp;
1392 if (a.modp>0 && b.modp>0 && a.modn==1 && b.modn==1)
1393 both_mod_small=
true;
1398 ltbinv = NumberMalloc(
"poly::div_univar");
1400 if (both_mod_small) {
1401 WORD ltb = b[b[1]]*b[2+AN.poly_num_vars];
1402 GetModInverses(ltb + (ltb<0?q.modp:0), q.modp, (WORD*)ltbinv, NULL);
1406 GetLongModInverses(BHEAD (UWORD *)&b[2+AN.poly_num_vars], b[b[1]], modq, nmodq, ltbinv, &nltbinv, NULL, NULL);
1411 UWORD *s = NumberMalloc(
"poly::div_univar");
1412 UWORD *t = NumberMalloc(
"poly::div_univar");
1415 int bpow = b[2+var];
1417 int ai=1, qi=1, ri=1;
1419 for (
int pow=a[2+var]; pow>=0; pow--) {
1425 while (ai<a[0] && a[ai+1+var] > pow)
1429 if (ai<a[0] && a[ai+1+var] == pow) {
1431 WCOPY(s, &a[ai+1+AN.poly_num_vars], ABS(ns));
1440 while (qj>1 && bi<b[0]) {
1442 qj -= 2 + AN.poly_num_vars + ABS(q[qj-1]);
1444 while (bi<b[0] && b[bi+1+var]+q[qj+1+var] > pow)
1447 if (bi<b[0] && b[bi+1+var]+q[qj+1+var] == pow) {
1450 if (both_mod_small) {
1451 s[0] = ((WORD)s[0]*ns - (LONG)b[bi+1+AN.poly_num_vars] * b[bi+b[bi]-1] *
1452 q[qj+1+AN.poly_num_vars] * q[qj+q[qj]-1]) % q.modp;
1453 ns = (s[0]==0 ? 0 : 1);
1457 MulLong((UWORD *)&b[bi+1+AN.poly_num_vars], b[bi+b[bi]-1],
1458 (UWORD *)&q[qj+1+AN.poly_num_vars], q[qj+q[qj]-1],
1461 AddLong(t,nt,s,ns,s,&ns);
1462 if (q.modp!=0) TakeNormalModulus((UWORD *)s,&ns,modq, nmodq, NOUNPACK);
1469 if (both_mod_small) {
1471 if ((WORD)s[0] > +q.modp/2) s[0] -= q.modp;
1472 if ((WORD)s[0] < -q.modp/2) s[0] += q.modp;
1473 ns = SGN((WORD)s[0]);
1474 s[0] = ABS((WORD)s[0]);
1481 (UWORD *)&b[2+AN.poly_num_vars], b[b[1]],
1482 (UWORD *)&q[qi+1+AN.poly_num_vars], &ns, t, &nt);
1485 if (both_mod_small) {
1486 q[qi+1+AN.poly_num_vars] = ((LONG)s[0]*ns*ltbinv[0]*nltbinv) % q.modp;
1487 if ((WORD)q[qi+1+AN.poly_num_vars] > +q.modp/2) q[qi+1+AN.poly_num_vars] -= q.modp;
1488 if ((WORD)q[qi+1+AN.poly_num_vars] < -q.modp/2) q[qi+1+AN.poly_num_vars] += q.modp;
1489 ns = (q[qi+1+AN.poly_num_vars]==0 ? 0 : SGN((WORD)q[qi+1+AN.poly_num_vars]));
1490 q[qi+1+AN.poly_num_vars] = ABS((WORD)q[qi+1+AN.poly_num_vars]);
1493 MulLong(s, ns, ltbinv, nltbinv, (UWORD *)&q[qi+1+AN.poly_num_vars], &ns);
1494 TakeNormalModulus((UWORD *)&q[qi+1+AN.poly_num_vars], &ns,
1495 modq,nmodq, NOUNPACK);
1509 for (
int i=0; i<AN.poly_num_vars; i++)
1511 q[qi+1+var] = pow-bpow;
1513 q[qi] = 2+AN.poly_num_vars+ABS(ns);
1519 if (only_divides) { r=
poly(BHEAD 1); ri=r[0];
break; }
1520 for (
int i=0; i<AN.poly_num_vars; i++)
1524 for (
int i=0; i<ABS(nt); i++)
1525 r[ri+1+AN.poly_num_vars+i] = t[i];
1527 r[ri] = 2+AN.poly_num_vars+ABS(nt);
1537 NumberFree(s,
"poly::div_univar");
1538 NumberFree(t,
"poly::div_univar");
1540 if (q.modp!=0 || ltbinv!=NULL) NumberFree(ltbinv,
"poly::div_univar");
1581 POLY_GETIDENTITY(a);
1591 LONG oldpWorkPointer = AT.pWorkPointer;
1593 bool both_mod_small=
false;
1597 modq = (UWORD *)&q.modp;
1599 if (a.modp>0 && b.modp>0 && a.modn==1 && b.modn==1)
1600 both_mod_small=
true;
1605 ltbinv = NumberMalloc(
"poly::div_heap-a");
1607 if (both_mod_small) {
1608 WORD ltb = b[b[1]]*b[2+AN.poly_num_vars];
1609 GetModInverses(ltb + (ltb<0?q.modp:0), q.modp, (WORD*)ltbinv, NULL);
1613 GetLongModInverses(BHEAD (UWORD *)&b[2+AN.poly_num_vars], b[b[1]], modq, nmodq, ltbinv, &nltbinv, NULL, NULL);
1617 int nb=b.number_of_terms();
1618 WantAddPointers(nb);
1619 WORD **heap = AT.pWorkSpace + AT.pWorkPointer;
1620 AT.pWorkPointer += nb;
1622 for (
int i=0; i<nb; i++)
1623 heap[i] = (WORD *) NumberMalloc(
"poly::div_heap-b");
1628 WCOPY(&heap[0][3], &a[1], a[1]);
1629 heap[0][3] = a[a[1]];
1634 WORD *t = (WORD *) NumberMalloc(
"poly::div_heap-c");
1638 vector<pair<int,int> > insert;
1640 while (insert.size()>0 || nheap>0) {
1650 WORD *p = heap[nheap];
1653 if (insert.empty()) {
1655 this_insert =
false;
1657 pop_heap(BHEAD heap, nheap--);
1661 WCOPY(t, p, (5+ABS(p[3])+AN.poly_num_vars));
1665 if (both_mod_small) {
1666 t[4+AN.poly_num_vars] = ((LONG)t[4+AN.poly_num_vars]*t[3] + p[4+AN.poly_num_vars]*p[3]) % q.modp;
1667 if (t[4+AN.poly_num_vars]==0)
1670 if (t[4+AN.poly_num_vars] > +q.modp/2) t[4+AN.poly_num_vars] -= q.modp;
1671 if (t[4+AN.poly_num_vars] < -q.modp/2) t[4+AN.poly_num_vars] += q.modp;
1672 t[3] = SGN(t[4+AN.poly_num_vars]);
1673 t[4+AN.poly_num_vars] = ABS(t[4+AN.poly_num_vars]);
1678 AddLong ((UWORD *)&p[4+AN.poly_num_vars], p[3],
1679 (UWORD *)&t[4+AN.poly_num_vars], t[3],
1680 (UWORD *)&t[4+AN.poly_num_vars], &t[3]);
1681 if (q.modp!=0) TakeNormalModulus((UWORD *)&t[4+AN.poly_num_vars], &t[3],
1682 modq, nmodq, NOUNPACK);
1690 p[0] = insert.back().first;
1691 p[1] = insert.back().second;
1700 if (p[0]==a[0])
break;
1701 WCOPY(&p[3], &a[p[0]], a[p[0]]);
1707 this_insert =
false;
1709 if (p[1]==qi) { s++;
break; }
1711 for (
int i=0; i<AN.poly_num_vars; i++)
1712 p[4+i] = b[p[0]+1+i] + q[p[1]+1+i];
1715 if (both_mod_small) {
1716 p[4+AN.poly_num_vars] = ((LONG)b[p[0]+1+AN.poly_num_vars]*b[p[0]+b[p[0]]-1]*
1717 q[p[1]+1+AN.poly_num_vars]*q[p[1]+q[p[1]]-1]) % q.modp;
1718 if (p[4+AN.poly_num_vars]==0)
1721 if (p[4+AN.poly_num_vars] > +q.modp/2) p[4+AN.poly_num_vars] -= q.modp;
1722 if (p[4+AN.poly_num_vars] < -q.modp/2) p[4+AN.poly_num_vars] += q.modp;
1723 p[3] = SGN(p[4+AN.poly_num_vars]);
1724 p[4+AN.poly_num_vars] = ABS(p[4+AN.poly_num_vars]);
1729 MulLong((UWORD *)&b[p[0]+1+AN.poly_num_vars], b[p[0]+b[p[0]]-1],
1730 (UWORD *)&q[p[1]+1+AN.poly_num_vars], q[p[1]+q[p[1]]-1],
1731 (UWORD *)&p[4+AN.poly_num_vars], &p[3]);
1732 if (q.modp!=0) TakeNormalModulus((UWORD *)&p[4+AN.poly_num_vars], &p[3],
1733 modq, nmodq, NOUNPACK);
1743 swap (heap[nheap],p);
1744 push_heap(BHEAD heap, ++nheap);
1748 while (t[0]==-1 || (nheap>0 && monomial_compare(BHEAD heap[0]+3, t+3)==0));
1750 if (t[3] == 0)
continue;
1754 for (
int i=0; i<AN.poly_num_vars; i++)
1755 if (t[4+i] < b[2+i]) div=
false;
1759 if (only_divides) { r=
poly(BHEAD 1); ri=r[0];
break; }
1760 t[4 + AN.poly_num_vars + ABS(t[3])] = t[3];
1761 t[3] = 2 + AN.poly_num_vars + ABS(t[3]);
1762 r.termscopy(&t[3], ri, t[3]);
1770 DivLong((UWORD *)&t[4+AN.poly_num_vars], t[3],
1771 (UWORD *)&b[2+AN.poly_num_vars], b[b[1]],
1772 (UWORD *)&q[qi+1+AN.poly_num_vars], &nq,
1773 (UWORD *)&r[ri+1+AN.poly_num_vars], &nr);
1774 if(check_div && nr != 0)
1783 if (both_mod_small) {
1784 q[qi+1+AN.poly_num_vars] = ((LONG)t[4+AN.poly_num_vars]*t[3]*ltbinv[0]*nltbinv) % q.modp;
1785 if (q[qi+1+AN.poly_num_vars]==0)
1788 if (q[qi+1+AN.poly_num_vars] > +q.modp/2) q[qi+1+AN.poly_num_vars] -= q.modp;
1789 if (q[qi+1+AN.poly_num_vars] < -q.modp/2) q[qi+1+AN.poly_num_vars] += q.modp;
1790 nq = SGN(q[qi+1+AN.poly_num_vars]);
1791 q[qi+1+AN.poly_num_vars] = ABS(q[qi+1+AN.poly_num_vars]);
1796 MulLong((UWORD *)&t[4+AN.poly_num_vars], t[3], ltbinv, nltbinv, (UWORD *)&q[qi+1+AN.poly_num_vars], &nq);
1797 TakeNormalModulus((UWORD *)&q[qi+1+AN.poly_num_vars], &nq, modq, nmodq, NOUNPACK);
1806 for (
int j=1; j<s; j++) {
1808 insert.push_back(make_pair(bi,qi));
1812 q[qi] = 2+AN.poly_num_vars+ABS(nq);
1813 for (
int i=0; i<AN.poly_num_vars; i++)
1814 q[qi+1+i] = t[4+i] - b[2+i];
1820 r[ri] = 2+AN.poly_num_vars+ABS(nr);
1821 for (
int i=0; i<AN.poly_num_vars; i++)
1832 for (
int i=0; i<nb; i++)
1833 NumberFree(heap[i],
"poly::div_heap-b");
1835 NumberFree(t,
"poly::div_heap-c");
1837 if (q.modp!=0||ltbinv!=NULL) NumberFree(ltbinv,
"poly::div_heap-a");
1838 AT.pWorkPointer = oldpWorkPointer;
1858 q.modp = r.modp = a.modp;
1859 q.modn = r.modn = a.modn;
1867 MLOCK(ErrorMessageLock);
1868 MesPrint ((
char*)
"ERROR: division by zero polynomial");
1869 MUNLOCK(ErrorMessageLock);
1873 q.check_memory(a[0]);
1874 q.termscopy(a.terms,0,a[0]);
1879 if (b.is_monomial()) {
1880 divmod_one_term(a,b,q,r,only_divides);
1887 if (vara!=-2 && varb!=-2 && (vara==-1 || varb==-1 || vara==varb)) {
1902bool poly::divides (
const poly &a,
const poly &b) {
1903 POLY_GETIDENTITY(a);
1904 poly q(BHEAD 0), r(BHEAD 0);
1915void poly::div (
const poly &a,
const poly &b,
poly &c) {
1916 POLY_GETIDENTITY(a);
1927void poly::mod (
const poly &a,
const poly &b,
poly &c) {
1928 POLY_GETIDENTITY(a);
1939poly & poly::operator= (
const poly &a) {
1940#ifdef POLY_MOVE_DEBUG
1941 std::cout <<
"poly copy assign" << std::endl;
1947 termscopy(a.terms,0,a[0]);
1959const poly poly::operator+ (
const poly &a)
const { POLY_GETIDENTITY(a);
poly b(BHEAD 0); add(*
this,a,b);
return b; }
1960const poly poly::operator- (
const poly &a)
const { POLY_GETIDENTITY(a);
poly b(BHEAD 0); sub(*
this,a,b);
return b; }
1961const poly poly::operator* (
const poly &a)
const { POLY_GETIDENTITY(a);
poly b(BHEAD 0);
mul(*
this,a,b);
return b; }
1962const poly poly::operator/ (
const poly &a)
const { POLY_GETIDENTITY(a);
poly b(BHEAD 0); div(*
this,a,b);
return b; }
1963const poly poly::operator% (
const poly &a)
const { POLY_GETIDENTITY(a);
poly b(BHEAD 0); mod(*
this,a,b);
return b; }
1966poly& poly::operator+= (
const poly &a) {
return *
this = *
this + a; }
1967poly& poly::operator-= (
const poly &a) {
return *
this = *
this - a; }
1968poly& poly::operator*= (
const poly &a) {
return *
this = *
this * a; }
1969poly& poly::operator/= (
const poly &a) {
return *
this = *
this / a; }
1970poly& poly::operator%= (
const poly &a) {
return *
this = *
this % a; }
1973bool poly::operator== (
const poly &a)
const {
1974 for (
int i=0; i<terms[0]; i++)
1975 if (terms[i] != a[i])
return 0;
1979bool poly::operator!= (
const poly &a)
const {
return !(*
this == a); }
1986int poly::number_of_terms ()
const {
1989 for (
int i=1; i<terms[0]; i+=terms[i])
2000int poly::first_variable ()
const {
2002 POLY_GETIDENTITY(*
this);
2004 int var = AN.poly_num_vars;
2005 for (
int j=0; j<var; j++)
2006 if (terms[2+j]>0)
return j;
2016const vector<int> poly::all_variables ()
const {
2018 POLY_GETIDENTITY(*
this);
2020 vector<bool> used(AN.poly_num_vars,
false);
2022 for (
int i=1; i<terms[0]; i+=terms[i])
2023 for (
int j=0; j<AN.poly_num_vars; j++)
2024 if (terms[i+1+j]>0) used[j] =
true;
2027 for (
int i=0; i<AN.poly_num_vars; i++)
2028 if (used[i]) vars.push_back(i);
2039int poly::sign ()
const {
2040 if (terms[0]==1)
return 0;
2041 return terms[terms[1]] > 0 ? 1 : -1;
2050int poly::degree (
int x)
const {
2052 for (
int i=1; i<terms[0]; i+=terms[i])
2053 deg = MaX(deg, terms[i+1+x]);
2063int poly::total_degree ()
const {
2065 POLY_GETIDENTITY(*
this);
2068 for (
int i=1; i<terms[0]; i+=terms[i]) {
2070 for (
int j=0; j<AN.poly_num_vars; j++)
2071 deg += terms[i+1+j];
2072 tot_deg = MaX(deg, tot_deg);
2083const poly poly::integer_lcoeff ()
const {
2085 POLY_GETIDENTITY(*
this);
2091 res.termscopy(&terms[1],1,terms[1]);
2092 res[0] = res[1] + 1;
2093 for (
int i=0; i<AN.poly_num_vars; i++)
2105const poly poly::coefficient (
int x,
int n)
const {
2107 POLY_GETIDENTITY(*
this);
2114 for (
int i=1; i<terms[0]; i+=terms[i])
2115 if (terms[i+1+x] == n) {
2116 res.check_memory(res[0]+terms[i]);
2117 res.termscopy(&terms[i], res[0], terms[i]);
2118 res[res[0]+1+x] -= n;
2119 res[0] += res[res[0]];
2133const poly poly::lcoeff_univar (
int x)
const {
2134 return coefficient(x, degree(x));
2140const poly poly::lcoeff_multivar (
int x)
const {
2142 POLY_GETIDENTITY(*
this);
2144 poly res(BHEAD 0,modp,modn);
2146 for (
int i=1; i<terms[0]; i+=terms[i]) {
2147 bool same_powers =
true;
2148 for (
int j=0; j<AN.poly_num_vars; j++)
2149 if (j!=x && terms[i+1+j]!=terms[2+j]) {
2150 same_powers =
false;
2153 if (!same_powers)
break;
2155 res.check_memory(res[0]+terms[i]);
2156 res.termscopy(&terms[i],res[0],terms[i]);
2157 for (
int k=0; k<AN.poly_num_vars; k++)
2158 if (k!=x) res[res[0]+1+k]=0;
2172const poly poly::derivative (
int x)
const {
2174 POLY_GETIDENTITY(*
this);
2179 for (
int i=1; i<terms[0]; i+=terms[i]) {
2181 int power = terms[i+1+x];
2185 b.termscopy(&terms[i], bi, terms[i]);
2188 WORD nb = b[bi+b[bi]-1];
2189 Product((UWORD *)&b[bi+1+AN.poly_num_vars], &nb, power);
2191 b[bi] = 2 + AN.poly_num_vars + ABS(nb);
2199 b.setmod(modp, modn);
2209bool poly::is_zero ()
const {
2210 return terms[0] == 1;
2219bool poly::is_one ()
const {
2221 POLY_GETIDENTITY(*
this);
2223 if (terms[0] != 4+AN.poly_num_vars)
return false;
2224 if (terms[1] != 3+AN.poly_num_vars)
return false;
2225 for (
int i=0; i<AN.poly_num_vars; i++)
2226 if (terms[2+i] != 0)
return false;
2227 if (terms[2+AN.poly_num_vars]!=1)
return false;
2228 if (terms[3+AN.poly_num_vars]!=1)
return false;
2239bool poly::is_integer ()
const {
2241 POLY_GETIDENTITY(*
this);
2243 if (terms[0] == 1)
return true;
2244 if (terms[0] != terms[1]+1)
return false;
2246 for (
int j=0; j<AN.poly_num_vars; j++)
2247 if (terms[2+j] != 0)
2259bool poly::is_monomial ()
const {
2260 return terms[0]>1 && terms[0]==terms[1]+1;
2286 POLY_GETIDENTITY(*
this);
2288 int num_terms=0, res=-1;
2291 for (
int i=1; i<terms[0]; i+=terms[i]) {
2292 for (
int j=0; j<AN.poly_num_vars; j++)
2293 if (terms[i+1+j] > 0) {
2294 if (res == -1) res = j;
2295 if (res != j)
return -2;
2302 if (res == -1)
return -1;
2305 int deg = terms[2+res];
2306 if (2*num_terms < deg+1)
return -2;
2317const poly poly::simple_poly (PHEAD
int x,
int a,
int b,
int p,
int n) {
2319 poly tmp(BHEAD 0,p,n);
2322 tmp[idx++] = 3 + AN.poly_num_vars;
2323 for (
int i=0; i<AN.poly_num_vars; i++)
2324 tmp[idx++] = i==x ? 1 : 0;
2329 tmp[idx++] = 3 + AN.poly_num_vars;
2330 for (
int i=0; i<AN.poly_num_vars; i++) tmp[idx++] = 0;
2331 tmp[idx++] = ABS(a);
2332 tmp[idx++] = -SGN(a);
2337 if (b == 1)
return tmp;
2339 poly res(BHEAD 1,p,n);
2356const poly poly::simple_poly (PHEAD
int x,
const poly &a,
int b,
int p,
int n) {
2358 poly res(BHEAD 1,p,n);
2359 poly tmp(BHEAD 0,p,n);
2363 tmp[idx++] = 3 + AN.poly_num_vars;
2364 for (
int i=0; i<AN.poly_num_vars; i++)
2365 tmp[idx++] = i==x ? 1 : 0;
2370 tmp[idx++] = 2 + AN.poly_num_vars + ABS(a[a[0]-1]);
2371 for (
int i=0; i<AN.poly_num_vars; i++) tmp[idx++] = 0;
2372 for (
int i=0; i<ABS(a[a[0]-1]); i++)
2373 tmp[idx++] = a[2 + AN.poly_num_vars + i];
2374 tmp[idx++] = -a[a[0]-1];
2395void poly::get_variables (PHEAD
const vector<WORD *> &es,
bool with_arghead,
bool sort_vars) {
2396 assert(AN.poly_vars == NULL);
2398 AN.poly_num_vars = 0;
2401 vector<int> degrees;
2402 map<int,int> var_to_idx;
2405 for (
int ei=0; ei<(int)es.size(); ei++) {
2406 const WORD *e = es[ei];
2409 if (*e == -SNUMBER) {
2411 else if (*e == -SYMBOL) {
2412 if (!var_to_idx.count(e[1])) {
2413 vars.push_back(e[1]);
2414 var_to_idx[e[1]] = AN.poly_num_vars++;
2415 degrees.push_back(1);
2420 MLOCK(ErrorMessageLock);
2421 MesPrint ((
char*)
"ERROR: polynomials and polyratfuns must contain symbols only");
2422 MUNLOCK(ErrorMessageLock);
2426 for (
int i=with_arghead ? ARGHEAD : 0; with_arghead ? i<e[0] : e[i]!=0; i+=e[i]) {
2427 if (i+1<i+e[i]-ABS(e[i+e[i]-1]) && e[i+1]!=SYMBOL) {
2428 MLOCK(ErrorMessageLock);
2429 MesPrint ((
char*)
"ERROR: polynomials and polyratfuns must contain symbols only");
2430 MUNLOCK(ErrorMessageLock);
2434 for (
int j=i+3; j<i+e[i]-ABS(e[i+e[i]-1]); j+=2) {
2435 if (!var_to_idx.count(e[j])) {
2436 vars.push_back(e[j]);
2437 var_to_idx[e[j]] = AN.poly_num_vars++;
2438 degrees.push_back(e[j+1]);
2441 degrees[var_to_idx[e[j]]] = MaX(degrees[var_to_idx[e[j]]], e[j+1]);
2449 if (var_to_idx.count(FACTORSYMBOL)) {
2450 int i = var_to_idx[FACTORSYMBOL];
2451 while (i+1<AN.poly_num_vars) {
2452 swap(vars[i], vars[i+1]);
2453 swap(degrees[i], degrees[i+1]);
2463 if ( (AN.poly_num_vars+1)*
sizeof(WORD) > (
size_t)(AM.MaxTer) ) {
2465 AN.poly_vars = (WORD *)Malloc1((AN.poly_num_vars+1)*
sizeof(WORD),
"AN.poly_vars");
2466 AN.poly_vars_type = 1;
2469 AN.poly_vars = TermMalloc(
"AN.poly_vars");
2470 AN.poly_vars_type = 0;
2473 for (
int i=0; i<AN.poly_num_vars; i++)
2474 AN.poly_vars[i] = vars[i];
2479 for (
int i=0; i<AN.poly_num_vars; i++)
2480 for (
int j=0; j+1<AN.poly_num_vars; j++)
2481 if (degrees[j] < degrees[j+1]) {
2482 swap(degrees[j], degrees[j+1]);
2483 swap(AN.poly_vars[j], AN.poly_vars[j+1]);
2488 sort(AN.poly_vars, AN.poly_vars+AN.poly_num_vars - var_to_idx.count(FACTORSYMBOL));
2498const poly poly::argument_to_poly (PHEAD WORD *e,
bool with_arghead,
bool sort_univar,
poly *denpoly) {
2500 map<int,int> var_to_idx;
2501 for (
int i=0; i<AN.poly_num_vars; i++)
2502 var_to_idx[AN.poly_vars[i]] = i;
2507 if (*e == -SNUMBER) {
2508 if (denpoly!=NULL) *denpoly =
poly(BHEAD 1);
2515 res[0] = 4 + AN.poly_num_vars;
2516 res[1] = 3 + AN.poly_num_vars;
2517 for (
int i=0; i<AN.poly_num_vars; i++)
2519 res[2+AN.poly_num_vars] = ABS(e[1]);
2520 res[3+AN.poly_num_vars] = SGN(e[1]);
2526 if (*e == -SYMBOL) {
2527 if (denpoly!=NULL) *denpoly =
poly(BHEAD 1);
2529 res[0] = 4 + AN.poly_num_vars;
2530 res[1] = 3 + AN.poly_num_vars;
2531 for (
int i=0; i<AN.poly_num_vars; i++)
2533 res[2+var_to_idx.find(e[1])->second] = 1;
2534 res[2+AN.poly_num_vars] = 1;
2535 res[3+AN.poly_num_vars] = 1;
2540 WORD nden=1, npro=0, ngcd=0, ndum=0;
2541 UWORD *den = NumberMalloc(
"poly::argument_to_poly");
2542 UWORD *pro = NumberMalloc(
"poly::argument_to_poly");
2543 UWORD *gcd = NumberMalloc(
"poly::argument_to_poly");
2544 UWORD *dum = NumberMalloc(
"poly::argument_to_poly");
2547 for (
int i=with_arghead ? ARGHEAD : 0; with_arghead ? i<e[0] : e[i]!=0; i+=e[i]) {
2548 int ncoe = ABS(e[i+e[i]-1]/2);
2549 UWORD *coe = (UWORD *)&e[i+e[i]-ncoe-1];
2550 while (ncoe>0 && coe[ncoe-1]==0) ncoe--;
2551 MulLong(den,nden,coe,ncoe,pro,&npro);
2552 GcdLong(BHEAD den,nden,coe,ncoe,gcd,&ngcd);
2553 DivLong(pro,npro,gcd,ngcd,den,&nden,dum,&ndum);
2556 if (denpoly!=NULL) *denpoly =
poly(BHEAD den, nden);
2561 for (
int i=with_arghead ? ARGHEAD : 0; with_arghead ? i<e[0] : e[i]!=0; i+=e[i]) {
2562 res.check_memory(ri);
2563 WORD nc = e[i+e[i]-1];
2564 for (
int j=0; j<AN.poly_num_vars; j++)
2566 WCOPY(dum, &e[i+e[i]-ABS(nc)], ABS(nc));
2568 Mully(BHEAD dum, &nc, den, nden);
2569 res.termscopy((WORD *)dum, ri+1+AN.poly_num_vars, ABS(nc));
2570 res[ri] = ABS(nc) + AN.poly_num_vars + 2;
2571 res[ri+res[ri]-1] = nc;
2572 for (
int j=i+3; j<i+e[i]-ABS(e[i+e[i]-1]); j+=2)
2573 res[ri+1+var_to_idx.find(e[j])->second] = e[j+1];
2585 if (sort_univar ==
false && AN.poly_num_vars == 1) {
2586 if (res.number_of_terms() >= 2) {
2587 if(res[2] < res.last_monomial()[2]) {
2593 if (sort_univar || AN.poly_num_vars>1) {
2597 NumberFree(den,
"poly::argument_to_poly");
2598 NumberFree(pro,
"poly::argument_to_poly");
2599 NumberFree(gcd,
"poly::argument_to_poly");
2600 NumberFree(dum,
"poly::argument_to_poly");
2611void poly::poly_to_argument (
const poly &a, WORD *res,
bool with_arghead) {
2613 POLY_GETIDENTITY(a);
2628 res[1] = AN.poly_num_vars>1 ? DIRTYFLAG : 0;
2629 for (
int i=2; i<ARGHEAD; i++)
2633 int L = with_arghead ? ARGHEAD : 0;
2635 for (
int i=1; i!=a[0]; i+=a[i]) {
2641 for (
int j=0; j<AN.poly_num_vars; j++)
2648 res[L+1+res[L+2]++] = AN.poly_vars[j];
2649 res[L+1+res[L+2]++] = a[i+1+j];
2652 if (!first) res[L] += res[L+2];
2654 WORD nc = a[i+a[i]-1];
2655 WCOPY(&res[L+res[L]], &a[i+a[i]-1-ABS(nc)], ABS(nc));
2658 memset(&res[L+res[L]], 0, ABS(nc)*
sizeof(WORD));
2661 res[L+res[L]] = SGN(nc) * (2*ABS(nc)+1);
2683void poly::poly_to_argument_with_den (
const poly &a, WORD nden,
const UWORD *den, WORD *res,
bool with_arghead) {
2685 POLY_GETIDENTITY(a);
2700 res[1] = AN.poly_num_vars>1 ? DIRTYFLAG : 0;
2701 for (
int i=2; i<ARGHEAD; i++)
2706 UWORD *den1 = (UWORD *)NumberMalloc(
"poly_to_argument_with_den");
2708 int L = with_arghead ? ARGHEAD : 0;
2710 for (
int i=1; i!=a[0]; i+=a[i]) {
2716 for (
int j=0; j<AN.poly_num_vars; j++)
2723 res[L+1+res[L+2]++] = AN.poly_vars[j];
2724 res[L+1+res[L+2]++] = a[i+1+j];
2727 if (!first) res[L] += res[L+2];
2730 WORD nc = a[i+a[i]-1];
2731 WCOPY(&res[L+res[L]], &a[i+a[i]-1-ABS(nc)], ABS(nc));
2735 WCOPY(den1, den, ABS(nden));
2737 if (nden != 1 || den[0] != 1) {
2739 Simplify(BHEAD (UWORD *)&res[L+res[L]], &nc, den1, &nden1);
2742 Pack((UWORD *)&res[L+res[L]], &nc, den1, nden1);
2743 res[L] += 2*ABS(nc)+1;
2744 res[L+res[L]-1] = SGN(nc)*(2*ABS(nc)+1);
2748 NumberFree(den1,
"poly_to_argument_with_den");
2766int poly::size_of_form_notation ()
const {
2768 POLY_GETIDENTITY(*
this);
2771 if (terms[0]==1)
return 0;
2775 for (
int i=1; i!=terms[0]; i+=terms[i]) {
2778 for (
int j=0; j<AN.poly_num_vars; j++)
2779 if (terms[i+1+j] > 0) npow++;
2780 if (npow > 0) len += 2*npow + 2;
2781 len += 2 * ABS(terms[i+terms[i]-1]) + 1;
2795int poly::size_of_form_notation_with_den (WORD nden)
const {
2797 POLY_GETIDENTITY(*
this);
2800 if (terms[0]==1)
return 0;
2805 for (
int i=1; i!=terms[0]; i+=terms[i]) {
2808 for (
int j=0; j<AN.poly_num_vars; j++)
2809 if (terms[i+1+j] > 0) npow++;
2810 if (npow > 0) len += 2*npow + 2;
2811 len += 2 * MaX(ABS(terms[i+terms[i]-1]), nden) + 1;
2823const vector<WORD> poly::to_coefficient_list (
const poly &a) {
2825 POLY_GETIDENTITY(a);
2827 if (a.is_zero())
return vector<WORD>();
2829 int x = a.first_variable();
2830 if (x == AN.poly_num_vars) x=0;
2832 vector<WORD> res(1+a[2+x],0);
2834 for (
int i=1; i<a[0]; i+=a[i])
2835 res[a[i+1+x]] = (a[i+a[i]-1] * a[i+a[i]-2]) % a.modp;
2846const vector<WORD> poly::coefficient_list_divmod (
const vector<WORD> &a,
const vector<WORD> &b, WORD p,
int divmod) {
2848 int bsize = (int)b.size();
2849 while (b[bsize-1]==0) bsize--;
2854 vector<WORD> q(a.size(),0);
2857 while ((
int)r.size() >= bsize) {
2858 LONG
mul = ((LONG)inv * r.back()) % p;
2859 int off = r.size()-bsize;
2861 for (
int i=0; i<bsize; i++)
2862 r[off+i] = (r[off+i] -
mul*b[i]) % p;
2863 while (r.size()>0 && r.back()==0)
2868 while (q.size()>0 && q.back()==0)
2873 while (r.size()>0 && r.back()==0)
2885const poly poly::from_coefficient_list (PHEAD
const vector<WORD> &a,
int x, WORD p) {
2890 for (
int i=(
int)a.size()-1; i>=0; i--)
2892 res.check_memory(ri);
2893 res[ri] = AN.poly_num_vars+3;
2894 for (
int j=0; j<AN.poly_num_vars; j++)
2897 res[ri+1+AN.poly_num_vars] = ABS(a[i]);
2898 res[ri+1+AN.poly_num_vars+1] = SGN(a[i]);
static void divmod(const poly &, const poly &, poly &, poly &, bool only_divides)
static void mul_heap(const poly &, const poly &, poly &)
int is_dense_univariate() const
static void divmod_univar(const poly &, const poly &, poly &, poly &, int, bool)
static void mul(const poly &, const poly &, poly &)
static void divmod_heap(const poly &, const poly &, poly &, poly &, bool, bool, bool &)
void RaisPowCached(PHEAD WORD, WORD, UWORD **, WORD *)
int GetModInverses(WORD, WORD, WORD *, WORD *)