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)
278 MLOCK(ErrorMessageLock);
279 MesPrint ((
char*)
"ERROR: pseudo-division failed in poly_divmod (denompower > INT_MAX)");
280 MUNLOCK(ErrorMessageLock);
287 WORD n = lcoeffb[lcoeffb[1]];
288 RaisPow(BHEAD (UWORD *)&lcoeffb[2+AN.poly_num_vars], &n, denompower-prevdenompower);
289 lcoeffb[1] = 2 + AN.poly_num_vars + ABS(n);
290 lcoeffb[0] = 1 + lcoeffb[1];
291 lcoeffb[lcoeffb[1]] = n;
302 prevdenompower = denompower;
303 denompower = (denompower==0 ? 1 : denompower*POLYWRAP_DENOMPOWER_INCREASE_FACTOR+1 );
307 pres = (divmod==0 ? pq : pr);
313 int denompower = MaX(0, pa.degree(0) - pb.degree(0) + 1);
316 WORD n = lcoeffb[lcoeffb[1]];
317 RaisPow(BHEAD (UWORD *)&lcoeffb[2+AN.poly_num_vars], &n, denompower);
318 lcoeffb[1] = 2 + AN.poly_num_vars + ABS(n);
319 lcoeffb[0] = 1 + lcoeffb[1];
320 lcoeffb[lcoeffb[1]] = n;
325 pres = (divmod==0 ? pa/pb : pa%pb);
332 pres = (divmod==0 ? pa/pb : pa%pb);
344 res = TermMalloc(
"poly_divmod");
347 res = (WORD *)Malloc1(
sizeof(WORD),
"poly_divmod");
355 UWORD *den = (UWORD *)NumberMalloc(
"poly_divmod");
359 int ressize = pres.size_of_form_notation() + pres.number_of_terms()*2*ABS(denres[denres[1]]) + 1;
362 if ( ressize*
sizeof(WORD) > (
size_t)(AM.MaxTer) ) {
363 MLOCK(ErrorMessageLock);
364 MesPrint(
"poly_divmod: Term too complex (%d words). Maybe increasing MaxTermSize (%d words) can help",
365 ressize, AM.MaxTer/
sizeof(WORD));
366 MUNLOCK(ErrorMessageLock);
369 res = TermMalloc(
"poly_divmod");
372 res = (WORD *)Malloc1(ressize*
sizeof(WORD),
"poly_divmod");
376 for (
int i=1; i!=pres[0]; i+=pres[i]) {
381 for (
int j=0; j<AN.poly_num_vars; j++)
382 if (pres[i+1+j] > 0) {
388 res[L+1+res[L+2]++] = AN.poly_vars[j];
389 res[L+1+res[L+2]++] = pres[i+1+j];
392 if (!first) res[L] += res[L+2];
395 WORD nnum = pres[i+pres[i]-1];
396 WCOPY(&res[L+res[L]], &pres[i+pres[i]-1-ABS(nnum)], ABS(nnum));
399 nden = denres[denres[1]];
400 WCOPY(den, &denres[2+AN.poly_num_vars], ABS(nden));
402 if (nden!=1 || den[0]!=1)
403 Simplify(BHEAD (UWORD *)&res[L+res[L]], &nnum, den, &nden);
404 Pack((UWORD *)&res[L+res[L]], &nnum, den, nden);
405 res[L] += 2*ABS(nnum)+1;
406 res[L+res[L]-1] = SGN(nnum)*(2*ABS(nnum)+1);
412 NumberFree(den,
"poly_divmod");
416 poly_free_poly_vars(BHEAD
"AN.poly_vars_divmod");
435WORD *poly_div(PHEAD WORD *a, WORD *b, WORD fit) {
438 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
439 WORD *ret = flint_div(BHEAD a, b, fit);
445 cout <<
"*** [" << thetime() <<
"] CALL : poly_div" << endl;
448 return poly_divmod(BHEAD a, b, 0, fit);
463WORD *poly_rem(PHEAD WORD *a, WORD *b, WORD fit) {
466 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
467 WORD *ret = flint_rem(BHEAD a, b, fit);
473 cout <<
"*** [" << thetime() <<
"] CALL : poly_rem" << endl;
476 return poly_divmod(BHEAD a, b, 1, fit);
499 cout <<
"*** [" << thetime() <<
"] CALL : poly_ratfun_read" << endl;
502 POLY_GETIDENTITY(num);
506 WORD *astop = a+a[1];
508 bool clean = (a[2] & MUSTCLEANPRF) == 0;
512 MLOCK(ErrorMessageLock);
513 MesPrint ((
char*)
"ERROR: PolyRatFun cannot have zero arguments");
514 MUNLOCK(ErrorMessageLock);
518 poly den_num(BHEAD 1),den_den(BHEAD 1);
520 num = poly::argument_to_poly(BHEAD a,
true, !clean, &den_num);
525 den = poly::argument_to_poly(BHEAD a,
true, !clean, &den_den);
530 den =
poly(BHEAD 1, modp, 1);
534 MLOCK(ErrorMessageLock);
535 MesPrint ((
char*)
"ERROR: PolyRatFun cannot have more than two arguments");
536 MUNLOCK(ErrorMessageLock);
543 vector<WORD> minpower(AN.poly_num_vars, MAXPOSITIVE);
545 for (
int i=1; i<num[0]; i+=num[i]) {
546 for (
int j=0; j<AN.poly_num_vars; j++) {
547 minpower[j] = MiN(minpower[j], num[i+1+j]);
550 for (
int i=1; i<den[0]; i+=den[i]) {
551 for (
int j=0; j<AN.poly_num_vars; j++) {
552 minpower[j] = MiN(minpower[j], den[i+1+j]);
553 if ( minpower[j] < 0 ) clean =
false;
558 for (
int i=1; i<num[0]; i+=num[i])
559 for (
int j=0; j<AN.poly_num_vars; j++)
560 num[i+1+j] -= minpower[j];
561 for (
int i=1; i<den[0]; i+=den[i])
562 for (
int j=0; j<AN.poly_num_vars; j++)
563 den[i+1+j] -= minpower[j];
568 poly gcd = polygcd::gcd(num,den);
593 cout <<
"*** [" << thetime() <<
"] CALL : poly_sort" << endl;
595 if (
NewSort(BHEAD0)) { Terminate(-1); }
598 for (
int i=ARGHEAD; i<a[0]; i+=a[i]) {
600 AR.CompareRoutine = (COMPAREDUMMY)(&
Compare1);
606 if (
EndSort(BHEAD a+ARGHEAD,1) < 0) {
607 AR.CompareRoutine = (COMPAREDUMMY)(&
Compare1);
611 AR.CompareRoutine = (COMPAREDUMMY)(&
Compare1);
636 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
637 WORD *ret = flint_ratfun_add(BHEAD t1, t2);
642 if ( AR.PolyFunExp == 1 )
return PolyRatFunSpecial(BHEAD t1, t2);
645 cout <<
"*** [" << thetime() <<
"] CALL : poly_ratfun_add" << endl;
648 WORD *oldworkpointer = AT.WorkPointer;
654 for (WORD *t=t1+FUNHEAD; t<t1+t1[1];) {
658 for (WORD *t=t2+FUNHEAD; t<t2+t2[1];) {
663 assert(e.size() == 4);
665 poly::get_variables(BHEAD e,
true,
true);
671 poly num1(BHEAD 0,modp,1), den1(BHEAD 0,modp,1), num2(BHEAD 0,modp,1), den2(BHEAD 0,modp,1);
676 poly num(BHEAD 0),den(BHEAD 0),gcd(BHEAD 0);
680 gcd = polygcd::gcd(den1,den2);
682 num = num1*(den2/gcd) + num2*(den1/gcd);
683 den = (den1/gcd)*den2;
684 gcd = polygcd::gcd(num,den);
687 num = num1*(den2/gcd) + num2*den;
689 gcd = polygcd::gcd(num,gcd);
695 gcd = polygcd::gcd(num,den);
702 if (den.sign() == -1) { num*=
poly(BHEAD -1); den*=
poly(BHEAD -1); }
707 if ((num.size_of_form_notation() + den.size_of_form_notation() + FUNHEAD + 2*ARGHEAD + 3 + 1)
708 > AM.MaxTer/(
int)
sizeof(WORD)) {
710 MLOCK(ErrorMessageLock);
711 MesPrint (
"ERROR: PolyRatFun doesn't fit in a term");
712 MesPrint (
"(1) num size = %d, den size = %d, rest = %d, MaxTermSize = %d words",
713 num.size_of_form_notation()+ARGHEAD,
714 den.size_of_form_notation()+ARGHEAD,
716 AM.MaxTer/
sizeof(WORD));
717 MUNLOCK(ErrorMessageLock);
722 WORD *t = oldworkpointer;
729 poly::poly_to_argument(num,t,
true);
730 if (*t>0 && t[1]==DIRTYFLAG)
732 t += (*t>0 ? *t : 2);
733 poly::poly_to_argument(den,t,
true);
734 if (*t>0 && t[1]==DIRTYFLAG)
736 t += (*t>0 ? *t : 2);
738 oldworkpointer[1] = t - oldworkpointer;
741 poly_free_poly_vars(BHEAD
"AN.poly_vars_ratfun_add");
746 return oldworkpointer;
772 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
773 flint_ratfun_normalize(BHEAD term);
779 cout <<
"*** [" << thetime() <<
"] CALL : poly_ratfun_normalize" << endl;
783 WORD *tstop = term + *term;
784 int ncoeff = tstop[-1];
785 tstop -= ABS(ncoeff);
788 int num_polyratfun = 0;
790 for (WORD *t=term+1; t<tstop; t+=t[1])
791 if (*t == AR.PolyFun) {
793 if ((t[2] & MUSTCLEANPRF) != 0)
794 num_polyratfun = INT_MAX;
795 if (num_polyratfun > 1)
break;
798 if (num_polyratfun <= 1)
return 0;
800 WORD oldsorttype = AR.SortType;
801 AR.SortType = SORTHIGHFIRST;
807 for (WORD *t=term+1; t<tstop; t+=t[1]) {
808 if (*t == AR.PolyFun && (t[1] == FUNHEAD+t[FUNHEAD]
809 || t[1] == FUNHEAD+2 ) ) { *t = TMPPOLYFUN; }
816 for (WORD *t=term+1; t<tstop; t+=t[1]) {
817 if (*t == AR.PolyFun)
818 for (WORD *t2 = t+FUNHEAD; t2<t+t[1];) {
823 poly::get_variables(BHEAD e,
true,
true);
830 poly num1(BHEAD (UWORD *)tstop, ncoeff/2, modp, 1);
831 poly den1(BHEAD (UWORD *)tstop+ABS(ncoeff/2), ABS(ncoeff)/2, modp, 1);
835 for (WORD *t=term+1; t<tstop;)
836 if (*t == AR.PolyFun) {
838 poly num2(BHEAD 0,modp,1);
839 poly den2(BHEAD 0,modp,1);
842 if ((t[2] & MUSTCLEANPRF) != 0) {
843 poly gcd1(polygcd::gcd(num2,den2));
848 poly gcd1(polygcd::gcd(num1,den2));
849 poly gcd2(polygcd::gcd(num2,den1));
851 num1 = (num1 / gcd1) * (num2 / gcd2);
852 den1 = (den1 / gcd2) * (den2 / gcd1);
856 if ( s != t ) { NCOPY(s,t,i) }
857 else { t += i; s += i; }
861 if (den1.sign() == -1) { num1*=
poly(BHEAD -1); den1*=
poly(BHEAD -1); }
865 if ((num1.size_of_form_notation() + den1.size_of_form_notation() + FUNHEAD + 2*ARGHEAD
866 + s-term + 3) > AM.MaxTer/(
int)
sizeof(WORD)) {
868 MLOCK(ErrorMessageLock);
869 MesPrint (
"ERROR: PolyRatFun doesn't fit in a term");
870 MesPrint (
"(2) num size = %d, den size = %d, rest = %d, MaxTermSize = %d words",
871 num1.size_of_form_notation()+ARGHEAD,
872 den1.size_of_form_notation()+ARGHEAD,
873 FUNHEAD + s-term + 3,
874 AM.MaxTer/
sizeof(WORD));
875 MUNLOCK(ErrorMessageLock);
883 *t++ &= ~MUSTCLEANPRF;
885 poly::poly_to_argument(num1,t,
true);
886 if (*t>0 && t[1]==DIRTYFLAG)
888 t += (*t>0 ? *t : 2);
889 poly::poly_to_argument(den1,t,
true);
890 if (*t>0 && t[1]==DIRTYFLAG)
892 t += (*t>0 ? *t : 2);
902 poly_free_poly_vars(BHEAD
"AN.poly_vars_ratfun_normalize");
907 tstop = term + *term; tstop -= ABS(tstop[-1]);
908 for (WORD *t=term+1; t<tstop; t+=t[1]) {
909 if (*t == TMPPOLYFUN ) *t = AR.PolyFun;
912 AR.SortType = oldsorttype;
923 if ( a.factor.empty() )
return;
925 POLY_GETIDENTITY(a.factor[0]);
927 int overall_sign = +1;
930 for (
int i=0; i<(int)a.factor.size(); i++) {
936 WORD *tstop = a.factor[i].terms; tstop += *tstop;
937 for (WORD *t=a.factor[i].terms+1; t<tstop; t+=*t)
938 for (
int j=0; j<AN.poly_num_vars; j++) {
939 int var = AN.poly_vars[j];
941 if (pow>0 && (var>maxvar || (var==maxvar && pow>maxpow))) {
944 sign = SGN(*(t+*t-1));
950 a.factor[i] *=
poly(BHEAD sign);
951 if (a.power[i] % 2 == 1) overall_sign*=-1;
956 if (overall_sign == -1) {
958 for (
int i=0; i<(int)a.factor.size(); i++)
959 if (a.factor[i].is_integer()) {
960 a.factor[i] *=
poly(BHEAD -1);
965 a.add_factor(
poly(BHEAD -1), 1);
986WORD *
poly_factorize (PHEAD WORD *argin, WORD *argout,
bool with_arghead,
bool is_fun_arg) {
989 cout <<
"*** [" << thetime() <<
"] CALL : poly_factorize" << endl;
992 poly::get_variables(BHEAD vector<WORD*>(1,argin), with_arghead,
true);
994 poly a(poly::argument_to_poly(BHEAD argin, with_arghead,
true, &den));
1002 poly_fix_minus_signs(f);
1005 for (
int i=0; i<(int)f.factor.size(); i++)
1006 if (f.factor[i].is_integer())
1010 int len = with_arghead ? ARGHEAD : 0;
1012 if (!num.is_one() || !den.is_one()) {
1014 len += MaX(ABS(num[num[1]]), den[den[1]])*2+1;
1015 len += with_arghead ? ARGHEAD : 1;
1018 for (
int i=0; i<(int)f.factor.size(); i++) {
1019 if (!f.factor[i].is_integer()) {
1020 len += f.power[i] * f.factor[i].size_of_form_notation();
1021 len += f.power[i] * (with_arghead ? ARGHEAD : 1);
1027 if (argout != NULL) {
1029 if (len >= AM.MaxTer) {
1030 MLOCK(ErrorMessageLock);
1031 MesPrint (
"ERROR: factorization doesn't fit in a term (len = %d, MaxTermSize = %d words)",
1032 len/
sizeof(WORD), AM.MaxTer/
sizeof(WORD));
1033 MUNLOCK(ErrorMessageLock);
1039 argout = (WORD*) Malloc1(len*
sizeof(WORD),
"poly_factorize");
1042 WORD *old_argout = argout;
1045 if (!num.is_one() || !den.is_one()) {
1046 int n = max(ABS(num[num[1]]), ABS(den[den[1]]));
1049 *argout++ = ARGHEAD + 2 + 2*n;
1050 for (
int i=1; i<ARGHEAD; i++)
1054 *argout++ = 2 + 2*n;
1056 for (
int i=0; i<n; i++)
1057 *argout++ = i<ABS(num[num[1]]) ? num[2+AN.poly_num_vars+i] : 0;
1058 for (
int i=0; i<n; i++)
1059 *argout++ = i<ABS(den[den[1]]) ? den[2+AN.poly_num_vars+i] : 0;
1061 *argout++ = SGN(num[num[1]]) * (2*n+1);
1066 if (ToFast(old_argout, old_argout))
1067 argout = old_argout+2;
1072 for (
int i=0; i<(int)f.factor.size(); i++)
1073 if (!f.factor[i].is_integer())
1074 for (
int j=0; j<f.power[i]; j++) {
1075 poly::poly_to_argument(f.factor[i],argout,with_arghead);
1078 argout += *argout > 0 ? *argout : 2;
1080 while (*argout!=0) argout+=*argout;
1087 poly_free_poly_vars(BHEAD
"AN.poly_vars_factorize");
1090 AN.ncmod = AC.ncmod;
1115 cout <<
"*** [" << thetime() <<
"] CALL : poly_factorize_argument" << endl;
1119 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
1120 flint_factorize_argument(BHEAD argin, argout);
1149 cout <<
"*** [" << thetime() <<
"] CALL : poly_factorize_dollar" << endl;
1153 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
1154 return flint_factorize_dollar(BHEAD argin);
1181 cout <<
"*** [" << thetime() <<
"] CALL : poly_factorize_expression" << endl;
1186 if (AT.WorkPointer + AM.MaxTer > AT.WorkTop ) {
1187 MLOCK(ErrorMessageLock);
1189 MUNLOCK(ErrorMessageLock);
1193 WORD *term = AT.WorkPointer;
1194 WORD startebuf = cbuf[AT.ebufnum].numrhs;
1200 WORD oldBracketOn = AR.BracketOn;
1201 WORD *oldBrackBuf = AT.BrackBuf;
1202 WORD oldbracketindexflag = AT.bracketindexflag;
1203 char oldCommercial[COMMERCIALSIZE+2];
1205 strcpy(oldCommercial, (
char*)AC.Commercial);
1206 strcpy((
char*)AC.Commercial,
"factorize");
1209 if (expr->status == HIDDENGEXPRESSION || expr->status == HIDDENLEXPRESSION ||
1210 expr->status == INTOHIDEGEXPRESSION || expr->status == INTOHIDELEXPRESSION) {
1211 AR.InHiBuf = 0; file = AR.hidefile; AR.GetFile = 2;
1214 AR.InInBuf = 0; file = AR.outfile; AR.GetFile = 0;
1218 AR.infile = AR.outfile = file;
1221 if (expr->numdummies > 0) {
1222 MesPrint(
"ERROR: factorization with dummy indices not implemented");
1229 SeekFile(file->
handle,&pos,SEEK_SET);
1230 if (ISNOTEQUALPOS(pos,expr->onfile)) {
1231 MesPrint(
"ERROR: something wrong in scratch file [poly_factorize_expression]");
1234 file->POposition = expr->onfile;
1235 file->POfull = file->PObuffer;
1236 if (expr->status == HIDDENGEXPRESSION)
1242 file->POfill = (WORD *)((UBYTE *)(file->PObuffer)+BASEPOSITION(expr->onfile));
1245 SetScratch(AR.infile, &(expr->onfile));
1248 WORD size = GetTerm(BHEAD term);
1250 MesPrint (
"ERROR: something wrong with expression [poly_factorize_expression]");
1256 ADDPOS(pos, size*
sizeof(WORD));
1259 poly buffer(BHEAD 0);
1264 while (GetTerm(BHEAD term)) {
1266 sumcommu += DoesCommu(term);
1267 if ( sumcommu > 1 ) {
1268 MesPrint(
"ERROR: Cannot factorize an expression with more than one noncommuting object");
1271 buffer.check_memory(bufpos);
1273 MesPrint(
"ERROR: in LocalConvertToPoly [factorize_expression]");
1276 bufpos += *(buffer.terms + bufpos);
1282 AN.poly_num_vars = 0;
1283 poly::get_variables(BHEAD vector<WORD*>(1,buffer.terms),
false,
true);
1285 poly a(poly::argument_to_poly(BHEAD buffer.terms,
false,
true, &den));
1292 SetScratch(file, &pos);
1295 CBUF *C = cbuf+AC.cbufnum;
1296 CBUF *CC = cbuf+AT.ebufnum;
1299 WORD nexpr = expr - Expressions;
1301 AT.BrackBuf = AM.BracketFactors;
1302 AT.bracketindexflag = 1;
1303 ClearBracketIndex(-nexpr-2);
1304 OpenBracketIndex(nexpr);
1307 expr->numfactors = 1;
1309 else if (a.is_one() && den.is_one()) {
1310 expr->numfactors = 1;
1315 term[3] = FACTORSYMBOL;
1321 AT.WorkPointer += *term;
1323 AT.WorkPointer = term;
1327 bool iszero =
false;
1329 if (!(expr->vflags & ISFACTORIZED)) {
1331 fac = polyfact::factorize(a);
1332 poly_fix_minus_signs(fac);
1335 int factorsymbol=-1;
1336 for (
int i=0; i<AN.poly_num_vars; i++)
1337 if (AN.poly_vars[i] == FACTORSYMBOL)
1340 poly denpow(BHEAD 1);
1343 for (
int i=1; i<=expr->numfactors; i++) {
1344 poly origfac(a.coefficient(factorsymbol, i));
1346 if (origfac.is_zero())
1349 fac2 = polyfact::factorize(origfac);
1350 poly_fix_minus_signs(fac2);
1353 for (
int j=0; j<(int)fac2.power.size(); j++)
1354 fac.add_factor(fac2.factor[j], fac2.power[j]);
1361 expr->numfactors = 0;
1365 for (
int i=0; i<(int)fac.factor.size(); i++)
1366 if (fac.factor[i].is_integer())
1367 num *= fac.factor[i];
1369 poly gcd(polygcd::integer_gcd(num,den));
1376 if (!iszero || (expr->vflags & KEEPZERO)) {
1377 if (!num.is_one() || !den.is_one()) {
1380 int n = max(ABS(num[num[1]]), ABS(den[den[1]]));
1385 term[3] = FACTORSYMBOL;
1386 term[4] = expr->numfactors;
1387 for (
int i=0; i<n; i++) {
1388 term[5+i] = i<ABS(num[num[1]]) ? num[2+AN.poly_num_vars+i] : 0;
1389 term[5+n+i] = i<ABS(den[den[1]]) ? den[2+AN.poly_num_vars+i] : 0;
1391 term[5+2*n] = SGN(num[num[1]]) * (2*n+1);
1392 AT.WorkPointer += *term;
1394 AT.WorkPointer = term;
1397 vector<poly> fac_arg(fac.factor.size(),
poly(BHEAD 0));
1400 for (
int i=0; i<(int)fac.factor.size(); i++)
1401 if (!fac.factor[i].is_integer()) {
1402 buffer.check_memory(fac.factor[i].size_of_form_notation()+1);
1403 poly::poly_to_argument(fac.factor[i], buffer.terms,
false);
1406 for (WORD *t=buffer.terms; *t!=0; t+=*t) {
1408 if (ConvertFromPoly(BHEAD t, term, numxsymbol, CC->numrhs-startebuf+numxsymbol,
1409 startebuf-numxsymbol, 1) <= 0 ) {
1410 MesPrint(
"ERROR: in ConvertFromPoly [factorize_expression]");
1416 AT.WorkPointer += *term;
1418 AT.WorkPointer = term;
1423 if (
EndSort(BHEAD (WORD *)((
void *)(&buffer)),2) < 0)
return -1;
1426 for (WORD *t=buffer; *t!=0; t+=*t)
1429 fac_arg[i].check_memory(bufsize+ARGHEAD+1);
1431 for (
int j=0; j<ARGHEAD; j++)
1432 fac_arg[i].terms[j] = 0;
1433 fac_arg[i].terms[0] = ARGHEAD + bufsize;
1434 WCOPY(fac_arg[i].terms+ARGHEAD, buffer, bufsize);
1435 M_free(buffer,
"polynomial factorization");
1440 vector<vector<int> > comp(fac.factor.size(), vector<int>(fac.factor.size(), 0));
1442 for (
int i=0; i<(int)fac.factor.size(); i++)
1443 if (!fac.factor[i].is_integer()) {
1446 for (
int j=i+1; j<(int)fac.factor.size(); j++)
1447 if (!fac.factor[j].is_integer()) {
1448 comp[i][j] = CompArg(fac_arg[j].terms, fac_arg[i].terms);
1449 comp[j][i] = -comp[i][j];
1453 for (
int i=0; i<(int)order.size(); i++)
1454 for (
int j=0; j+1<(int)order.size(); j++)
1455 if (comp[order[i]][order[j]] == 1)
1456 swap(order[i],order[j]);
1459 for (
int i=0; i<(int)order.size(); i++)
1460 for (
int j=0; j<fac.power[order[i]]; j++) {
1464 WORD *tstop = fac_arg[order[i]].terms + *fac_arg[order[i]].terms;
1465 for (WORD *t=fac_arg[order[i]].terms+ARGHEAD; t<tstop; t+=*t) {
1467 WCOPY(term+4, t, *t);
1470 *term = *(term+4) + 4;
1473 *(term+3) = FACTORSYMBOL;
1474 *(term+4) = expr->numfactors;
1477 AT.WorkPointer += *term;
1479 AT.WorkPointer = term;
1486 if (
EndSort(BHEAD NULL,0) < 0) {
1492 if (expr->numfactors > 0)
1493 expr->vflags |= ISFACTORIZED;
1496 AR.infile = oldinfile;
1497 AR.outfile = oldoutfile;
1498 AR.BracketOn = oldBracketOn;
1499 AT.BrackBuf = oldBrackBuf;
1500 AT.bracketindexflag = oldbracketindexflag;
1501 strcpy((
char*)AC.Commercial, oldCommercial);
1503 poly_free_poly_vars(BHEAD
"AN.poly_vars_factorize_expression");
1525#if ( SUBEXPSIZE == 5 )
1526static WORD genericterm[] = {38,1,4,FACTORSYMBOL,0
1527 ,EXPRESSION,15,0,1,0,13,10,8,1,4,FACTORSYMBOL,0,1,1,3
1528 ,EXPRESSION,15,0,1,0,13,10,8,1,4,FACTORSYMBOL,0,1,1,3
1530static WORD genericterm2[] = {23,1,4,FACTORSYMBOL,0
1531 ,EXPRESSION,15,0,1,0,13,10,8,1,4,FACTORSYMBOL,0,1,1,3
1538 int i, j, nfac = expr->numfactors, nfacp, nexpr = expr - Expressions;
1543 char oldCommercial[COMMERCIALSIZE+2];
1545 WORD *oldworkpointer = AT.WorkPointer;
1546 WORD *term = AT.WorkPointer, *t, *w, size;
1551 WORD oldBracketOn = AR.BracketOn;
1552 WORD *oldBrackBuf = AT.BrackBuf;
1553 CBUF *C = cbuf+AC.cbufnum;
1555 if ( ( expr->vflags & ISFACTORIZED ) == 0 )
return(0);
1557 if ( AT.WorkPointer + AM.MaxTer > AT.WorkTop ) {
1558 MLOCK(ErrorMessageLock);
1560 MUNLOCK(ErrorMessageLock);
1564 oldpos = AS.OldOnFile[nexpr];
1565 AS.OldOnFile[nexpr] = expr->onfile;
1567 strcpy(oldCommercial, (
char*)AC.Commercial);
1568 strcpy((
char*)AC.Commercial,
"unfactorize");
1572 if ( expr->status == HIDDENGEXPRESSION || expr->status == HIDDENLEXPRESSION ||
1573 expr->status == INTOHIDEGEXPRESSION || expr->status == INTOHIDELEXPRESSION ) {
1574 AR.InHiBuf = 0; file = AR.hidefile; AR.GetFile = 2;
1577 AR.InInBuf = 0; file = AR.outfile; AR.GetFile = 0;
1582 AR.infile = AR.outfile = file;
1586 if ( file->
handle >= 0 ) {
1588 SeekFile(file->
handle,&pos,SEEK_SET);
1589 if (ISNOTEQUALPOS(pos,expr->onfile)) {
1590 MesPrint(
"ERROR: something wrong in scratch file unfactorize_expression");
1593 file->POposition = expr->onfile;
1594 file->POfull = file->PObuffer;
1595 if ( expr->status == HIDDENGEXPRESSION )
1601 file->POfill = (WORD *)((UBYTE *)(file->PObuffer)+BASEPOSITION(expr->onfile));
1603 SetScratch(AR.infile, &(expr->onfile));
1607 if ( GetFirstBracket(term,nexpr) < 0 ) Terminate(-1);
1608 if ( term[4] != 1 || *term != 8 || term[1] != SYMBOL || term[3] != FACTORSYMBOL || term[4] != 1 ) {
1611 SetScratch(AR.infile, &(expr->onfile));
1615 size = GetTerm(BHEAD term);
1617 MesPrint (
"ERROR: something wrong with expression unfactorize_expression");
1621 ADDPOS(pos, size*
sizeof(WORD));
1626 AT.BrackBuf = AM.BracketFactors;
1628 while ( nfac > 2 ) {
1629 nfacp = nfac - nfac%2;
1638 if ( AT.bracketinfo != 0 ) ClearBracketIndex(-1);
1639 AT.bracketinfo = expr->newbracketinfo;
1640 OpenBracketIndex(nexpr);
1647 if ( expriszero == 0 ) {
1648 for ( i = 0; i < nfacp; i += 2 ) {
1649 t = genericterm; w = term = oldworkpointer;
1650 j = *t; NCOPY(w,t,j);
1656 AT.WorkPointer = term + *term;
1659 if ( nfac > nfacp ) {
1660 t = genericterm2; w = term = oldworkpointer;
1661 j = *t; NCOPY(w,t,j);
1665 AT.WorkPointer = term + *term;
1669 if (
EndSort(BHEAD AM.S0->sBuffer,0) < 0 ) {
1676 SetScratch(file, &pos);
1678 if ( expriszero ) { nfac = 1; }
1680 if ( AT.bracketinfo != 0 ) ClearBracketIndex(-1);
1681 AT.bracketinfo = expr->newbracketinfo;
1682 expr->newbracketinfo = 0;
1686 AR.BracketOn = oldBracketOn;
1687 AT.BrackBuf = oldBrackBuf;
1688 if ( AR.BracketOn ) OpenBracketIndex(nexpr);
1694 if ( expriszero == 0 ) {
1696 t = genericterm2; w = term = oldworkpointer;
1697 j = *t; NCOPY(w,t,j);
1701 else if ( nfac == 2 ) {
1702 t = genericterm; w = term = oldworkpointer;
1703 j = *t; NCOPY(w,t,j);
1710 AS.OldOnFile[nexpr] = oldpos;
1713 term[4] = term[0]-4;
1715 AT.WorkPointer = term + *term;
1718 if (
EndSort(BHEAD AM.S0->sBuffer,0) < 0 ) {
1725 expr->numfactors = 0;
1726 expr->vflags &= ~ISFACTORIZED;
1727 if ( AT.bracketinfo != 0 ) ClearBracketIndex(-1);
1729 AR.infile = oldinfile;
1730 AR.outfile = oldoutfile;
1731 strcpy((
char*)AC.Commercial, oldCommercial);
1732 AT.WorkPointer = oldworkpointer;
1733 AS.OldOnFile[nexpr] = oldpos;
1743WORD *poly_inverse(PHEAD WORD *arga, WORD *argb) {
1746 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
1747 return flint_inverse(BHEAD arga, argb);
1752 cout <<
"*** [" << thetime() <<
"] CALL : poly_inverse" << endl;
1760 poly::get_variables(BHEAD e,
false,
true);
1762 if (AN.poly_num_vars > 1) {
1763 MLOCK(ErrorMessageLock);
1764 MesPrint ((
char*)
"ERROR: multivariate polynomial inverse is generally impossible");
1765 MUNLOCK(ErrorMessageLock);
1769 poly finalden(BHEAD 1), finalres(BHEAD 1);
1775 poly a(poly::argument_to_poly(BHEAD arga,
false,
true, &dena));
1776 poly b(poly::argument_to_poly(BHEAD argb,
false,
true));
1779 poly content_a(BHEAD 0), content_b(BHEAD 0);
1780 content_a = polygcd::integer_content(a);
1781 content_b = polygcd::integer_content(b);
1785 poly invamodp(BHEAD 0), invbmodp(BHEAD 0);
1790 if ((a.is_one() && b.is_one()) || a.is_one()) {
1791 finalres =
poly(BHEAD 1);
1793 else if (b.is_one()) {
1794 finalres =
poly(BHEAD 0);
1799 const bool mod_calc = modp==0 ? false :
true;
1804 poly gcd(polygcd::gcd(a,b));
1805 if (!gcd.is_one()) {
1806 MLOCK(ErrorMessageLock);
1808 MesPrint ((
char*)
"ERROR: polynomial inverse does not exist (mod %d)", modp);
1811 MesPrint ((
char*)
"ERROR: polynomial inverse does not exist");
1813 MUNLOCK(ErrorMessageLock);
1817 bool inv_exists =
true;
1822 modp = polyfact::choose_prime(a.integer_lcoeff()*b.integer_lcoeff(), x, modp);
1825 poly amodp(a,modp,1);
1826 poly bmodp(b,modp,1);
1829 vector<poly> xgcd(polyfact::extended_gcd_Euclidean_lifted(amodp,bmodp));
1830 invamodp =
poly(xgcd[0]);
1831 invbmodp =
poly(xgcd[1]);
1833 inv_exists = ((invamodp * amodp) % bmodp).is_one();
1834 if (!inv_exists && mod_calc) {
1836 MLOCK(ErrorMessageLock);
1837 MesPrint ((
char*)
"ERROR: polynomial inverse does not exist (mod %d) B", modp);
1838 MUNLOCK(ErrorMessageLock);
1845 }
while (!inv_exists);
1848 ressize = invamodp.size_of_form_notation()+1;
1849 res = (WORD *)Malloc1(ressize*
sizeof(WORD),
"poly_inverse");
1852 poly primepower(BHEAD modp);
1853 poly inva(invamodp,modp,1);
1854 poly invb(invbmodp,modp,1);
1860 for (
int i=1; i<inva[0]; i+=inva[i]) {
1863 while (ressize < j + 2*ABS(inva[i+inva[i]-1]) + (inva[i+1]>0?4:0) + 3) {
1864 int newressize = 2*ressize;
1866 WORD *newres = (WORD *)Malloc1(newressize*
sizeof(WORD),
"poly_inverse");
1867 WCOPY(newres, res, ressize);
1868 M_free(res,
"poly_inverse");
1870 ressize = newressize;
1875 res[j+res[j]++] = SYMBOL;
1876 res[j+res[j]++] = 4;
1877 res[j+res[j]++] = AN.poly_vars[0];
1878 res[j+res[j]++] = inva[i+1];
1880 MakeLongRational(BHEAD (UWORD *)&inva[i+2], inva[i+inva[i]-1],
1881 (UWORD*)&primepower.terms[3], primepower.terms[primepower.terms[1]],
1882 (UWORD *)&res[j+res[j]], &n);
1884 res[j+res[j]++] = SGN(n)*(2*ABS(n)+1);
1890 if (a.modp != 0)
break;
1894 poly check(poly::argument_to_poly(BHEAD res,
false,
true, &den));
1897 if (poly::divides(b.integer_lcoeff(), check.integer_lcoeff()*a.integer_lcoeff())) {
1898 check = check*a - den;
1899 if (poly::divides(b, check))
break;
1903 poly error((
poly(BHEAD 1) - a*inva - b*invb) / primepower);
1904 poly errormodpp(error, modp, inva.modn);
1909 poly dinva((inva * errormodpp) % b);
1910 poly dinvb((invb * errormodpp) % a);
1912 inva += dinva * primepower;
1913 invb += dinvb * primepower;
1915 primepower *= primepower;
1919 finalres =
poly(poly::argument_to_poly(BHEAD res,
false,
true, &finalden));
1924 finalden *= content_a;
1925 const WORD finalden_size = finalden.terms[finalden.terms[1]];
1926 const int finalsize = finalres.size_of_form_notation_with_den(finalden_size)+1;
1927 if (ressize < finalsize) {
1929 M_free(res,
"poly_inverse");
1931 res = (WORD *)Malloc1(finalsize*
sizeof(WORD),
"poly_inverse");
1933 poly::poly_to_argument_with_den(finalres, finalden_size,
1934 (UWORD*)&(finalden.terms[finalden.terms[1] - ABS(finalden_size)]), res,
false);
1937 poly_free_poly_vars(BHEAD
"AN.poly_vars_inverse");
1939 AN.ncmod = AC.ncmod;
1948WORD *poly_mul(PHEAD WORD *a, WORD *b) {
1951 cout <<
"*** [" << thetime() <<
"] CALL : poly_mul" << endl;
1955 if ( AC.FlintPolyFlag && AC.ncmod==0 ) {
1956 return flint_mul(BHEAD a, b);
1965 poly::get_variables(BHEAD e,
false,
false);
1970 poly pa(poly::argument_to_poly(BHEAD a,
false,
true, &dena));
1971 poly pb(poly::argument_to_poly(BHEAD b,
false,
true, &denb));
1983 assert(dena.is_integer());
1984 assert(denb.is_integer());
1985 assert(modp == 0 || dena.is_one());
1986 assert(modp == 0 || denb.is_one());
1993 if (dena.is_one() && denb.is_one()) {
1994 res = (WORD *)Malloc1((pa.size_of_form_notation() + 1) *
sizeof(WORD),
"poly_mul");
1995 poly::poly_to_argument(pa, res,
false);
1998 res = (WORD *)Malloc1((pa.size_of_form_notation_with_den(dena[dena[1]]) + 1) *
sizeof(WORD),
"poly_mul");
1999 poly::poly_to_argument_with_den(pa, dena[dena[1]], (
const UWORD *)&dena[2+AN.poly_num_vars], res,
false);
2003 poly_free_poly_vars(BHEAD
"AN.poly_vars_mul");
2004 AN.ncmod = AC.ncmod;
2014void poly_free_poly_vars(PHEAD
const char *text)
2016 if ( AN.poly_vars_type == 0 ) {
2017 TermFree(AN.poly_vars, text);
2020 M_free(AN.poly_vars, text);
2022 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)