52const int POLYWRAP_DENOMPOWER_INCREASE_FACTOR = 2;
81 if (AC.ncmod==0)
return 0;
83 if (!is_fun_arg || (AC.modmode & ALSOFUNARGS)) {
85 if (ABS(AC.ncmod)>1) {
86 MLOCK(ErrorMessageLock);
87 MesPrint ((
char*)
"ERROR: %s with modulus > WORDSIZE not implemented",message.c_str());
88 MUNLOCK(ErrorMessageLock);
92 if (multi_error && AN.poly_num_vars>1) {
93 MLOCK(ErrorMessageLock);
94 MesPrint ((
char*)
"ERROR: multivariate %s with modulus not implemented",message.c_str());
95 MUNLOCK(ErrorMessageLock);
127 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
128 WORD *ret = flint_gcd(BHEAD a, b, fit);
134 cout <<
"*** [" << thetime() <<
"] CALL : poly_gcd" << endl;
159 poly::get_variables(BHEAD e,
false,
true);
165 poly pa(poly::argument_to_poly(BHEAD a,
false,
true), modp, 1);
166 poly pb(poly::argument_to_poly(BHEAD b,
false,
true), modp, 1);
169 poly gcd(polygcd::gcd(pa,pb));
172 int newsize = (gcd.size_of_form_notation()+1);
175 if ( newsize*
sizeof(WORD) >= (size_t)(AM.MaxTer) ) {
176 MLOCK(ErrorMessageLock);
177 MesPrint(
"poly_gcd: Term too complex (%d words). Maybe increasing MaxTermSize (%d words) can help",
178 newsize, AM.MaxTer/
sizeof(WORD));
179 MUNLOCK(ErrorMessageLock);
182 res = TermMalloc(
"poly_gcd");
185 res = (WORD *)Malloc1(newsize*
sizeof(WORD),
"poly_gcd");
187 poly::poly_to_argument(gcd, res,
false);
189 poly_free_poly_vars(BHEAD
"AN.poly_vars_qcd");
203WORD *poly_divmod(PHEAD WORD *a, WORD *b,
int divmod, WORD fit) {
206 cout <<
"*** [" << thetime() <<
"] CALL : poly_divmod" << endl;
217 poly::get_variables(BHEAD e,
false,
false);
220 const int DENOMSYMBOL = MAXPOSITIVE;
229 AN.poly_vars[AN.poly_num_vars++] = DENOMSYMBOL;
234 poly pa(poly::argument_to_poly(BHEAD a,
false,
true, &dena), modp, 1);
235 poly pb(poly::argument_to_poly(BHEAD b,
false,
true, &denb), modp, 1);
238 poly numres(polygcd::integer_content(pa));
239 poly denres(polygcd::integer_content(pb));
251 poly gcdres(polygcd::integer_gcd(numres,denres));
256 poly lcoeffb(pb.integer_lcoeff());
260 if (!lcoeffb.is_one()) {
262 if (AN.poly_num_vars > 2) {
267 int denompower = 0, prevdenompower = 0;
272 bool div_fail =
true;
275 if(denompower < prevdenompower)
279 MLOCK(ErrorMessageLock);
280 MesPrint ((
char*)
"!>ERROR: pseudo-division failed in poly_divmod (denompower > INT_MAX)");
281 MUNLOCK(ErrorMessageLock);
289 WORD n = lcoeffb[lcoeffb[1]];
290 RaisPow(BHEAD (UWORD *)&lcoeffb[2+AN.poly_num_vars], &n, denompower-prevdenompower);
291 lcoeffb[1] = 2 + AN.poly_num_vars + ABS(n);
292 lcoeffb[0] = 1 + lcoeffb[1];
293 lcoeffb[lcoeffb[1]] = n;
304 prevdenompower = denompower;
305 denompower = (denompower==0 ? 1 : denompower*POLYWRAP_DENOMPOWER_INCREASE_FACTOR+1 );
309 pres = (divmod==0 ? pq : pr);
315 int denompower = MaX(0, pa.degree(0) - pb.degree(0) + 1);
318 WORD n = lcoeffb[lcoeffb[1]];
319 RaisPow(BHEAD (UWORD *)&lcoeffb[2+AN.poly_num_vars], &n, denompower);
320 lcoeffb[1] = 2 + AN.poly_num_vars + ABS(n);
321 lcoeffb[0] = 1 + lcoeffb[1];
322 lcoeffb[lcoeffb[1]] = n;
327 pres = (divmod==0 ? pa/pb : pa%pb);
334 pres = (divmod==0 ? pa/pb : pa%pb);
346 res = TermMalloc(
"poly_divmod");
349 res = (WORD *)Malloc1(
sizeof(WORD),
"poly_divmod");
357 UWORD *den = (UWORD *)NumberMalloc(
"poly_divmod");
361 int ressize = pres.size_of_form_notation() + pres.number_of_terms()*2*ABS(denres[denres[1]]) + 1;
364 if ( ressize*
sizeof(WORD) > (
size_t)(AM.MaxTer) ) {
365 MLOCK(ErrorMessageLock);
366 MesPrint(
"poly_divmod: Term too complex (%d words). Maybe increasing MaxTermSize (%d words) can help",
367 ressize, AM.MaxTer/
sizeof(WORD));
368 MUNLOCK(ErrorMessageLock);
371 res = TermMalloc(
"poly_divmod");
374 res = (WORD *)Malloc1(ressize*
sizeof(WORD),
"poly_divmod");
378 for (
int i=1; i!=pres[0]; i+=pres[i]) {
383 for (
int j=0; j<AN.poly_num_vars; j++)
384 if (pres[i+1+j] > 0) {
390 res[L+1+res[L+2]++] = AN.poly_vars[j];
391 res[L+1+res[L+2]++] = pres[i+1+j];
394 if (!first) res[L] += res[L+2];
397 WORD nnum = pres[i+pres[i]-1];
398 WCOPY(&res[L+res[L]], &pres[i+pres[i]-1-ABS(nnum)], ABS(nnum));
401 nden = denres[denres[1]];
402 WCOPY(den, &denres[2+AN.poly_num_vars], ABS(nden));
404 if (nden!=1 || den[0]!=1)
405 Simplify(BHEAD (UWORD *)&res[L+res[L]], &nnum, den, &nden);
406 Pack((UWORD *)&res[L+res[L]], &nnum, den, nden);
407 res[L] += 2*ABS(nnum)+1;
408 res[L+res[L]-1] = SGN(nnum)*(2*ABS(nnum)+1);
414 NumberFree(den,
"poly_divmod");
418 poly_free_poly_vars(BHEAD
"AN.poly_vars_divmod");
437WORD *poly_div(PHEAD WORD *a, WORD *b, WORD fit) {
440 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
441 WORD *ret = flint_div(BHEAD a, b, fit);
447 cout <<
"*** [" << thetime() <<
"] CALL : poly_div" << endl;
450 return poly_divmod(BHEAD a, b, 0, fit);
465WORD *poly_rem(PHEAD WORD *a, WORD *b, WORD fit) {
468 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
469 WORD *ret = flint_rem(BHEAD a, b, fit);
475 cout <<
"*** [" << thetime() <<
"] CALL : poly_rem" << endl;
478 return poly_divmod(BHEAD a, b, 1, fit);
501 cout <<
"*** [" << thetime() <<
"] CALL : poly_ratfun_read" << endl;
504 POLY_GETIDENTITY(num);
508 WORD *astop = a+a[1];
510 bool clean = (a[2] & MUSTCLEANPRF) == 0;
514 MLOCK(ErrorMessageLock);
515 MesPrint ((
char*)
"ERROR: PolyRatFun cannot have zero arguments");
516 MUNLOCK(ErrorMessageLock);
520 poly den_num(BHEAD 1),den_den(BHEAD 1);
522 num = poly::argument_to_poly(BHEAD a,
true, !clean, &den_num);
527 den = poly::argument_to_poly(BHEAD a,
true, !clean, &den_den);
532 den =
poly(BHEAD 1, modp, 1);
536 MLOCK(ErrorMessageLock);
537 MesPrint ((
char*)
"ERROR: PolyRatFun cannot have more than two arguments");
538 MUNLOCK(ErrorMessageLock);
545 vector<WORD> minpower(AN.poly_num_vars, MAXPOSITIVE);
547 for (
int i=1; i<num[0]; i+=num[i]) {
548 for (
int j=0; j<AN.poly_num_vars; j++) {
549 minpower[j] = MiN(minpower[j], num[i+1+j]);
552 for (
int i=1; i<den[0]; i+=den[i]) {
553 for (
int j=0; j<AN.poly_num_vars; j++) {
554 minpower[j] = MiN(minpower[j], den[i+1+j]);
555 if ( minpower[j] < 0 ) clean =
false;
560 for (
int i=1; i<num[0]; i+=num[i])
561 for (
int j=0; j<AN.poly_num_vars; j++)
562 num[i+1+j] -= minpower[j];
563 for (
int i=1; i<den[0]; i+=den[i])
564 for (
int j=0; j<AN.poly_num_vars; j++)
565 den[i+1+j] -= minpower[j];
570 poly gcd = polygcd::gcd(num,den);
595 cout <<
"*** [" << thetime() <<
"] CALL : poly_sort" << endl;
597 if (
NewSort(BHEAD0)) { Terminate(-1); }
600 for (
int i=ARGHEAD; i<a[0]; i+=a[i]) {
602 AR.CompareRoutine = (COMPAREDUMMY)(&
Compare1);
608 if (
EndSort(BHEAD a+ARGHEAD,1) < 0) {
609 AR.CompareRoutine = (COMPAREDUMMY)(&
Compare1);
613 AR.CompareRoutine = (COMPAREDUMMY)(&
Compare1);
638 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
639 WORD *ret = flint_ratfun_add(BHEAD t1, t2);
644 if ( AR.PolyFunExp == 1 )
return PolyRatFunSpecial(BHEAD t1, t2);
647 cout <<
"*** [" << thetime() <<
"] CALL : poly_ratfun_add" << endl;
650 WORD *oldworkpointer = AT.WorkPointer;
656 for (WORD *t=t1+FUNHEAD; t<t1+t1[1];) {
660 for (WORD *t=t2+FUNHEAD; t<t2+t2[1];) {
665 assert(e.size() == 4);
667 poly::get_variables(BHEAD e,
true,
true);
673 poly num1(BHEAD 0,modp,1), den1(BHEAD 0,modp,1), num2(BHEAD 0,modp,1), den2(BHEAD 0,modp,1);
678 poly num(BHEAD 0),den(BHEAD 0),gcd(BHEAD 0);
682 gcd = polygcd::gcd(den1,den2);
684 num = num1*(den2/gcd) + num2*(den1/gcd);
685 den = (den1/gcd)*den2;
686 gcd = polygcd::gcd(num,den);
689 num = num1*(den2/gcd) + num2*den;
691 gcd = polygcd::gcd(num,gcd);
697 gcd = polygcd::gcd(num,den);
704 if (den.sign() == -1) { num*=
poly(BHEAD -1); den*=
poly(BHEAD -1); }
709 if ((num.size_of_form_notation() + den.size_of_form_notation() + FUNHEAD + 2*ARGHEAD + 3 + 1)
710 > AM.MaxTer/(
int)
sizeof(WORD)) {
712 MLOCK(ErrorMessageLock);
713 MesPrint (
"ERROR: PolyRatFun doesn't fit in a term");
714 MesPrint (
"(1) num size = %d, den size = %d, rest = %d, MaxTermSize = %d words",
715 num.size_of_form_notation()+ARGHEAD,
716 den.size_of_form_notation()+ARGHEAD,
718 AM.MaxTer/
sizeof(WORD));
719 MUNLOCK(ErrorMessageLock);
724 WORD *t = oldworkpointer;
731 poly::poly_to_argument(num,t,
true);
732 if (*t>0 && t[1]==DIRTYFLAG)
734 t += (*t>0 ? *t : 2);
735 poly::poly_to_argument(den,t,
true);
736 if (*t>0 && t[1]==DIRTYFLAG)
738 t += (*t>0 ? *t : 2);
740 oldworkpointer[1] = t - oldworkpointer;
743 poly_free_poly_vars(BHEAD
"AN.poly_vars_ratfun_add");
748 return oldworkpointer;
774 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
775 flint_ratfun_normalize(BHEAD term);
781 cout <<
"*** [" << thetime() <<
"] CALL : poly_ratfun_normalize" << endl;
785 WORD *tstop = term + *term;
786 int ncoeff = tstop[-1];
787 tstop -= ABS(ncoeff);
790 int num_polyratfun = 0;
792 for (WORD *t=term+1; t<tstop; t+=t[1])
793 if (*t == AR.PolyFun) {
795 if ((t[2] & MUSTCLEANPRF) != 0)
796 num_polyratfun = INT_MAX;
797 if (num_polyratfun > 1)
break;
800 if (num_polyratfun <= 1)
return 0;
802 WORD oldsorttype = AR.SortType;
803 AR.SortType = SORTHIGHFIRST;
809 for (WORD *t=term+1; t<tstop; t+=t[1]) {
810 if (*t == AR.PolyFun && (t[1] == FUNHEAD+t[FUNHEAD]
811 || t[1] == FUNHEAD+2 ) ) { *t = TMPPOLYFUN; }
818 for (WORD *t=term+1; t<tstop; t+=t[1]) {
819 if (*t == AR.PolyFun)
820 for (WORD *t2 = t+FUNHEAD; t2<t+t[1];) {
825 poly::get_variables(BHEAD e,
true,
true);
832 poly num1(BHEAD (UWORD *)tstop, ncoeff/2, modp, 1);
833 poly den1(BHEAD (UWORD *)tstop+ABS(ncoeff/2), ABS(ncoeff)/2, modp, 1);
837 for (WORD *t=term+1; t<tstop;)
838 if (*t == AR.PolyFun) {
840 poly num2(BHEAD 0,modp,1);
841 poly den2(BHEAD 0,modp,1);
844 if ((t[2] & MUSTCLEANPRF) != 0) {
845 poly gcd1(polygcd::gcd(num2,den2));
850 poly gcd1(polygcd::gcd(num1,den2));
851 poly gcd2(polygcd::gcd(num2,den1));
853 num1 = (num1 / gcd1) * (num2 / gcd2);
854 den1 = (den1 / gcd2) * (den2 / gcd1);
858 if ( s != t ) { NCOPY(s,t,i) }
859 else { t += i; s += i; }
863 if (den1.sign() == -1) { num1*=
poly(BHEAD -1); den1*=
poly(BHEAD -1); }
867 if ((num1.size_of_form_notation() + den1.size_of_form_notation() + FUNHEAD + 2*ARGHEAD
868 + s-term + 3) > AM.MaxTer/(
int)
sizeof(WORD)) {
870 MLOCK(ErrorMessageLock);
871 MesPrint (
"ERROR: PolyRatFun doesn't fit in a term");
872 MesPrint (
"(2) num size = %d, den size = %d, rest = %d, MaxTermSize = %d words",
873 num1.size_of_form_notation()+ARGHEAD,
874 den1.size_of_form_notation()+ARGHEAD,
875 FUNHEAD + s-term + 3,
876 AM.MaxTer/
sizeof(WORD));
877 MUNLOCK(ErrorMessageLock);
885 *t++ &= ~MUSTCLEANPRF;
887 poly::poly_to_argument(num1,t,
true);
888 if (*t>0 && t[1]==DIRTYFLAG)
890 t += (*t>0 ? *t : 2);
891 poly::poly_to_argument(den1,t,
true);
892 if (*t>0 && t[1]==DIRTYFLAG)
894 t += (*t>0 ? *t : 2);
904 poly_free_poly_vars(BHEAD
"AN.poly_vars_ratfun_normalize");
909 tstop = term + *term; tstop -= ABS(tstop[-1]);
910 for (WORD *t=term+1; t<tstop; t+=t[1]) {
911 if (*t == TMPPOLYFUN ) *t = AR.PolyFun;
914 AR.SortType = oldsorttype;
925 if ( a.factor.empty() )
return;
927 POLY_GETIDENTITY(a.factor[0]);
929 int overall_sign = +1;
932 for (
int i=0; i<(int)a.factor.size(); i++) {
938 WORD *tstop = a.factor[i].terms; tstop += *tstop;
939 for (WORD *t=a.factor[i].terms+1; t<tstop; t+=*t)
940 for (
int j=0; j<AN.poly_num_vars; j++) {
941 int var = AN.poly_vars[j];
943 if (pow>0 && (var>maxvar || (var==maxvar && pow>maxpow))) {
946 sign = SGN(*(t+*t-1));
952 a.factor[i] *=
poly(BHEAD sign);
953 if (a.power[i] % 2 == 1) overall_sign*=-1;
958 if (overall_sign == -1) {
960 for (
int i=0; i<(int)a.factor.size(); i++)
961 if (a.factor[i].is_integer()) {
962 a.factor[i] *=
poly(BHEAD -1);
967 a.add_factor(
poly(BHEAD -1), 1);
988WORD *
poly_factorize (PHEAD WORD *argin, WORD *argout,
bool with_arghead,
bool is_fun_arg) {
991 cout <<
"*** [" << thetime() <<
"] CALL : poly_factorize" << endl;
994 poly::get_variables(BHEAD vector<WORD*>(1,argin), with_arghead,
true);
996 poly a(poly::argument_to_poly(BHEAD argin, with_arghead,
true, &den));
1004 poly_fix_minus_signs(f);
1007 for (
int i=0; i<(int)f.factor.size(); i++)
1008 if (f.factor[i].is_integer())
1012 int len = with_arghead ? ARGHEAD : 0;
1014 if (!num.is_one() || !den.is_one()) {
1016 len += MaX(ABS(num[num[1]]), den[den[1]])*2+1;
1017 len += with_arghead ? ARGHEAD : 1;
1020 for (
int i=0; i<(int)f.factor.size(); i++) {
1021 if (!f.factor[i].is_integer()) {
1022 len += f.power[i] * f.factor[i].size_of_form_notation();
1023 len += f.power[i] * (with_arghead ? ARGHEAD : 1);
1029 if (argout != NULL) {
1031 if (len >= AM.MaxTer) {
1032 MLOCK(ErrorMessageLock);
1033 MesPrint (
"ERROR: factorization doesn't fit in a term (len = %d, MaxTermSize = %d words)",
1034 len/
sizeof(WORD), AM.MaxTer/
sizeof(WORD));
1035 MUNLOCK(ErrorMessageLock);
1041 argout = (WORD*) Malloc1(len*
sizeof(WORD),
"poly_factorize");
1044 WORD *old_argout = argout;
1047 if (!num.is_one() || !den.is_one()) {
1048 int n = max(ABS(num[num[1]]), ABS(den[den[1]]));
1051 *argout++ = ARGHEAD + 2 + 2*n;
1052 for (
int i=1; i<ARGHEAD; i++)
1056 *argout++ = 2 + 2*n;
1058 for (
int i=0; i<n; i++)
1059 *argout++ = i<ABS(num[num[1]]) ? num[2+AN.poly_num_vars+i] : 0;
1060 for (
int i=0; i<n; i++)
1061 *argout++ = i<ABS(den[den[1]]) ? den[2+AN.poly_num_vars+i] : 0;
1063 *argout++ = SGN(num[num[1]]) * (2*n+1);
1068 if (ToFast(old_argout, old_argout))
1069 argout = old_argout+2;
1074 for (
int i=0; i<(int)f.factor.size(); i++)
1075 if (!f.factor[i].is_integer())
1076 for (
int j=0; j<f.power[i]; j++) {
1077 poly::poly_to_argument(f.factor[i],argout,with_arghead);
1080 argout += *argout > 0 ? *argout : 2;
1082 while (*argout!=0) argout+=*argout;
1089 poly_free_poly_vars(BHEAD
"AN.poly_vars_factorize");
1092 AN.ncmod = AC.ncmod;
1117 cout <<
"*** [" << thetime() <<
"] CALL : poly_factorize_argument" << endl;
1121 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
1122 flint_factorize_argument(BHEAD argin, argout);
1151 cout <<
"*** [" << thetime() <<
"] CALL : poly_factorize_dollar" << endl;
1155 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
1156 return flint_factorize_dollar(BHEAD argin);
1183 cout <<
"*** [" << thetime() <<
"] CALL : poly_factorize_expression" << endl;
1188 if (AT.WorkPointer + AM.MaxTer > AT.WorkTop ) {
1189 MLOCK(ErrorMessageLock);
1191 MUNLOCK(ErrorMessageLock);
1195 WORD *term = AT.WorkPointer;
1196 WORD startebuf = cbuf[AT.ebufnum].numrhs;
1202 WORD oldBracketOn = AR.BracketOn;
1203 WORD *oldBrackBuf = AT.BrackBuf;
1204 WORD oldbracketindexflag = AT.bracketindexflag;
1205 char oldCommercial[COMMERCIALSIZE+2];
1207 strcpy(oldCommercial, (
char*)AC.Commercial);
1208 strcpy((
char*)AC.Commercial,
"factorize");
1211 if (expr->status == HIDDENGEXPRESSION || expr->status == HIDDENLEXPRESSION ||
1212 expr->status == INTOHIDEGEXPRESSION || expr->status == INTOHIDELEXPRESSION) {
1213 AR.InHiBuf = 0; file = AR.hidefile; AR.GetFile = 2;
1216 AR.InInBuf = 0; file = AR.outfile; AR.GetFile = 0;
1220 AR.infile = AR.outfile = file;
1223 if (expr->numdummies > 0) {
1224 MesPrint(
"ERROR: factorization with dummy indices not implemented");
1231 SeekFile(file->
handle,&pos,SEEK_SET);
1232 if (ISNOTEQUALPOS(pos,expr->onfile)) {
1234 MesPrint(
"!>ERROR: something wrong in scratch file [poly_factorize_expression]");
1238 file->POposition = expr->onfile;
1239 file->POfull = file->PObuffer;
1240 if (expr->status == HIDDENGEXPRESSION)
1246 file->POfill = (WORD *)((UBYTE *)(file->PObuffer)+BASEPOSITION(expr->onfile));
1249 SetScratch(AR.infile, &(expr->onfile));
1252 WORD size = GetTerm(BHEAD term);
1255 MesPrint (
"!>ERROR: something wrong with expression [poly_factorize_expression]");
1262 ADDPOS(pos, size*
sizeof(WORD));
1265 poly buffer(BHEAD 0);
1270 while (GetTerm(BHEAD term)) {
1272 sumcommu += DoesCommu(term);
1273 if ( sumcommu > 1 ) {
1274 MesPrint(
"ERROR: Cannot factorize an expression with more than one noncommuting object");
1277 buffer.check_memory(bufpos);
1280 MesPrint(
"!>ERROR: in LocalConvertToPoly [factorize_expression]");
1284 bufpos += *(buffer.terms + bufpos);
1290 AN.poly_num_vars = 0;
1291 poly::get_variables(BHEAD vector<WORD*>(1,buffer.terms),
false,
true);
1293 poly a(poly::argument_to_poly(BHEAD buffer.terms,
false,
true, &den));
1300 SetScratch(file, &pos);
1303 CBUF *C = cbuf+AC.cbufnum;
1304 CBUF *CC = cbuf+AT.ebufnum;
1307 WORD nexpr = expr - Expressions;
1309 AT.BrackBuf = AM.BracketFactors;
1310 AT.bracketindexflag = 1;
1311 ClearBracketIndex(-nexpr-2);
1312 OpenBracketIndex(nexpr);
1315 expr->numfactors = 1;
1317 else if (a.is_one() && den.is_one()) {
1318 expr->numfactors = 1;
1323 term[3] = FACTORSYMBOL;
1329 AT.WorkPointer += *term;
1331 AT.WorkPointer = term;
1335 bool iszero =
false;
1337 if (!(expr->vflags & ISFACTORIZED)) {
1339 fac = polyfact::factorize(a);
1340 poly_fix_minus_signs(fac);
1343 int factorsymbol=-1;
1344 for (
int i=0; i<AN.poly_num_vars; i++)
1345 if (AN.poly_vars[i] == FACTORSYMBOL)
1348 poly denpow(BHEAD 1);
1351 for (
int i=1; i<=expr->numfactors; i++) {
1352 poly origfac(a.coefficient(factorsymbol, i));
1354 if (origfac.is_zero())
1357 fac2 = polyfact::factorize(origfac);
1358 poly_fix_minus_signs(fac2);
1361 for (
int j=0; j<(int)fac2.power.size(); j++)
1362 fac.add_factor(fac2.factor[j], fac2.power[j]);
1369 expr->numfactors = 0;
1373 for (
int i=0; i<(int)fac.factor.size(); i++)
1374 if (fac.factor[i].is_integer())
1375 num *= fac.factor[i];
1377 poly gcd(polygcd::integer_gcd(num,den));
1384 if (!iszero || (expr->vflags & KEEPZERO)) {
1385 if (!num.is_one() || !den.is_one()) {
1388 int n = max(ABS(num[num[1]]), ABS(den[den[1]]));
1393 term[3] = FACTORSYMBOL;
1394 term[4] = expr->numfactors;
1395 for (
int i=0; i<n; i++) {
1396 term[5+i] = i<ABS(num[num[1]]) ? num[2+AN.poly_num_vars+i] : 0;
1397 term[5+n+i] = i<ABS(den[den[1]]) ? den[2+AN.poly_num_vars+i] : 0;
1399 term[5+2*n] = SGN(num[num[1]]) * (2*n+1);
1400 AT.WorkPointer += *term;
1402 AT.WorkPointer = term;
1405 vector<poly> fac_arg(fac.factor.size(),
poly(BHEAD 0));
1408 for (
int i=0; i<(int)fac.factor.size(); i++)
1409 if (!fac.factor[i].is_integer()) {
1410 buffer.check_memory(fac.factor[i].size_of_form_notation()+1);
1411 poly::poly_to_argument(fac.factor[i], buffer.terms,
false);
1414 for (WORD *t=buffer.terms; *t!=0; t+=*t) {
1416 if (ConvertFromPoly(BHEAD t, term, numxsymbol, CC->numrhs-startebuf+numxsymbol,
1417 startebuf-numxsymbol, 1) <= 0 ) {
1419 MesPrint(
"!>ERROR: in ConvertFromPoly [factorize_expression]");
1426 AT.WorkPointer += *term;
1428 AT.WorkPointer = term;
1433 if (
EndSort(BHEAD (WORD *)((
void *)(&buffer)),2) < 0)
return -1;
1436 for (WORD *t=buffer; *t!=0; t+=*t)
1439 fac_arg[i].check_memory(bufsize+ARGHEAD+1);
1441 for (
int j=0; j<ARGHEAD; j++)
1442 fac_arg[i].terms[j] = 0;
1443 fac_arg[i].terms[0] = ARGHEAD + bufsize;
1444 WCOPY(fac_arg[i].terms+ARGHEAD, buffer, bufsize);
1445 M_free(buffer,
"polynomial factorization");
1450 vector<vector<int> > comp(fac.factor.size(), vector<int>(fac.factor.size(), 0));
1452 for (
int i=0; i<(int)fac.factor.size(); i++)
1453 if (!fac.factor[i].is_integer()) {
1456 for (
int j=i+1; j<(int)fac.factor.size(); j++)
1457 if (!fac.factor[j].is_integer()) {
1458 comp[i][j] = CompArg(fac_arg[j].terms, fac_arg[i].terms);
1459 comp[j][i] = -comp[i][j];
1463 for (
int i=0; i<(int)order.size(); i++)
1464 for (
int j=0; j+1<(int)order.size(); j++)
1465 if (comp[order[i]][order[j]] == 1)
1466 swap(order[i],order[j]);
1469 for (
int i=0; i<(int)order.size(); i++)
1470 for (
int j=0; j<fac.power[order[i]]; j++) {
1474 WORD *tstop = fac_arg[order[i]].terms + *fac_arg[order[i]].terms;
1475 for (WORD *t=fac_arg[order[i]].terms+ARGHEAD; t<tstop; t+=*t) {
1477 WCOPY(term+4, t, *t);
1480 *term = *(term+4) + 4;
1483 *(term+3) = FACTORSYMBOL;
1484 *(term+4) = expr->numfactors;
1487 AT.WorkPointer += *term;
1489 AT.WorkPointer = term;
1496 if (
EndSort(BHEAD NULL,0) < 0) {
1502 if (expr->numfactors > 0)
1503 expr->vflags |= ISFACTORIZED;
1506 AR.infile = oldinfile;
1507 AR.outfile = oldoutfile;
1508 AR.BracketOn = oldBracketOn;
1509 AT.BrackBuf = oldBrackBuf;
1510 AT.bracketindexflag = oldbracketindexflag;
1511 strcpy((
char*)AC.Commercial, oldCommercial);
1513 poly_free_poly_vars(BHEAD
"AN.poly_vars_factorize_expression");
1535#if ( SUBEXPSIZE == 5 )
1536static WORD genericterm[] = {38,1,4,FACTORSYMBOL,0
1537 ,EXPRESSION,15,0,1,0,13,10,8,1,4,FACTORSYMBOL,0,1,1,3
1538 ,EXPRESSION,15,0,1,0,13,10,8,1,4,FACTORSYMBOL,0,1,1,3
1540static WORD genericterm2[] = {23,1,4,FACTORSYMBOL,0
1541 ,EXPRESSION,15,0,1,0,13,10,8,1,4,FACTORSYMBOL,0,1,1,3
1548 int i, j, nfac = expr->numfactors, nfacp, nexpr = expr - Expressions;
1553 char oldCommercial[COMMERCIALSIZE+2];
1555 WORD *oldworkpointer = AT.WorkPointer;
1556 WORD *term = AT.WorkPointer, *t, *w, size;
1561 WORD oldBracketOn = AR.BracketOn;
1562 WORD *oldBrackBuf = AT.BrackBuf;
1563 CBUF *C = cbuf+AC.cbufnum;
1565 if ( ( expr->vflags & ISFACTORIZED ) == 0 )
return(0);
1567 if ( AT.WorkPointer + AM.MaxTer > AT.WorkTop ) {
1568 MLOCK(ErrorMessageLock);
1570 MUNLOCK(ErrorMessageLock);
1574 oldpos = AS.OldOnFile[nexpr];
1575 AS.OldOnFile[nexpr] = expr->onfile;
1577 strcpy(oldCommercial, (
char*)AC.Commercial);
1578 strcpy((
char*)AC.Commercial,
"unfactorize");
1582 if ( expr->status == HIDDENGEXPRESSION || expr->status == HIDDENLEXPRESSION ||
1583 expr->status == INTOHIDEGEXPRESSION || expr->status == INTOHIDELEXPRESSION ) {
1584 AR.InHiBuf = 0; file = AR.hidefile; AR.GetFile = 2;
1587 AR.InInBuf = 0; file = AR.outfile; AR.GetFile = 0;
1592 AR.infile = AR.outfile = file;
1596 if ( file->
handle >= 0 ) {
1598 SeekFile(file->
handle,&pos,SEEK_SET);
1599 if (ISNOTEQUALPOS(pos,expr->onfile)) {
1601 MesPrint(
"!>ERROR: something wrong in scratch file unfactorize_expression");
1605 file->POposition = expr->onfile;
1606 file->POfull = file->PObuffer;
1607 if ( expr->status == HIDDENGEXPRESSION )
1613 file->POfill = (WORD *)((UBYTE *)(file->PObuffer)+BASEPOSITION(expr->onfile));
1615 SetScratch(AR.infile, &(expr->onfile));
1619 if ( GetFirstBracket(term,nexpr) < 0 ) Terminate(-1);
1620 if ( term[4] != 1 || *term != 8 || term[1] != SYMBOL || term[3] != FACTORSYMBOL || term[4] != 1 ) {
1623 SetScratch(AR.infile, &(expr->onfile));
1627 size = GetTerm(BHEAD term);
1630 MesPrint (
"!>ERROR: something wrong with expression unfactorize_expression");
1635 ADDPOS(pos, size*
sizeof(WORD));
1640 AT.BrackBuf = AM.BracketFactors;
1642 while ( nfac > 2 ) {
1643 nfacp = nfac - nfac%2;
1652 if ( AT.bracketinfo != 0 ) ClearBracketIndex(-1);
1653 AT.bracketinfo = expr->newbracketinfo;
1654 OpenBracketIndex(nexpr);
1661 if ( expriszero == 0 ) {
1662 for ( i = 0; i < nfacp; i += 2 ) {
1663 t = genericterm; w = term = oldworkpointer;
1664 j = *t; NCOPY(w,t,j);
1670 AT.WorkPointer = term + *term;
1673 if ( nfac > nfacp ) {
1674 t = genericterm2; w = term = oldworkpointer;
1675 j = *t; NCOPY(w,t,j);
1679 AT.WorkPointer = term + *term;
1683 if (
EndSort(BHEAD AM.S0->sBuffer,0) < 0 ) {
1690 SetScratch(file, &pos);
1692 if ( expriszero ) { nfac = 1; }
1694 if ( AT.bracketinfo != 0 ) ClearBracketIndex(-1);
1695 AT.bracketinfo = expr->newbracketinfo;
1696 expr->newbracketinfo = 0;
1700 AR.BracketOn = oldBracketOn;
1701 AT.BrackBuf = oldBrackBuf;
1702 if ( AR.BracketOn ) OpenBracketIndex(nexpr);
1708 if ( expriszero == 0 ) {
1710 t = genericterm2; w = term = oldworkpointer;
1711 j = *t; NCOPY(w,t,j);
1715 else if ( nfac == 2 ) {
1716 t = genericterm; w = term = oldworkpointer;
1717 j = *t; NCOPY(w,t,j);
1724 AS.OldOnFile[nexpr] = oldpos;
1727 term[4] = term[0]-4;
1729 AT.WorkPointer = term + *term;
1732 if (
EndSort(BHEAD AM.S0->sBuffer,0) < 0 ) {
1739 expr->numfactors = 0;
1740 expr->vflags &= ~ISFACTORIZED;
1741 if ( AT.bracketinfo != 0 ) ClearBracketIndex(-1);
1743 AR.infile = oldinfile;
1744 AR.outfile = oldoutfile;
1745 strcpy((
char*)AC.Commercial, oldCommercial);
1746 AT.WorkPointer = oldworkpointer;
1747 AS.OldOnFile[nexpr] = oldpos;
1757WORD *poly_inverse(PHEAD WORD *arga, WORD *argb) {
1760 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
1761 return flint_inverse(BHEAD arga, argb);
1766 cout <<
"*** [" << thetime() <<
"] CALL : poly_inverse" << endl;
1774 poly::get_variables(BHEAD e,
false,
true);
1776 if (AN.poly_num_vars > 1) {
1777 MLOCK(ErrorMessageLock);
1778 MesPrint ((
char*)
"ERROR: multivariate polynomial inverse is generally impossible");
1779 MUNLOCK(ErrorMessageLock);
1783 poly finalden(BHEAD 1), finalres(BHEAD 1);
1789 poly a(poly::argument_to_poly(BHEAD arga,
false,
true, &dena));
1790 poly b(poly::argument_to_poly(BHEAD argb,
false,
true));
1793 poly content_a(BHEAD 0), content_b(BHEAD 0);
1794 content_a = polygcd::integer_content(a);
1795 content_b = polygcd::integer_content(b);
1799 poly invamodp(BHEAD 0), invbmodp(BHEAD 0);
1804 if ((a.is_one() && b.is_one()) || a.is_one()) {
1805 finalres =
poly(BHEAD 1);
1807 else if (b.is_one()) {
1808 finalres =
poly(BHEAD 0);
1813 const bool mod_calc = modp==0 ? false :
true;
1818 poly gcd(polygcd::gcd(a,b));
1819 if (!gcd.is_one()) {
1820 MLOCK(ErrorMessageLock);
1822 MesPrint ((
char*)
"ERROR: polynomial inverse does not exist (mod %d)", modp);
1825 MesPrint ((
char*)
"ERROR: polynomial inverse does not exist");
1827 MUNLOCK(ErrorMessageLock);
1831 bool inv_exists =
true;
1836 modp = polyfact::choose_prime(a.integer_lcoeff()*b.integer_lcoeff(), x, modp);
1839 poly amodp(a,modp,1);
1840 poly bmodp(b,modp,1);
1843 vector<poly> xgcd(polyfact::extended_gcd_Euclidean_lifted(amodp,bmodp));
1844 invamodp =
poly(xgcd[0]);
1845 invbmodp =
poly(xgcd[1]);
1847 inv_exists = ((invamodp * amodp) % bmodp).is_one();
1848 if (!inv_exists && mod_calc) {
1850 MLOCK(ErrorMessageLock);
1851 MesPrint ((
char*)
"ERROR: polynomial inverse does not exist (mod %d) B", modp);
1852 MUNLOCK(ErrorMessageLock);
1859 }
while (!inv_exists);
1862 ressize = invamodp.size_of_form_notation()+1;
1863 res = (WORD *)Malloc1(ressize*
sizeof(WORD),
"poly_inverse");
1866 poly primepower(BHEAD modp);
1867 poly inva(invamodp,modp,1);
1868 poly invb(invbmodp,modp,1);
1874 for (
int i=1; i<inva[0]; i+=inva[i]) {
1877 while (ressize < j + 2*ABS(inva[i+inva[i]-1]) + (inva[i+1]>0?4:0) + 3) {
1878 int newressize = 2*ressize;
1880 WORD *newres = (WORD *)Malloc1(newressize*
sizeof(WORD),
"poly_inverse");
1881 WCOPY(newres, res, ressize);
1882 M_free(res,
"poly_inverse");
1884 ressize = newressize;
1889 res[j+res[j]++] = SYMBOL;
1890 res[j+res[j]++] = 4;
1891 res[j+res[j]++] = AN.poly_vars[0];
1892 res[j+res[j]++] = inva[i+1];
1894 MakeLongRational(BHEAD (UWORD *)&inva[i+2], inva[i+inva[i]-1],
1895 (UWORD*)&primepower.terms[3], primepower.terms[primepower.terms[1]],
1896 (UWORD *)&res[j+res[j]], &n);
1898 res[j+res[j]++] = SGN(n)*(2*ABS(n)+1);
1904 if (a.modp != 0)
break;
1908 poly check(poly::argument_to_poly(BHEAD res,
false,
true, &den));
1911 if (poly::divides(b.integer_lcoeff(), check.integer_lcoeff()*a.integer_lcoeff())) {
1912 check = check*a - den;
1913 if (poly::divides(b, check))
break;
1917 poly error((
poly(BHEAD 1) - a*inva - b*invb) / primepower);
1918 poly errormodpp(error, modp, inva.modn);
1923 poly dinva((inva * errormodpp) % b);
1924 poly dinvb((invb * errormodpp) % a);
1926 inva += dinva * primepower;
1927 invb += dinvb * primepower;
1929 primepower *= primepower;
1933 finalres =
poly(poly::argument_to_poly(BHEAD res,
false,
true, &finalden));
1938 finalden *= content_a;
1939 const WORD finalden_size = finalden.terms[finalden.terms[1]];
1940 const int finalsize = finalres.size_of_form_notation_with_den(finalden_size)+1;
1941 if (ressize < finalsize) {
1943 M_free(res,
"poly_inverse");
1945 res = (WORD *)Malloc1(finalsize*
sizeof(WORD),
"poly_inverse");
1947 poly::poly_to_argument_with_den(finalres, finalden_size,
1948 (UWORD*)&(finalden.terms[finalden.terms[1] - ABS(finalden_size)]), res,
false);
1951 poly_free_poly_vars(BHEAD
"AN.poly_vars_inverse");
1953 AN.ncmod = AC.ncmod;
1962WORD *poly_mul(PHEAD WORD *a, WORD *b) {
1965 cout <<
"*** [" << thetime() <<
"] CALL : poly_mul" << endl;
1969 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
1970 return flint_mul(BHEAD a, b);
1979 poly::get_variables(BHEAD e,
false,
false);
1984 poly pa(poly::argument_to_poly(BHEAD a,
false,
true, &dena));
1985 poly pb(poly::argument_to_poly(BHEAD b,
false,
true, &denb));
1997 assert(dena.is_integer());
1998 assert(denb.is_integer());
1999 assert(modp == 0 || dena.is_one());
2000 assert(modp == 0 || denb.is_one());
2007 if (dena.is_one() && denb.is_one()) {
2008 res = (WORD *)Malloc1((pa.size_of_form_notation() + 1) *
sizeof(WORD),
"poly_mul");
2009 poly::poly_to_argument(pa, res,
false);
2012 res = (WORD *)Malloc1((pa.size_of_form_notation_with_den(dena[dena[1]]) + 1) *
sizeof(WORD),
"poly_mul");
2013 poly::poly_to_argument_with_den(pa, dena[dena[1]], (
const UWORD *)&dena[2+AN.poly_num_vars], res,
false);
2017 poly_free_poly_vars(BHEAD
"AN.poly_vars_mul");
2018 AN.ncmod = AC.ncmod;
2028void poly_free_poly_vars(PHEAD
const char *text)
2030 if ( AN.poly_vars_type == 0 ) {
2031 TermFree(AN.poly_vars, text);
2034 M_free(AN.poly_vars, text);
2036 AN.poly_num_vars = 0;
static void divmod_heap(const poly &, const poly &, poly &, poly &, bool, bool, bool &)
int LocalConvertToPoly(PHEAD WORD *, WORD *, WORD, WORD)
LONG EndSort(PHEAD WORD *, int)
int Generator(PHEAD WORD *, WORD)
void LowerSortLevel(void)
int StoreTerm(PHEAD WORD *)
WORD Compare1(PHEAD WORD *, WORD *, WORD)
WORD CompareSymbols(PHEAD WORD *, WORD *, WORD)
int SymbolNormalize(WORD *)
int poly_factorize_expression(EXPRESSIONS expr)
WORD poly_determine_modulus(PHEAD bool multi_error, bool is_fun_arg, string message)
WORD * poly_ratfun_add(PHEAD WORD *t1, WORD *t2)
void poly_ratfun_read(WORD *a, poly &num, poly &den)
void poly_sort(PHEAD WORD *a)
WORD * poly_gcd(PHEAD WORD *a, WORD *b, WORD fit)
int poly_ratfun_normalize(PHEAD WORD *term)
WORD * poly_factorize(PHEAD WORD *argin, WORD *argout, bool with_arghead, bool is_fun_arg)
int poly_unfactorize_expression(EXPRESSIONS expr)
int poly_factorize_argument(PHEAD WORD *argin, WORD *argout)
WORD * poly_factorize_dollar(PHEAD WORD *argin)