//////////////////////////////////////////////////////////// // emacs edit mode for this file is -*- C++ -*- /* $Id$ */ ///////////////////////////////////////////////////////////// // FACTORY - Includes #include // Factor - Includes #include #include #include #include #include // Charset - Includes #include "csutil.h" extern void out_cf(char *s1,const CanonicalForm &f,char *s2); extern CanonicalForm alg_lc(const CanonicalForm &f); extern int hasAlgVar(const CanonicalForm &f); static bool lowerRank ( const CanonicalForm & f, const CanonicalForm & g, int & ind ) { int df, dg; Variable vf = f.mvar(), vg = g.mvar(); if ( f.inCoeffDomain() ) { if ( g.inCoeffDomain() ) ind= 1; return true;//( vg > vf ); } else if ( g.inCoeffDomain() ) return false; else if ( vf < vg ) return true; else if ( vf == vg ) { df = degree( f ); dg = degree( g ); if ( df < dg ) return true; else if ( df == dg ) return lowerRank( LC( f ), LC( g ) , ind); else return false; } return false; } CanonicalForm lowestRank( const CFList & F ) { CFListIterator i = F; CanonicalForm f; int ind=0; if ( ! i.hasItem() ) return f; f = i.getItem(); ++i; while ( i.hasItem() ) { //CERR << "comparing " << f << " and " << i.getItem() // << " == " << lowerRank( i.getItem(), f, ind ) << "\n"; if ( lowerRank( i.getItem(), f, ind ) ) { if ( ind ) { CFList Itemlist= get_Terms(i.getItem()); CFList Flist= get_Terms(f); // Have to further compare number of terms! //CERR << "compare terms! f= " << Flist.length() << " item= " // << Itemlist.length() <<"\n"; if ( Itemlist.length() < Flist.length()) f = i.getItem(); ind=0; } else { f = i.getItem(); } } ++i; } return f; } // old version // CanonicalForm // prem ( const CanonicalForm &f, const CanonicalForm &g ) // { // CanonicalForm ff, gg, cg; // int df, dg; // bool reord; // Variable vf, vg, v; // // if ( (vf = f.mvar()) < (vg = g.mvar()) ) return f; // else { // if ( vf == vg ) { // ff = f; gg = g; // reord = false; // v = vg; // } // else { // v = Variable(level(f.mvar()) + 1); // ff = swapvar(f,vg,v); // gg = swapvar(g,vg,v); // reord=true; // } // cg = ini( gg, v ); // dg = degree( gg, v ); // while ( ( df = degree( ff, v ) ) >= dg ) // ff = cg * ff - power( v, df-dg ) * gg * LC( ff, v ); // if ( reord ) { // return swapvar( ff, vg, v ); // } // else // return ff; // } // } CanonicalForm Prem ( const CanonicalForm &f, const CanonicalForm &g ) { CanonicalForm ff, gg, l, test, lu, lv, t, retvalue; int df, dg; bool reord; Variable vf, vg, v; if ( (vf = f.mvar()) < (vg = g.mvar()) ) return f; else { if ( vf == vg ) { ff = f; gg = g; reord = false; v = vg; } else { v = Variable(level(f.mvar()) + 1); ff = swapvar(f,vg,v); gg = swapvar(g,vg,v); reord=true; } dg = degree( gg, v ); df = degree( ff, v ); if (dg <= df) {l=LC(gg); gg = gg -LC(gg)*power(v,dg);} else { l = 1; } while ( ( dg <= df ) && ( !ff.isZero()) ) { // CERR << "Start gcd..." << "\n"; test = gcd(l,LC(ff)); //CERR << "gcd(" << l << "," << LC(ff) << ")= " << test << "\n"; lu = l/test; lv = LC(ff)/test; t = power(v,df-dg) * gg * lv; if ( df == 0 ){ ff = ff.genZero(); } else { ff = ff - LC(ff)*power(v,df); } ff = lu*ff - t; df = degree( ff, v ); } if ( reord ) { retvalue= swapvar( ff, vg, v ); } else { retvalue= ff; } return retvalue; } } static CanonicalForm Sprem ( const CanonicalForm &f, const CanonicalForm &g, CanonicalForm & m, CanonicalForm & q ) { CanonicalForm ff, gg, l, test, retvalue; int df, dg,n; bool reord; Variable vf, vg, v; if ( (vf = f.mvar()) < (vg = g.mvar()) ) { m=CanonicalForm(0); q=CanonicalForm(0); return f; } else { if ( vf == vg ) { ff = f; gg = g; reord = false; v = vg; // == x } else { v = Variable(level(f.mvar()) + 1); ff = swapvar(f,vg,v); // == r gg = swapvar(g,vg,v); // == v reord=true; } dg = degree( gg, v ); // == dv df = degree( ff, v ); // == dr if (dg <= df) {l=LC(gg); gg = gg -LC(gg)*power(v,dg);} else { l = 1; } n= 0; while ( ( dg <= df ) && ( !ff.isZero()) ) { test= power(v,df-dg) * gg * LC(ff); if ( df == 0 ){ff= ff.genZero();} else {ff= ff - LC(ff)*power(v,df);} ff = l*ff-test; df= degree(ff,v); n++; } if ( reord ) { retvalue= swapvar( ff, vg, v ); } else { retvalue= ff; } m= power(l,n); if ( fdivides(g,m*f-retvalue) ) q= (m*f-retvalue)/g; else q= CanonicalForm(0); return retvalue; } } CanonicalForm divide( const CanonicalForm & ff, const CanonicalForm & f, const CFList & as) { CanonicalForm r,m,q; //out_cf("divide f=",ff,"\n"); //out_cf("divide g=",f,"\n"); if (f.inCoeffDomain()) { bool b=!isOn(SW_RATIONAL); On(SW_RATIONAL); q=ff/f; if (b) Off(SW_RATIONAL); } else r= Sprem(ff,f,m,q); //result in q, ignore r,m //CERR << "r= " << r << " , m= " << m << " , q= " << q << "\n"; r= Prem(q,as); //CERR << "r= " << r << "\n"; //out_cf(" ->",r,"\n"); return r; } // This function allows as to be empty; in that case, it is equivalent // to the previous version (treating no variables as algebraic). static CanonicalForm myfitting( const CanonicalForm &f, const CFList &as ) { CanonicalForm rem=f; if ( !(rem.isZero()) ) { if ( getCharacteristic() > 0 ) return num((rem/lc(rem))); else { On(SW_RATIONAL); CanonicalForm temp= mapinto(rem); // CERR << "temp= " << temp << "\n"; // CERR << "lc(temp)= " << lc(temp) << "\n"; // CERR << "temp/lc(temp)= " << temp/lc(temp) << "\n"; // CERR << "num(rem/lc(rem))= " << num(rem/lc(rem)) << "\n"; // If as is of length 1, and its polynomial is level 1, then // we treat the first variable as algebraic and invert the leading // coefficient where this variable is part of the coefficient domain. if (as.length() == 1 && level(as.getFirst()) == 1) { CanonicalForm lcoeff = temp; while (level(lcoeff) > 1) { lcoeff = LC(lcoeff); } // out_cf("myfitting: lcoeff = ", lcoeff, "\n"); CanonicalForm p = as.getFirst(); // out_cf("myfitting: p = ", p, "\n"); CanonicalForm unused, inverse; extgcd(lcoeff, p, inverse, unused); // out_cf("myfitting: inverse = ", inverse, "\n"); // This may leave temp with non-integral coefficients, // which will be cleaned up below. temp = temp * inverse; // out_cf("myfitting: temp = ", temp, "\n"); } temp= bCommonDen(temp/lc(temp))*(temp/lc(temp)); Off(SW_RATIONAL); rem= mapinto(temp); return rem; } } else return rem; } CanonicalForm Prem( const CanonicalForm &f, const CFList &L ) { CanonicalForm rem = f; CFListIterator i = L; for ( i.lastItem(); i.hasItem(); i-- ) { //CERR << " PREM: Prem(" << rem << "," ; rem = Prem( rem, i.getItem() ); //CERR << " PREM: Prem(" << rem << "," << i.getItem() << ") = " << rem << "\n"; } return myfitting(rem, CFList()); } CanonicalForm Prem( const CanonicalForm &f, const CFList &L, const CFList &as ) { CanonicalForm rem = f; CFListIterator i = L; for ( i.lastItem(); i.hasItem(); i-- ) { //CERR << " PREM: Prem(" << rem << "," ; rem = Prem( rem, i.getItem() ); //CERR << " PREM: Prem(" << rem << "," << i.getItem() << ") = " << rem << "\n"; } return myfitting(rem, as); } CFList Prem( const CFList &AS, const CFList &L ) { CFList Output; for ( CFListIterator i=AS; i.hasItem(); i++ ) Output = Union(CFList(Prem(i.getItem(),L)), Output); return Output; } static CanonicalForm premasb( const CanonicalForm & f, const CFList & as) { CanonicalForm remd=f; CFList AS=as; if ( as.length() > 1 ) { AS.removeFirst(); // get rid of first elem CanonicalForm elem; while ( ! AS.isEmpty() ) { // thats true for at least the first iteration elem= AS.getLast(); remd= Prem(remd,elem); AS.removeLast(); } } CanonicalForm a,b; if ( mydivremt(remd, as.getFirst(), a,b )){ remd= remd.genZero();} else { remd= Prem(remd, as.getFirst()); } return remd; } CFList remsetb( const CFList & ps, const CFList & as) { CFList output; CanonicalForm elem; for (CFListIterator i=ps; i.hasItem(); i++) { elem= premasb(i.getItem(),as); if ( !elem.isZero() ) output.append(elem); } return output; } // for characteristic sets ////////////////////////////////// // replace the power of factors of polys in as by 1 if any static CFList nopower( const CanonicalForm & init ) { CFFList sqrfreelist;// = Factorize(init);//SqrFree(init); CFList output; CanonicalForm elem; int count=0; for ( CFIterator j=init; j.hasTerms(); j++ ) if (!(j.coeff().isOne()) ) count++; // if ( init != 1 ){ // CERR << "nopower: f is " << init << "\n"; // CERR << "nopower: count is " << count << "\n";} if ( count > 1 ) sqrfreelist = CFFList( CFFactor(init,1)); else { sqrfreelist = Factorize(init); //sqrfreelist.removeFirst(); } for ( CFFListIterator i=sqrfreelist; i.hasItem(); i++ ) { elem=i.getItem().factor(); if ( cls(elem) > 0 ) output.append(elem); } return output; } // remove the content of polys in PS; add the removed content to // Remembern.FS2 ( the set of removed factors ) CFList removecontent ( const CFList & PS, PremForm & Remembern ) { CFListIterator i=PS; if ((!i.hasItem()) || ( cls(PS.getFirst()) == 0 )) return PS; CFList output; CanonicalForm cc,elem; for (; i.hasItem(); i++) { elem = i.getItem(); cc = content(elem, elem.mvar()); if ( cls(cc) > 0 ) { output.append(elem/cc); Remembern.FS2 = Union(CFList(cc), Remembern.FS2); } else{ output.append(elem); } } return output; } // remove possible factors in Remember.FS1 from poly r // Remember.FS2 contains all factors removed before void removefactor( CanonicalForm & r , PremForm & Remembern) { int test; CanonicalForm a,b,testelem; CFList testlist; int n=level(r); CFListIterator j ; for ( int J=1; J<= n ; J++ ) { testlist.append(CanonicalForm(Variable(J))); } // testlist = Union(Remembern.FS1, testlist); // add candidates // remove already removed factors for ( j = Remembern.FS2 ; j.hasItem(); j++ ) { testelem = j.getItem(); while ( 1 ) { test = mydivremt(r,testelem,a,b); if ( test && b.isZero() ) r = a; else break; } } // Let's look if we have other canditates to remove for ( j = testlist ; j.hasItem(); j++ ) { testelem = j.getItem(); // if ( testelem != r && testelem != r.mvar() ){ if ( testelem != r ) { while ( 1 ) { test = divremt(r,testelem,a,b); if ( test && b.isZero() ) { Remembern.FS2= Union(Remembern.FS2, CFList(testelem)); r = a; if ( r == 1 ) break; } else break; } } } // CERR << "Remembern.FS1 = " << Remembern.FS1 << "\n"; // CERR << "Remembern.FS2 = " << Remembern.FS2 << "\n"; // Remembern.FS1 = Difference(Remembern.FS1, Remembern.FS2); // CERR << " New Remembern.FS1 = " << Remembern.FS1 << "\n"; } // all irreducible nonconstant factors of a set of polynomials CFList factorps( const CFList &ps ) { CFList qs; CFFList q; CanonicalForm elem; for ( CFListIterator i=ps; i. hasItem(); i++ ) { q=Factorize(i.getItem()); q.removeFirst(); // Next can be simplified ( first (already removed) elem in q is the only constant for ( CFFListIterator j=q; j.hasItem(); j++ ) { elem = j.getItem().factor(); if ( getNumVars(elem) > 0 ) qs= Union(qs, CFList(myfitting(elem, CFList()))); } } return qs; } // the initial of poly f wrt to the order of the variables static CanonicalForm inital( const CanonicalForm &f ) { CanonicalForm leadcoeff; if ( cls(f) == 0 ) {return f.genOne(); } else { leadcoeff = LC(f,lvar(f)); // if ( leadcoeff != 0 ) return myfitting(leadcoeff, CFList()); //num(leadcoeff/lc(leadcoeff)); // else return leadcoeff; } } // the set of all nonconstant factors of initals of polys in as // CFList // initalset(const CFList &as){ // CanonicalForm elem; // CFList is, iss,iniset; // for ( CFListIterator i=as ; i.hasItem(); i++ ){ // elem = inital(i.getItem()); // if ( cls(elem) > 0 ) is.append(elem); // } // iss = factorps(is); // for ( CFListIterator j=iss; j.hasItem();j++ ){ // elem = j.getItem(); // if ( cls(elem) > 0 ) iniset.append(num(elem/lc(elem))); // } // return iniset; // } // the set of nonconstant initials of Cset // with certain repeated factors cancelled CFList initalset1(const CFList & Cset) { CFList temp; CFList initals; CanonicalForm init; for ( CFListIterator i = Cset ; i.hasItem(); i++ ) { initals= nopower( inital(i.getItem()) ); // init= inital(i.getItem()); for ( CFListIterator j = initals; j.hasItem(); j++) { init = j.getItem(); if ( cls(init) > 0 ) temp= Union(temp, CFList(init)); } } return temp; } // the set of nonconstant initials of Cset of those polys // not having their cls higher than reducible // with certain repeated factors cancelled CFList initalset2(const CFList & Cset, const CanonicalForm & reducible) { CFList temp; CFList initals; CanonicalForm init; int clsred = cls(reducible); for ( CFListIterator i = Cset ; i.hasItem(); i++ ) { init = i.getItem(); if ( cls(init) < clsred ) { initals= nopower( inital(init) ); // init= inital(i.getItem()); for ( CFListIterator j = initals; j.hasItem(); j++) { init = j.getItem(); if ( cls(init) > 0 ) temp= Union(temp, CFList(init)); } } } return temp; } //replace the power of factors of poly in CF init by 1 if any // and return the sqrfree poly // static CanonicalForm // nopower1( const CanonicalForm & init ){ // CFFList returnlist=Factorize(init); // CanonicalForm elem, test=init.genOne(); // for ( CFFListIterator i= returnlist; i.hasItem(); i++){ // elem = i.getItem().factor(); // if ( cls(elem)>0 ) test *= elem; // } // return test; // } // the sequence of distinct factors of f //CF pfactor( ..... ) // ////////////////////////////////////////// // // for IrrCharSeries #ifdef IRRCHARSERIESDEBUG # define DEBUGOUTPUT #else # undef DEBUGOUTPUT #endif #include "debug.h" // examine the irreducibility of as for IrrCharSeries int irreducible( const CFList & AS) { // AS is given by AS = { A1, A2, .. Ar }, d_i = degree(Ai) // 1) we test: if d_i > 1, d_j =1 for all j<>i, then AS is irreducible. bool deg1=true; for ( CFListIterator i = AS ; i.hasItem(); i++ ) { if ( degree(i.getItem()) > 1 ) { if ( deg1 ) deg1=0; else return 0; // found 2nd poly with deg > 1 } } return 1; } // select an item from PS for irras CFList select( const ListCFList & PS) { return PS.getFirst(); } // divide list ppi in elems having length <= and > length void select( const ListCFList & ppi, int length, ListCFList & ppi1, ListCFList & ppi2) { CFList elem; for ( ListCFListIterator i=ppi ; i.hasItem(); i++ ) { elem = i.getItem(); if ( ! elem.isEmpty() ) if ( length <= elem.length() ){ ppi2.append(elem); } else { ppi1.append(elem); } } } ////////////////////////////////////////////////////////////// // help-functions for sets // is f in F ? static bool member( const CanonicalForm &f, const CFList &F) { for ( CFListIterator i=F; i.hasItem(); i++ ) if ( i.getItem() == f ) return 1; return 0; } // are list A and B the same? bool same( const CFList &A, const CFList &B ) { CFListIterator i; for (i = A; i.hasItem(); i++) if (! member(i.getItem(), B) ) return 0; for (i = B; i.hasItem(); i++) if (! member(i.getItem(), A) ) return 0; return 1; } // is List cs contained in List of lists pi? bool member( const CFList & cs, const ListCFList & pi ) { ListCFListIterator i; CFList elem; for ( i=pi; i.hasItem(); i++) { elem = i.getItem(); if ( same(cs,elem) ) return 1; } return 0; } // is PS a subset of Cset ? bool subset( const CFList &PS, const CFList &Cset ) { // CERR << "subset: called with: " << PS << " " << Cset << "\n"; for ( CFListIterator i=PS; i.hasItem(); i++ ) if ( ! member(i.getItem(), Cset) ) { // CERR << "subset: " << i.getItem() << " is not a member of " << Cset << "\n"; return 0; } return 1; } // Union of two List of Lists ListCFList MyUnion( const ListCFList & a, const ListCFList &b ) { ListCFList output; ListCFListIterator i; CFList elem; for ( i = a ; i.hasItem(); i++ ) { elem=i.getItem(); if ( (! elem.isEmpty()) && ( ! member(elem,output)) ) { output.append(elem); } } for ( i = b ; i.hasItem(); i++ ) { elem=i.getItem(); if ( (! elem.isEmpty()) && ( ! member(elem,output)) ) { output.append(elem); } } return output; } //if list b is member of the list of lists remove b and return the rest ListCFList MyDifference( const ListCFList & a, const CFList &b) { ListCFList output; ListCFListIterator i; CFList elem; for ( i = a ; i.hasItem(); i++ ) { elem=i.getItem(); if ( (! elem.isEmpty()) && ( ! same(elem,b)) ) { output.append(elem); } } return output; } // remove all elements of b from list of lists a and return the rest ListCFList Minus( const ListCFList & a, const ListCFList & b) { ListCFList output=a; for ( ListCFListIterator i=b; i.hasItem(); i++ ) output = MyDifference(output, i.getItem() ); return output; } #if 0 static CanonicalForm alg_lc(const CanonicalForm &f, const CFList as) { for(CFListIterator i=as; i.hasItem(); i++) { if (f.mvar()==i.getItem().mvar()) return f; } if (f.level()>0) { return alg_lc(f.LC(),as); } return CanonicalForm(1); } #endif CanonicalForm alg_gcd(const CanonicalForm & fff, const CanonicalForm &ggg, const CFList &as) { CanonicalForm f=fff; CanonicalForm g=ggg; f=Prem(f,as); g=Prem(g,as); if ( f.isZero() ) { if ( g.lc().sign() < 0 ) return -g; else return g; } else if ( g.isZero() ) { if ( f.lc().sign() < 0 ) return -f; else return f; } //out_cf("alg_gcd(",fff," , "); //out_cf("",ggg,")\n"); CanonicalForm res; // does as appear in f and g ? bool has_alg_var=false; for ( CFListIterator j=as;j.hasItem(); j++ ) { Variable v=j.getItem().mvar(); if (hasVar(f,v)) {has_alg_var=true; /*break;*/} if (hasVar(g,v)) {has_alg_var=true; /*break;*/} //out_cf("as:",j.getItem(),"\n"); } if (!has_alg_var) { if ((hasAlgVar(f)) || (hasAlgVar(g))) { Varlist ord; for ( CFListIterator j=as;j.hasItem(); j++ ) ord.append(j.getItem().mvar()); res=algcd(f,g,as,ord); } else res=gcd(f,g); //out_cf("gcd=",res,"\n"); //out_cf("of f=",fff," , "); //out_cf("and g=",ggg,"\n"); return res; } int mvf=f.level(); int mvg=g.level(); if (mvg > mvf) { CanonicalForm tmp=f; f=g; g=tmp; int tmp2=mvf; mvf=mvg; mvg=tmp2; } if (g.inBaseDomain() || f.inBaseDomain()) { //printf("const\n"); //out_cf("of f=",fff," , "); //out_cf("and g=",ggg,"\n"); return CanonicalForm(1); } // gcd of all coefficients: CFIterator i=f; CanonicalForm c_gcd=i.coeff(); i++; while( i.hasTerms()) { c_gcd=alg_gcd(i.coeff(),c_gcd,as); if (c_gcd.inBaseDomain()) break; i++; } //printf("f.mvar=%d (%d), g.mvar=%d (%d)\n",f.level(),mvf,g.level(),mvg); if (mvf!=mvg) // => mvf > mvg { res=alg_gcd(g,c_gcd,as); //out_cf("alg_gcd1=",res,"\n"); //out_cf("of f=",fff," , "); //out_cf("and g=",ggg,"\n"); return res; } // now: mvf==mvg, f.level()==g.level() if (!c_gcd.inBaseDomain()) { i=g; while( i.hasTerms()) { c_gcd=alg_gcd(i.coeff(),c_gcd,as); if (c_gcd.inBaseDomain()) break; i++; } } //f/=c_gcd; //g/=c_gcd; if (!c_gcd.isOne()) { f=divide(f,c_gcd,as); g=divide(g,c_gcd,as); } CFList gg; CanonicalForm r=1; while (1) { //printf("f.mvar=%d, g.mvar=%d\n",f.level(),g.level()); gg=as; if (!g.inCoeffDomain()) gg.append(g); //out_cf("Prem(",f," , "); //out_cf("",g,")\n"); if (g.inCoeffDomain()|| g.isZero()) { //printf("in coeff domain:"); if (g.isZero()) { //printf("0\n"); i=f; CanonicalForm f_gcd=i.coeff(); i++; while( i.hasTerms()) { f_gcd=alg_gcd(i.coeff(),f_gcd,as); if (f_gcd.inBaseDomain()) break; i++; } //out_cf("g=0 -> f:",f,"\n"); //out_cf("f_gcd:",f_gcd,"\n"); //out_cf("c_gcd:",c_gcd,"\n"); //f/=f_gcd; f=divide(f,f_gcd,as); //out_cf("f/f_gcd:",f,"\n"); f*=c_gcd; //out_cf("f*c_gcd:",f,"\n"); CanonicalForm r_lc=alg_lc(f); //out_cf("r_lc:",r_lc,"\n"); //f/=r_lc; f=divide(f,r_lc,as); //out_cf(" -> gcd:",f,"\n"); return f; } else { //printf("c\n"); return c_gcd;} } else if (g.level()==f.level()) r=Prem(f,gg,as); else { //printf("diff. level: %d, %d\n", f.level(), g.level()); // g and f have different levels //out_cf("c_gcd=",c_gcd,"\n"); //out_cf("of f=",fff," , "); //out_cf("and g=",ggg,"\n"); return c_gcd; } //out_cf("->",r,"\n"); f=g; g=r; } if (degree(f,Variable(mvg))==0) { // remark: mvf == mvg == f.level() ==g.level() //out_cf("c_gcd=",c_gcd,"\n"); //out_cf("of f=",fff," , "); //out_cf("and g=",ggg,"\n"); return c_gcd; } //out_cf("f=",f,"\n"); i=f; CanonicalForm k=i.coeff(); i++; //out_cf("k=",k,"\n"); while( i.hasTerms()) { if (k.inCoeffDomain()) break; k=alg_gcd(i.coeff(),k,as); //out_cf("k=",k,"\n"); i++; } //out_cf("end-k=",k,"\n"); f/=k; //out_cf("f/k=",f,"\n"); res=c_gcd*f; CanonicalForm r_lc=alg_lc(res); res/=r_lc; //CanonicalForm r_lc=alg_lc(res,as); //res/=r_lc; //out_cf("alg_gcd2=",res,"\n"); // out_cf("of f=",fff," , "); // out_cf("and g=",ggg,"\n"); //return res; //if (res.level()