1 //   Copyright (c)  2007,2009 John Abbott and Anna Bigatti
2 //   Author:  2007,2009  Anna Bigatti
3 
4 //   This file is part of the source of CoCoALib, the CoCoA Library.
5 
6 //   CoCoALib is free software: you can redistribute it and/or modify
7 //   it under the terms of the GNU General Public License as published by
8 //   the Free Software Foundation, either version 3 of the License, or
9 //   (at your option) any later version.
10 
11 //   CoCoALib is distributed in the hope that it will be useful,
12 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //   GNU General Public License for more details.
15 
16 //   You should have received a copy of the GNU General Public License
17 //   along with CoCoALib.  If not, see <http://www.gnu.org/licenses/>.
18 
19 
20 // Source code for abstract class SparsePolyRing and friends
21 
22 #include "CoCoA/DenseUPolyRing.H"
23 
24 #include "CoCoA/BigIntOps.H"
25 #include "CoCoA/BigRat.H"
26 #include "CoCoA/CpuTimeLimit.H"
27 #include "CoCoA/OpenMath.H"
28 #include "CoCoA/QuotientRing.H"  // for IsQuotientRing
29 #include "CoCoA/RingDenseUPolyClean.H" // for NewPolyRing_DUP
30 #include "CoCoA/RingFp.H" // for IsRingFp
31 #include "CoCoA/RingQQ.H" // for IsQQ
32 #include "CoCoA/RingTwinFloat.H" // for IsRingTwinFloat
33 #include "CoCoA/RingZZ.H" // for IsZZ
34 #include "CoCoA/assert.H"
35 #include "CoCoA/degree.H"
36 #include "CoCoA/error.H"
37 #include "CoCoA/symbol.H"
38 #include "CoCoA/utils.H"
39 
40 //#include <vector>
41 using std::vector;
42 #include <algorithm>
43 using std::max;
44 using std::sort;
45 
46 
47 namespace CoCoA
48 {
49 
NewPolyRing(const ring & CoeffRing)50   DenseUPolyRing NewPolyRing(const ring& CoeffRing)
51   {
52     return NewPolyRing_DUP(CoeffRing);
53   }
54 
NewPolyRing(const ring & CoeffRing,const symbol & IndetSym)55   DenseUPolyRing NewPolyRing(const ring& CoeffRing, const symbol& IndetSym)
56   {
57     return NewPolyRing_DUP(CoeffRing, IndetSym);
58   }
59 
IsGoodIndetName(const ring & CoeffRing,const symbol & IndetName)60   bool IsGoodIndetName(const ring& CoeffRing, const symbol& IndetName)
61   {
62     vector<symbol> syms = symbols(CoeffRing);
63     const long NumSyms = len(syms);
64     for (long i=0; i < NumSyms; ++i)
65     {
66       if (syms[i] == IndetName) return false;
67       if (head(syms[i]) == head(IndetName) &&
68           NumSubscripts(syms[i]) != NumSubscripts(IndetName))
69         return false;
70     }
71     return true;
72   }
73 
74 
mySymbolValue(const symbol & s)75   RingElem DenseUPolyRingBase::mySymbolValue(const symbol& s) const
76   {
77     if (s == myIndetSymbol()) return myIndets()[0];
78     return myCoeffEmbeddingHomCtor()(myCoeffRing()->mySymbolValue(s));
79   }
80 
81 
82   //---- Functions for creating/building polynomials
83 
monomial(const DenseUPolyRing & P,ConstRefRingElem c,const MachineInt & exp)84   RingElem monomial(const DenseUPolyRing& P, ConstRefRingElem c, const MachineInt& exp)
85   {
86     if (owner(c) != CoeffRing(P)) CoCoA_THROW_ERROR(ERR::MixedCoeffRings, "monomial(P,c,d)");
87     if (IsNegative(exp))
88       CoCoA_THROW_ERROR(ERR::NegExp, "monomial(P,c,d)");
89     if (!IsSignedLong(exp))
90       CoCoA_THROW_ERROR(ERR::ExpTooBig, "monomial(P,c,d)");
91     if (IsZero(c)) return zero(P);
92     return P->myMonomial(raw(c), AsSignedLong(exp));
93   }
94 
95 
monomial(const DenseUPolyRing & P,const BigInt & N,const MachineInt & exp)96   RingElem monomial(const DenseUPolyRing& P, const BigInt& N, const MachineInt& exp)
97   {
98     // All arg checking made by the call below...
99     return monomial(P, RingElem(CoeffRing(P), N), exp);
100   }
101 
102 
monomial(const DenseUPolyRing & P,const BigRat & N,const MachineInt & exp)103   RingElem monomial(const DenseUPolyRing& P, const BigRat& N, const MachineInt& exp)
104   {
105     // All arg checking made by the call below...
106     return monomial(P, RingElem(CoeffRing(P), N), exp);
107   }
108 
109 
monomial(const DenseUPolyRing & P,const MachineInt & n,const MachineInt & exp)110   RingElem monomial(const DenseUPolyRing& P, const MachineInt& n, const MachineInt& exp)
111   {
112     // All arg checking made by the call below...
113     return monomial(P, RingElem(CoeffRing(P), n), exp);
114   }
115 
116 
117   /*----------------------------------------------------------------------
118     Member functions every concrete DenseUPolyRing implementation
119     must have in addition to those of PolyRingBase.
120     ----------------------------------------------------------------------*/
121 
myIsValid(ConstRawPtr rawf)122   bool DenseUPolyRingBase::myIsValid(ConstRawPtr rawf) const
123   {
124     if (myDegPlus1(rawf)>mySize(rawf)) return false;
125     for (long i=myDegPlus1(rawf); i<mySize(rawf); ++i)
126       if (!IsZero(myCoeff(rawf, i))) return false;
127     if (myIsZero(rawf)) return true;
128     if (IsZero(myLC(rawf))) return false;
129     return true;
130   }
131 
132 
myStdDeg(ConstRawPtr rawf)133   long DenseUPolyRingBase::myStdDeg(ConstRawPtr rawf) const
134   {
135     if (myIsZero(rawf)) CoCoA_THROW_ERROR(ERR::ZeroRingElem, "myStdDeg(rawf)");
136     return myDegPlus1(rawf) - 1;
137   }
138 
139 
myDeg(ConstRawPtr rawf,long index)140   long DenseUPolyRingBase::myDeg(ConstRawPtr rawf, long index) const
141   {
142     if (index!=0) CoCoA_THROW_ERROR(ERR::BadIndetIndex, "myDeg(rawf, index)");
143     return myStdDeg(rawf);
144   }
145 
146 
myLC(ConstRawPtr rawf)147   RingElemAlias DenseUPolyRingBase::myLC(ConstRawPtr rawf) const
148   {
149     if (myIsZero(rawf)) CoCoA_THROW_ERROR(ERR::ZeroRingElem, "DenseUPolyRingBase::myLC(rawf)");
150     return myCoeff(rawf, myStdDeg(rawf));
151   }
152 
153 
myContent(RawPtr rawcontent,ConstRawPtr rawf)154   void DenseUPolyRingBase::myContent(RawPtr rawcontent, ConstRawPtr rawf) const
155   {
156     const ring& R = myCoeffRing();
157     CoCoA_ASSERT(IsTrueGCDDomain(R));
158     // Compute answer in local var to avoid aliasing problems; also exception clean.
159     RingElem ans(R);
160     for (long i=0; i<myDegPlus1(rawf); ++i)
161     {
162       if (IsZero(myCoeff(rawf,i))) continue;
163       R->myGcd(raw(ans), raw(ans), raw(myCoeff(rawf, i))); // ans = GCD(ans, coeff(i));
164       if (IsOne(ans)) break;
165     }
166     // Finally, swap answer into rawcontent.
167     R->mySwap(rawcontent, raw(ans));
168   }
169 
myContentFrF(RawPtr rawcontent,ConstRawPtr rawf)170   void DenseUPolyRingBase::myContentFrF(RawPtr rawcontent, ConstRawPtr rawf) const
171   {
172     CoCoA_ASSERT(IsFractionFieldOfGCDDomain(myCoeffRing()));
173     const FractionField R = myCoeffRing();
174     const ring& S = BaseRing(R);
175     RingElem N(S);
176     RingElem D(S,1);
177     for (long i=0; i < myDegPlus1(rawf); ++i)
178     {
179       if (IsZero(myCoeff(rawf,i))) continue;
180 //      R->myGcd(raw(ans), raw(ans), raw(num(myCoeff(rawf, i)))); // ans = GCD(ans, num(coeff(i)));
181       N = gcd(N, num(myCoeff(rawf, i)));
182       D = lcm(D, den(myCoeff(rawf, i)));
183 //      if (IsOne(ans)) break;
184     }
185     RingHom phi = EmbeddingHom(R);
186     RingElem ans = phi(N)/phi(D);
187     // Finally, swap answer into rawcontent.
188     R->mySwap(rawcontent, raw(ans));
189   }
190 
191 
myCommonDenom(RawPtr rawcontent,ConstRawPtr rawf)192   void DenseUPolyRingBase::myCommonDenom(RawPtr rawcontent, ConstRawPtr rawf) const
193   {
194     CoCoA_ASSERT(IsFractionFieldOfGCDDomain(myCoeffRing()));
195     const ring& R = BaseRing(myCoeffRing());
196     // Compute answer in local var to avoid aliasing problems; also exception clean.
197     RingElem ans = one(R);
198     for (long i=0; i<myDegPlus1(rawf); ++i)
199     {
200       ConstRefRingElem C = myCoeff(rawf, i);
201       if (!IsZero(C))
202       {
203         const RingElem D = den(C);
204         ans *= D/gcd(D, ans);
205       }
206     }
207     // Finally, swap answer into rawcontent.
208     R->mySwap(rawcontent, raw(ans));
209   }
210 
211 
myClearDenom(RawPtr rawg,ConstRawPtr rawf)212   void DenseUPolyRingBase::myClearDenom(RawPtr rawg, ConstRawPtr rawf) const
213   {
214     CoCoA_ASSERT(IsFractionFieldOfGCDDomain(myCoeffRing()));
215     const ring& R = BaseRing(myCoeffRing());
216     // Compute answer in local var to avoid aliasing problems; also exception clean.
217     RingElem c(R);
218     myCommonDenom(raw(c), rawf);
219     const RingElem coeff = CoeffEmbeddingHom(DenseUPolyRing(this))(EmbeddingHom(myCoeffRing()))(c);
220     myMul(rawg, raw(coeff), rawf);
221   }
222 
223 
myRemoveBigContent(RawPtr rawf)224   void DenseUPolyRingBase::myRemoveBigContent(RawPtr rawf) const
225   {
226     CoCoA_ASSERT(IsTrueGCDDomain(myCoeffRing()));
227     CoCoA_ASSERT(!myIsZero(rawf));
228     RingElem cont(myCoeffRing());
229     myContent(raw(cont), rawf);
230     myDivByCoeff(rawf, raw(cont));
231   }
232 
233 
234   /*----------------------------------------------------------------------
235     Member functions inherited from ring with a single implementation
236     for all DenseUPolyRing implementations
237     ----------------------------------------------------------------------*/
238 
239   namespace
240   {
241     // only if CoeffRing is a field
mod(RingElem & a,ConstRefRingElem b)242     void mod(RingElem& a, ConstRefRingElem b)  // a = a%b
243     {
244       CoCoA_ASSERT(owner(a) == owner(b));
245       CoCoA_ASSERT(!IsZero(b));  // this should be an error
246       while (!IsZero(a) && deg(a) >= deg(b))
247         DenseUPolyRingPtr(owner(a))->myAddMulLM(raw(a), raw(-LC(a)/LC(b)), deg(a)-deg(b), raw(b));
248     }
249 
DivMod(RingElem & q,RingElem & a,ConstRefRingElem b)250     void DivMod(RingElem& q, RingElem& a, ConstRefRingElem b)  // q = a/b;  a = a%b
251     {
252       // pointers must be different
253       CoCoA_ASSERT(owner(a) == owner(b));
254       CoCoA_ASSERT(owner(q) == owner(a));
255       CoCoA_ASSERT(!IsZero(b));  // this should be an error
256       const DenseUPolyRing P = owner(a);
257       q = zero(owner(q));
258       if (IsZero(a) || (deg(a)<deg(b)) ) return;
259       P->myResize(raw(q), deg(a)-deg(b)+1);
260       while (!IsZero(a) && deg(a) >= deg(b))
261       {
262         // q += monomial(P, -LC(a)/LC(b), deg(a)-deg(b));
263         P->myAssignNonZeroCoeff(raw(q), raw(LC(a)/LC(b)), deg(a)-deg(b));
264         P->myAddMulLM(raw(a), raw(-LC(a)/LC(b)), deg(a)-deg(b), raw(b));
265       }
266     }
267 
ExgcdAux(RingElem & acofac,RingElem & bcofac,RingElem & a,RingElem & b)268     void ExgcdAux(RingElem& acofac, RingElem& bcofac, RingElem& a, RingElem& b) // gcd is acofac*orig_a + bcofac*orig_b;  terminates with a=gcd and b=0
269     {
270       // all pointers must be different
271       CoCoA_ASSERT(owner(a) == owner(b));
272       CoCoA_ASSERT(!IsZero(b));  // this should be an error
273       acofac = 1;
274       bcofac = 0;  // i.e. a = acofac*a + bcofac*b
275       RingElem q(owner(b));
276       RingElem b_acofac(owner(b));
277       RingElem b_bcofac(one(owner(b)));  // i.e. b = b_acofac*a + b_bcofac*b
278       while (!IsZero(b))
279       {
280         // q = div(a, b);  a = a - b*d;
281         DivMod(q, a, b);
282         acofac -= b_acofac*q;
283         bcofac -= b_bcofac*q;
284         swap(a, b);
285         swap(acofac, b_acofac);
286         swap(bcofac, b_bcofac);
287       }
288   }
289 
290 
291   }  // anonymous namespace
292 
293 
myMul(RawPtr rawlhs,ConstRawPtr rawf,ConstRawPtr rawg)294   void DenseUPolyRingBase::myMul(RawPtr rawlhs, ConstRawPtr rawf, ConstRawPtr rawg) const
295   {
296     ring P(this);
297     RingElemAlias g(P, rawg);
298 
299     RingElem ans(P);
300     for (long i=0; i<myDegPlus1(rawf); ++i)
301       myAddMulLM(raw(ans), raw(myCoeff(rawf,i)), i, rawg);
302     mySwap(raw(ans), rawlhs); // really an assignment
303   }
304 
305 
myIsDivisible(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)306   bool DenseUPolyRingBase::myIsDivisible(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
307   {
308     ring P(this);
309     RingElem r = RingElemAlias(P, rawx);
310     RingElem ans(P);
311     DivMod(ans, r, RingElemAlias(P, rawy));
312     mySwap(raw(ans), rawlhs); // really an assignment
313     return IsZero(r);
314   }
315 
316 
317   // code for R[x]: compute gcd in FractionField(R)[x]
318   // see also myExgcd
myGcd(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)319   void DenseUPolyRingBase::myGcd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
320   {
321     RingElem a = RingElemAlias(ring(this), rawx);
322     if (IsInvertible(a))  a=1;
323     if (myIsZero(rawy))
324     {
325       mySwap(rawlhs, raw(a));
326       return;
327     }
328     RingElem b = RingElemAlias(ring(this), rawy);
329     if (IsInvertible(b))  b=1;
330     if (myIsZero(rawx))
331     {
332       mySwap(rawlhs, raw(b));
333       return;
334     }
335     if (!IsField(myCoeffRing()))
336     {
337       if (!IsTrueGCDDomain(myCoeffRing()))
338         CoCoA_THROW_ERROR(ERR::NYI, "DenseUPolyRingBase::myGcd");
339       else
340       {
341         const FractionField K = NewFractionField(myCoeffRing());
342         const DenseUPolyRing Kx = NewPolyRing(K);
343         const DenseUPolyRing P(this);
344         const RingHom phi = PolyRingHom(P, Kx, CoeffEmbeddingHom(Kx)(EmbeddingHom(K)), indets(Kx));
345         RingElem z = gcd(phi(a), phi(b));
346         Kx->myClearDenom(raw(z), raw(z));
347         RingElem g(P);
348         for (long d=myStdDeg(raw(z)) ; d >= 0 ; --d)
349           g += monomial(P, num(myCoeff(raw(z), d)), d);
350         myDivByCoeff(raw(g), raw(content(g)));
351         myMulByCoeff(raw(g), raw(gcd(content(a), content(b))));
352         P->mySwap(rawlhs, raw(g));
353         return;
354       }
355     }
356     // finally Euclid's Algorithm
357     mod(a, b);  // a = remainder(a, b)
358     while (!IsZero(a))
359     {
360       mySwap(raw(a), raw(b));
361       mod(a, b);  // a = remainder(a, b)
362     }
363     if (IsInvertible(b))  b=1;
364     mySwap(rawlhs, raw(b));
365   }
366 
367 
368   // See also myGcd
myExgcd(RawPtr rawlhs,RawPtr rawxcofac,RawPtr rawycofac,ConstRawPtr rawx,ConstRawPtr rawy)369   void DenseUPolyRingBase::myExgcd(RawPtr rawlhs, RawPtr rawxcofac, RawPtr rawycofac, ConstRawPtr rawx, ConstRawPtr rawy) const
370   {
371     ring P(ring(this));
372     RingElem ZeroP(P);
373     RingElem OneP(one(P));
374     RingElem a(RingElemAlias(P, rawx));
375     if (myIsZero(rawy))  // = raw(b)
376     {
377       mySwap(rawlhs, raw(a));
378       mySwap(rawxcofac, raw(OneP));
379       mySwap(rawycofac, raw(ZeroP));
380       return;
381     }
382     RingElem b(RingElemAlias(P, rawy));
383     if (myIsZero(rawx))  // = raw(a)
384     {
385       mySwap(rawlhs, raw(b));
386       mySwap(rawxcofac, raw(ZeroP));
387       mySwap(rawycofac, raw(OneP));
388       return;
389     }
390     if (!IsField(myCoeffRing()))
391       CoCoA_THROW_ERROR(ERR::NYI, "DenseUPolyRingBase::myGcd(RawPtr, ConstRawPtr, ConstRawPtr) const");
392     // finally Euclid's Algorithm
393     RingElem res(P), acofac(P), bcofac(P);
394     ExgcdAux(acofac, bcofac, a, b);
395     mySwap(rawlhs, raw(a));
396     mySwap(rawxcofac, raw(acofac));
397     mySwap(rawycofac, raw(bcofac));
398   }
399 
400 
mySymbols(std::vector<symbol> & SymList)401   void DenseUPolyRingBase::mySymbols(std::vector<symbol>& SymList) const
402   {
403     myCoeffRing()->mySymbols(SymList);
404     SymList.push_back(myIndetSymbol());
405   }
406 
407 
myOutput(std::ostream & out,ConstRawPtr rawf)408   void DenseUPolyRingBase::myOutput(std::ostream& out, ConstRawPtr rawf) const
409   {
410     if (!out) return;  // short-cut for bad ostreams
411 
412     if (myIsZero(rawf)) { out << "0"; return; }
413 
414     const ring& R = myCoeffRing();
415     bool PrintStar, IsFirstCoeff=true;
416     const bool IsQuotientOfZZ = IsQuotientRing(R) && IsZZ(BaseRing(R));
417     //bool IsQuotientOfZZ = IsRingFp(R);
418     const bool IsNumberRing = IsZZ(R) || IsQuotientOfZZ || IsQQ(R) || IsRingTwinFloat(R);
419 
420     for (long d=myStdDeg(rawf) ; d != 0 ; --d)
421     {
422       PrintStar = true;
423       ConstRefRingElem c = myCoeff(rawf, d);
424       if (IsZero(c)) continue;
425       //----------------------------------------------------------------------
426       // coefficient
427       //----------------------------------------------------------------------
428 
429       if (!IsNumberRing)
430       {
431         if (!IsFirstCoeff) out << " +";
432         out << '(' << c << ')';
433         goto EndCoeffPrint;
434       }
435       // assuming Q is printed with positive denominator
436       if (!IsFirstCoeff)
437       {
438         if (R->myIsPrintedWithMinus(raw(c))) out << " ";
439         else out <<" +";
440       }
441       if (IsOne(c)) // do not print "1 * "
442       {
443         PrintStar = false;
444         goto EndCoeffPrint;
445       }
446       if ( !IsQuotientOfZZ && IsMinusOne(c) ) // do not print "-1 * "
447       {
448         PrintStar = false;
449         out << "-";
450         goto EndCoeffPrint;
451       }
452       out << c;
453 
454     EndCoeffPrint:
455 
456       //----------------------------------------------------------------------
457       // PP
458       //----------------------------------------------------------------------
459       if (PrintStar)  out << "*";
460       out << myIndetSymbol();
461       if (d > 1) out << "^" << d;
462 
463       IsFirstCoeff = false;
464     }
465       //----------------------------------------------------------------------
466       // coefficient
467       //----------------------------------------------------------------------
468 
469     ConstRefRingElem c = myCoeff(rawf, 0);
470     if (IsZero(c)) return;
471     if (!IsNumberRing)
472     {
473       if (!IsFirstCoeff) out << " +";
474       out << '(' << c << ')';
475       return;
476     }
477       // assuming Q is printed with positive denominator
478     if (!IsFirstCoeff)
479     {
480       if (R->myIsPrintedWithMinus(raw(c))) out << " ";
481       else out <<" +";
482     }
483     out << c;
484   }
485 
486 
myOutputSelf(OpenMathOutput & OMOut)487   void DenseUPolyRingBase::myOutputSelf(OpenMathOutput& OMOut) const
488   {
489     OMOut->mySendApplyStart();
490     OMOut << OpenMathSymbol("setname1", myImplDetails());
491     OMOut << myCoeffRing();
492     OMOut->mySendApplyEnd();
493   }
494 
495 
myIsZero(ConstRawPtr rawx)496   bool DenseUPolyRingBase::myIsZero(ConstRawPtr rawx) const
497   {
498     return myDegPlus1(rawx)==0;
499   }
500 
501 
myIsPrintAtom(ConstRawPtr rawx)502   bool DenseUPolyRingBase::myIsPrintAtom(ConstRawPtr rawx) const
503   {
504     if (!myIsConstant(rawx)) return false;
505     // same as in "output"
506     const ring& R = myCoeffRing();
507 
508     if (IsZZ(R) || IsQQ(R)) return R->myIsPrintAtom(raw(myLC(rawx)));
509     return true;
510   }
511 
512 
myOutput(OpenMathOutput & OMOut,ConstRawPtr rawx)513   void DenseUPolyRingBase::myOutput(OpenMathOutput& OMOut, ConstRawPtr rawx) const
514   {
515     OMOut->mySendApplyStart();
516     OMOut << OpenMathSymbol("cocoa", "DUPCoeffs");
517     // ??? if (IsZero(rawx)) .....
518     OMOut << myStdDeg(rawx);
519 
520     for (long i=0 ; i <= myStdDeg(rawx) ; ++i)
521       OMOut << myCoeff(rawx, i);
522     OMOut->mySendApplyEnd();
523   }
524 
525 
myIsOne(ConstRawPtr rawf)526   bool DenseUPolyRingBase::myIsOne(ConstRawPtr rawf) const
527   {
528     if (myDegPlus1(rawf)!=1) return false;
529     return IsOne(myCoeff(rawf, 0));
530   }
531 
532 
myIsMinusOne(ConstRawPtr rawf)533   bool DenseUPolyRingBase::myIsMinusOne(ConstRawPtr rawf) const
534   {
535     if (myDegPlus1(rawf)!=1) return false;
536     return IsMinusOne(myCoeff(rawf, 0));
537   }
538 
539 
myIsConstant(ConstRawPtr rawf)540   bool DenseUPolyRingBase::myIsConstant(ConstRawPtr rawf) const
541   {
542     if (myDegPlus1(rawf)>1) return false;
543     return true;
544   }
545 
546 
myIsIndet(long & IndetIndex,ConstRawPtr rawf)547   bool DenseUPolyRingBase::myIsIndet(long& IndetIndex, ConstRawPtr rawf) const
548   {
549     if (myDegPlus1(rawf)!=2) return false;
550     if (!(IsOne(myCoeff(rawf,1)) && IsZero(myCoeff(rawf,0))))
551       return false;
552     IndetIndex = 0;
553     return true;
554   }
555 
556 
myIsIndetPosPower(ConstRawPtr rawf)557   bool DenseUPolyRingBase::myIsIndetPosPower(ConstRawPtr rawf) const
558   {
559     long d = -1;
560     for (long i=0; i<myDegPlus1(rawf); ++i)
561       if (!IsZero(myCoeff(rawf, i)))
562       {
563         if (!IsOne(myCoeff(rawf, i))) return false;
564         if (d != -1) return false; else d = i;
565       }
566     return true;
567   }
568 
569 
myIsEvenPoly(ConstRawPtr rawf)570   bool DenseUPolyRingBase::myIsEvenPoly(ConstRawPtr rawf) const
571   {
572     const long d1 = myDegPlus1(rawf);
573     if (d1 == 0) return true;
574     for (long i=1; i<d1; i+=2)
575       if (!IsZero(myCoeff(rawf, i))) return false;
576     return true;
577   }
578 
myIsOddPoly(ConstRawPtr rawf)579   bool DenseUPolyRingBase::myIsOddPoly(ConstRawPtr rawf) const
580   {
581     const long d1 = myDegPlus1(rawf);
582     if (d1 == 0) return true;
583     for (long i=0; i<d1; i+=2)
584       if (!IsZero(myCoeff(rawf, i))) return false;
585     return true;
586   }
587 
588 
myIsMonomial(ConstRawPtr rawf)589   bool DenseUPolyRingBase::myIsMonomial(ConstRawPtr rawf) const
590   {
591     if (myIsZero(rawf)) return true;
592     for (long i=0; i<myStdDeg(rawf); ++i)
593       if (!myIsZero(raw(myCoeff(rawf,i)))) return false;
594     return true;
595   }
596 
597 
myIndetPower(RawPtr rawf,long var,long exp)598   void DenseUPolyRingBase::myIndetPower(RawPtr rawf, long var, long exp) const
599   {
600     (void)(var); // to avoid compiler warning about unused parameter
601     CoCoA_ASSERT(var==0);
602     RingElem ans(ring(this));
603     myResize(raw(ans), exp+1);
604     myAssignNonZeroCoeff(raw(ans), raw(one(myCoeffRing())), exp);
605     mySwap(raw(ans), rawf); // do it this way to be exception clean
606   }
607 
608 
myNumTerms(ConstRawPtr rawf)609   long DenseUPolyRingBase::myNumTerms(ConstRawPtr rawf) const
610   {
611     long nt = 0;
612     for (long i=0; i<myDegPlus1(rawf); ++i)
613       if (!myCoeffRing()->myIsZero(raw(myCoeff(rawf,i)))) ++nt;
614     return nt;
615   }
616 
myMonomial(ConstRawPtr rawc,unsigned long exp)617   RingElem DenseUPolyRingBase::myMonomial(ConstRawPtr rawc, unsigned long exp) const
618   {
619     CoCoA_ASSERT(!myCoeffRing()->myIsZero(rawc));
620     RingElem ans(ring(this));
621     myResize(raw(ans), exp+1);
622     myAssignNonZeroCoeff(raw(ans), rawc, exp);
623     return ans;
624   }
625 
626 
myIsEqual(ConstRawPtr rawx,ConstRawPtr rawy)627   bool DenseUPolyRingBase::myIsEqual(ConstRawPtr rawx, ConstRawPtr rawy) const
628   {
629     if (myIsZero(rawx))
630     {
631       if (myIsZero(rawy)) return true;
632       else return false;
633     }
634     if (myDegPlus1(rawx) != myDegPlus1(rawy)) return false;
635     for (long i=0; i<myDegPlus1(rawx); ++i)
636       if (myCoeff(rawx,i) != myCoeff(rawy,i))
637         return false;
638     return true;
639   }
640 
641 
myIsInteger(BigInt & N,ConstRawPtr rawx)642   bool DenseUPolyRingBase::myIsInteger(BigInt& N, ConstRawPtr rawx) const
643   {
644     if (myIsZero(rawx))
645     {
646       N = 0;
647       return true;
648     }
649     if (myIsConstant(rawx))
650       return myCoeffRing()->myIsInteger(N, raw(myCoeff(rawx, 0)));
651     return false;
652   }
653 
654 
myIsRational(BigRat & Q,ConstRawPtr rawx)655   bool DenseUPolyRingBase::myIsRational(BigRat& Q, ConstRawPtr rawx) const
656   {
657     if (myIsZero(rawx)) { Q = 0; return true; }
658     if (!myIsConstant(rawx)) return false;
659     return IsRational(Q, myCoeff(rawx,0));
660   }
661 
662 
663 //   bool DenseUPolyRingBase::myIsHomog(ConstRawPtr rawf) const
664 //   {
665 //     if (myIsConstant(rawf)) { return true; }
666 //     CoCoA_THROW_ERROR(ERR::NYI, "DenseUPolyRingBase::myIsHomog(ConstRawPtr)");
667 //     return true;
668 //   }
669 
670 
myIsInvertible(ConstRawPtr rawx)671   bool DenseUPolyRingBase::myIsInvertible(ConstRawPtr rawx) const
672   {
673     return (!myIsZero(rawx)) && myIsConstant(rawx) && IsInvertible(myLC(rawx));
674   }
675 
676 
myPowerSmallExp(RawPtr rawlhs,ConstRawPtr rawx,long n)677   void DenseUPolyRingBase::myPowerSmallExp(RawPtr rawlhs, ConstRawPtr rawx, long n) const
678   {
679     // Assert that we have a genuinely non-trivial case.
680     CoCoA_ASSERT(n > 1);
681     CoCoA_ASSERT(!myIsZero(rawx) && !myIsOne(rawx) && !myIsMinusOne(rawx));
682     long NoUse;
683     if (myIsIndet(NoUse, rawx))  //??? is this the right place for this check??
684       myIndetPower(rawlhs, 0, n);
685     else
686       myBinaryPower(rawlhs, rawx, n);
687     //    mySequentialPower(rawlhs, rawx, n); //??? BUG/SLUG myBinaryPower better if univariate or coeffs are finite field
688   }
689 
690 
myIndetSymbol(long idx)691   const symbol& DenseUPolyRingBase::myIndetSymbol(long idx) const
692   {
693     if (idx!=0)
694       CoCoA_THROW_ERROR(ERR::BadIndetIndex, "DenseUPolyRingBase::myIndetSymbol(idx)");
695     return myIndetSymbol();
696   }
697 
698 
699   //---- Special functions on RingElem owned by DenseUPolyRing
700 
701 
702   //-- IdealImpl ----------------------------------------
703 
myIdealCtor(const std::vector<RingElem> & gens)704   ideal DenseUPolyRingBase::myIdealCtor(const std::vector<RingElem>& gens) const
705   {
706     return ideal(new IdealImpl(DenseUPolyRing(this), gens)); //??? ugly ???
707   }
708 
709 
IdealImpl(const DenseUPolyRing & P,const std::vector<RingElem> & gens)710   DenseUPolyRingBase::IdealImpl::IdealImpl(const DenseUPolyRing& P, const std::vector<RingElem>& gens):
711     myP(P),
712     myGensValue(gens)
713   {
714     myTidyGensIsValid = false;
715     if (!IsField(CoeffRing(P)))
716       CoCoA_THROW_ERROR("NYI ideal of polynomials with coeffs not in a field", "ideal(DenseUPolyRing, gens)");//???
717     const long ngens = len(gens);
718     for (long i=0; i < ngens; ++i)
719       if (owner(gens[i]) != myP) CoCoA_THROW_ERROR(ERR::MixedRings, "DenseUPolyRingBase::IdealImpl ctor");
720   }
721 
722 
myClone()723   IdealBase* DenseUPolyRingBase::IdealImpl::myClone() const
724   {
725     return new IdealImpl(*this);
726   }
727 
728 
IamZero()729   bool DenseUPolyRingBase::IdealImpl::IamZero() const
730   {
731     if (myTidyGensIsValid) return myTidyGensValue.empty();
732     const vector<RingElem>& g = myGensValue;
733     const long ngens = len(g);
734     for (long i=0; i < ngens; ++i)
735       if (!IsZero(g[i])) return false;
736     return true;
737   }
738 
739 
myTestIsMaximal()740   void DenseUPolyRingBase::IdealImpl::myTestIsMaximal() const
741   {
742     if (!IsField(CoeffRing(myP)))
743       CoCoA_THROW_ERROR(ERR::NYI, "DenseUPolyRingBase::IdealImpl::myTestIsMaximal() non-field CoeffRing");
744     myTestIsPrime();
745   }
746 
747 
myTestIsPrimary()748   void DenseUPolyRingBase::IdealImpl::myTestIsPrimary() const
749   {
750     CoCoA_THROW_ERROR(ERR::NYI, "DenseUPolyRingBase::IdealImpl::myTestIsPrimary()");
751   }
752 
753 
myTestIsPrime()754   void DenseUPolyRingBase::IdealImpl::myTestIsPrime() const
755   {
756     if (IamZero())
757     { myAssignPrimeFlag(IsIntegralDomain(CoeffRing(myRing()))); return; }
758     if (!IsField(CoeffRing(myP)))
759       CoCoA_THROW_ERROR(ERR::NYI, "DenseUPolyRingBase::IdealImpl::myTestIsPrime() non-field CoeffRing");
760     // The ring is K[x], thus a PID; hence ideal has a single generator.
761     CoCoA_ASSERT(len(myTidyGens(NoCpuTimeLimit()))==1);
762     const RingElem& f = myTidyGens(NoCpuTimeLimit())[0];
763     myAssignPrimeFlag(!IsConstant(f) && IsIrred(f));
764   }
765 
766   // redefine myAssignMaximalFlag etc, for PID
myTestIsRadical()767   void DenseUPolyRingBase::IdealImpl::myTestIsRadical() const
768   {
769     if (!IsField(CoeffRing(myP)))
770       CoCoA_THROW_ERROR(ERR::NYI, "DenseUPolyRingBase::IdealImpl::myTestIsRadical() non-field CoeffRing");
771     // The ring is K[x], thus a PID; hence ideal has a single generator.
772     CoCoA_ASSERT(len(myTidyGens(NoCpuTimeLimit()))==1);
773     myAssignRadicalFlag(IsSqFree(myTidyGens(NoCpuTimeLimit())[0]));
774   }
775 
776 
myReduceMod(RingElemRawPtr rawf)777   void DenseUPolyRingBase::IdealImpl::myReduceMod(RingElemRawPtr rawf) const
778   {
779     if (myP->myIsZero(rawf)) return;
780     if (IamZero()) return;
781     RingElem g = RingElemAlias(myP, rawf);
782     mod(g, (myTidyGens(NoCpuTimeLimit()))[0]);
783     myP->mySwap(rawf, raw(g));
784   }
785 
786 
IhaveElem(RingElemConstRawPtr rawf)787   bool DenseUPolyRingBase::IdealImpl::IhaveElem(RingElemConstRawPtr rawf) const
788   {
789     RingElem g = RingElemAlias(myP, rawf);
790     myReduceMod(raw(g));
791     return IsZero(g);
792   }
793 
794 
GetPtr(const ideal & I)795   inline const DenseUPolyRingBase::IdealImpl* DenseUPolyRingBase::IdealImpl::GetPtr(const ideal& I)
796   {
797     return dynamic_cast<const DenseUPolyRingBase::IdealImpl*>(I.myIdealPtr());
798   }
799 
800 
myAdd(const ideal & Jin)801   void DenseUPolyRingBase::IdealImpl::myAdd(const ideal& Jin)
802   {
803     myGensValue.insert(myGensValue.end(), gens(Jin).begin(), gens(Jin).end());
804     myTidyGensIsValid = false;
805     myTidyGensValue.clear();
806   }
807 
808 
myMul(const ideal & Jin)809   void DenseUPolyRingBase::IdealImpl::myMul(const ideal& Jin)
810   {
811     CoCoA_THROW_ERROR(ERR::NYI, "DenseUPolyRingBase::IdealImpl::mul");
812   }
813 
814 
myIntersect(const ideal & J)815   void DenseUPolyRingBase::IdealImpl::myIntersect(const ideal& J)
816   {
817     if (IamZero()) return;
818     if (IsZero(J))
819     {
820       myGensValue.clear();
821       myTidyGensValue.clear();
822       myTidyGensIsValid = true;
823       return;
824     }
825     if (!IsField(CoeffRing(myP)))
826       CoCoA_THROW_ERROR(ERR::NYI, "DenseUPolyRingBase::IdealImpl::intersect non-field CoeffRing");
827     RingElem f = myTidyGens(NoCpuTimeLimit())[0];
828     RingElem g = TidyGens(J)[0];
829     //    ideal I(myP, (g*f)/gcd(f,g));
830     RingElem h = (g*f)/gcd(f,g);
831     myGensValue.clear();
832     myGensValue.push_back(h);
833     myTidyGensValue.clear();
834     myTidyGensIsValid = false;
835   }
836 
837 
myColon(const ideal & J)838   void DenseUPolyRingBase::IdealImpl::myColon(const ideal& J)
839   {
840     if (!IsField(CoeffRing(myP)))
841       CoCoA_THROW_ERROR(ERR::NYI, "DenseUPolyRingBase::IdealImpl::colon non-field CoeffRing");
842     if (IamZero()) return;
843     if (IsZero(J))
844     {
845       myGensValue.clear();
846       myGensValue.push_back(one(myP));
847       myTidyGensValue.clear();
848       myTidyGensIsValid = false;
849       return;
850     }
851     RingElem f = myTidyGens(NoCpuTimeLimit())[0];
852     RingElem g = TidyGens(J)[0];
853     RingElem h = f/gcd(f,g);
854     myGensValue.clear();
855     myGensValue.push_back(h);
856     myTidyGensValue.clear();
857     myTidyGensIsValid = false;
858   }
859 
860 
myDivMod(RingElemRawPtr,RingElemConstRawPtr,RingElemConstRawPtr)861   bool DenseUPolyRingBase::IdealImpl::myDivMod(RingElemRawPtr /*rawlhs*/, RingElemConstRawPtr /*rawnum*/, RingElemConstRawPtr /*rawden*/) const
862   {
863     CoCoA_THROW_ERROR(ERR::NYI, "DenseUPolyRingBase::IdealImpl::myDivMod");
864     return false; // just to keep compiler quiet!!
865   }
866 
867 
myTidyGens(const CpuTimeLimit & CheckForTimeOut)868   const std::vector<RingElem>& DenseUPolyRingBase::IdealImpl::myTidyGens(const CpuTimeLimit& CheckForTimeOut) const
869   {
870     if (!IsField(CoeffRing(myP)))
871       CoCoA_THROW_ERROR(ERR::NYI, "DenseUPolyRingBase::IdealImpl::myTidyGens non-field CoeffRing");
872     if (myTidyGensIsValid) return myTidyGensValue;
873     CoCoA_ASSERT(myTidyGensValue.empty());
874     RingElem g(myP);
875     const long ngens = len(myGensValue);
876     for (long i=0; i < ngens; ++i)
877     {
878       CheckForTimeOut("DenseUPolyRingBase::IdealImpl::myTidyGens"); // could this ever be useful?
879       myP->myGcd(raw(g), raw(g), raw(myGensValue[i]));
880       if (IsInvertible(g)) break; // gcd is 1
881     }
882     if (!IsZero(g))  myTidyGensValue.push_back(g);
883     myTidyGensIsValid = true;
884     return myTidyGensValue;
885   }
886 
887 
coeff(ConstRefRingElem f,long d)888   RingElemAlias coeff(ConstRefRingElem f, long d)
889   {
890     if (!IsDenseUPolyRing(owner(f)))
891       CoCoA_THROW_ERROR(ERR::BadRing, "coeff(f,d)");
892     if (d < 0)
893       CoCoA_THROW_ERROR(ERR::NegExp, "coeff(f,d);");
894     return DenseUPolyRingPtr(owner(f))->myCoeff(raw(f), AsSignedLong(d));
895   }
896 
897 
898   //-- HomImpl ----------------------------------------
899 
HomImpl(const DenseUPolyRing & domain,const ring & codomain,const RingHom & CoeffHom,ConstRefRingElem IndetImage)900   DenseUPolyRingBase::HomImpl::HomImpl(const DenseUPolyRing& domain, const ring& codomain, const RingHom& CoeffHom, ConstRefRingElem IndetImage):
901       RingHomBase(domain, codomain),
902       myCoeffHom(CoeffHom),
903       myIndetImage(IndetImage)
904   {
905     // No need to check anything: checks already made when CoeffHom was built.
906   }
907 
908 namespace
909 {
910   // ??? this is essentially the same as ApplyGeneral: it should be improved
911   // assume image==0
ApplyDPRCodomain(RingElem & image,ConstRefRingElem arg,const RingHom CoeffHom,ConstRefRingElem IndetImage)912   void ApplyDPRCodomain(RingElem& image, ConstRefRingElem arg, const RingHom CoeffHom, ConstRefRingElem IndetImage)
913   {
914     const ring DPR = owner(image);
915     RingElem g(DPR);
916     if (!IsZero(arg))
917       for (long i=0; i<=deg(arg); ++i)
918       {
919         RingElem SummandImage = CoeffHom(coeff(arg,i));
920         CoCoA_ASSERT(owner(SummandImage) == DPR);
921         if (IsZero(SummandImage)) continue; // efficiency hack????
922         if (i != 0)
923           SummandImage *= power(IndetImage, i);
924         g += SummandImage;
925       }
926     swap(image, g);
927   }
928 
929 
ApplyGeneral(RingElem & image,ConstRefRingElem arg,const RingHom CoeffHom,ConstRefRingElem IndetImage)930   void ApplyGeneral(RingElem& image, ConstRefRingElem arg, const RingHom CoeffHom, ConstRefRingElem IndetImage)
931   {
932     ring R = owner(image);
933     RingElem g(R);
934     if (!IsZero(arg))
935       for (long i=0; i<=deg(arg); ++i)
936       {
937         RingElem SummandImage = CoeffHom(coeff(arg,i));
938         CoCoA_ASSERT(owner(SummandImage) == R);
939         if (IsZero(SummandImage)) continue; // efficiency hack????
940         if (i != 0)
941           SummandImage *= power(IndetImage, i);
942         g += SummandImage;
943       }
944     swap(image, g);
945   }
946 }  // end of anonymous namespace
947 
myApply(RingElemRawPtr rawimage,RingElemConstRawPtr rawarg)948   void DenseUPolyRingBase::HomImpl::myApply(RingElemRawPtr rawimage, RingElemConstRawPtr rawarg) const
949   {
950     RingElem ans(myCodomain);  // Putting result into ans is exception safe and avoids aliasing problems.
951     if ( IsDenseUPolyRing(myCodomain) )
952       ApplyDPRCodomain(ans, RingElemAlias(myDomain, rawarg), myCoeffHom, myIndetImage);
953     else
954       ApplyGeneral(ans, RingElemAlias(myDomain, rawarg), myCoeffHom, myIndetImage);
955     myCodomain->mySwap(rawimage, raw(ans));
956   }
957 
958 
myOutputSelfDetails(std::ostream & out)959   void DenseUPolyRingBase::HomImpl::myOutputSelfDetails(std::ostream& out) const
960   {
961     if (!out) return;  // short-cut for bad ostreams
962     if (NumIndets(myDomain) == 0) return;
963     out << " sending "
964         << "(" << indet(myDomain, 0) << " |--> " << myIndetImage << ")";
965   }
966 
967 
myHomCtor(const ring & codomain,const RingHom & CoeffHom,const std::vector<RingElem> & IndetImages)968   RingHom DenseUPolyRingBase::myHomCtor(const ring& codomain, const RingHom& CoeffHom, const std::vector<RingElem>& IndetImages) const
969   {
970     // Args already sanity checked by PolyRingHom (see PolyRing.C)
971 // DON'T KNOW IF I REALLY WANT TO MAKE THIS CHECK...
972 //       // Check to see if we're building an identity homomorphism
973 //       if (ring(this) == codomain && IsIdentity(CoeffHom))
974 //       {
975 //         bool IndetsFixed = true;
976 //         for (long i=0; i < myNumIndetsValue; ++i)
977 //           IndetsFixed &= (myIndetVector[i] == IndetImages[i]);
978 //         if (IndetsFixed) return IdentityHom(ring(this));
979 //       }
980       // General case
981     return RingHom(new HomImpl(DenseUPolyRing(this), codomain, CoeffHom, IndetImages[0]));
982   }
983 
984 
myCompose(const RingHom & phi,const RingHom & theta)985   RingHom DenseUPolyRingBase::myCompose(const RingHom& phi, const RingHom& theta) const
986   {
987     vector<RingElem> IndetImages;
988     IndetImages.push_back(phi(theta(myIndets()[0])));
989 
990     return myHomCtor(codomain(phi), phi(theta(myCoeffEmbeddingHomCtor())), IndetImages);
991   }
992 
993 
994   //-- CoeffEmbeddingHomImpl ----------------------------------------
995 
996   //---------------------------------------------------------------------------
997   // Functions for the class DenseUPolyRingBase::CoeffEmbeddingHomImpl
998 
999 
CoeffEmbeddingHomImpl(const DenseUPolyRing & P)1000   DenseUPolyRingBase::CoeffEmbeddingHomImpl::CoeffEmbeddingHomImpl(const DenseUPolyRing& P):
1001     RingHomEmbeddingBase(CoeffRing(P), P)
1002   {}
1003 
1004 
myApply(RingElemRawPtr rawimage,RingElemConstRawPtr rawarg)1005   void DenseUPolyRingBase::CoeffEmbeddingHomImpl::myApply(RingElemRawPtr rawimage, RingElemConstRawPtr rawarg) const
1006   {
1007     const DenseUPolyRing P = myCodomain;
1008     RingElem ans(P);  // don't use image here for aliasing
1009     // ??? ANNA profile this:  (probably better to have myMonomial)
1010     if (!myDomain->myIsZero(rawarg))
1011       ans = monomial(P, RingElemAlias(myDomain, rawarg), 0);
1012     P->mySwap(rawimage, raw(ans));
1013   }
1014 
1015 
1016 } // end of namespace CoCoA
1017 
1018 // RCS header/log in the next few lines
1019 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/DenseUPolyRing.C,v 1.76 2020/06/17 15:49:22 abbott Exp $
1020 // $Log: DenseUPolyRing.C,v $
1021 // Revision 1.76  2020/06/17 15:49:22  abbott
1022 // Summary: Changed CoCoA_ERROR into CoCoA_THROW_ERROR
1023 //
1024 // Revision 1.75  2020/02/12 10:48:59  bigatti
1025 // -- changed calls to myAssignBLAHFlagPID
1026 //
1027 // Revision 1.74  2020/02/12 09:01:47  bigatti
1028 // -- changed myTestIsMaximal etc to return void (and consequences)
1029 //
1030 // Revision 1.73  2020/02/11 16:56:40  abbott
1031 // Summary: Corrected last update (see redmine 969)
1032 //
1033 // Revision 1.72  2020/02/11 16:12:17  abbott
1034 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969
1035 //
1036 // Revision 1.71  2019/09/16 17:38:48  abbott
1037 // Summary: Impl myIsEvenPoly, myIsOddPoly
1038 //
1039 // Revision 1.70  2018/05/25 09:24:46  abbott
1040 // Summary: Major redesign of CpuTimeLimit (many consequences)
1041 //
1042 // Revision 1.69  2018/05/18 12:13:36  bigatti
1043 // -- renamed IntOperations --> BigIntOps
1044 //
1045 // Revision 1.68  2018/04/18 14:25:59  abbott
1046 // Summary: Added missing return
1047 //
1048 // Revision 1.67  2018/03/29 09:36:40  bigatti
1049 // -- added member functions myTestIsRadical, myTestIsPrimary and flags
1050 //
1051 // Revision 1.66  2018/03/20 11:45:54  bigatti
1052 // -- changed myPrimeTest --> myTestIsPrime (etc)
1053 //
1054 // Revision 1.65  2017/03/28 12:56:51  bigatti
1055 // -- changed copyright
1056 //
1057 // Revision 1.64  2016/11/08 13:03:31  bigatti
1058 // -- removed useless comment
1059 //
1060 // Revision 1.63  2016/09/08 14:12:32  bigatti
1061 // -- mySetMaximalFlag --> myAssignMaximalFlag
1062 // -- mySetPrimeFlag --> myAssignPrimeFlag
1063 // -- updated the related code
1064 // -- (still "old design", but better aligned)
1065 //
1066 // Revision 1.62  2015/05/04 13:14:10  bigatti
1067 // -- removed and fixed some comments
1068 //
1069 // Revision 1.61  2015/04/24 15:40:59  bigatti
1070 // -- renamed: myAddMul --> myAddMulLM
1071 // -- renamed: myMoveLM --> myMoveLMToFront
1072 // -- new myMoveLMToBack (used in ReductionCog --> bug in test-TmpMorseGraph??)
1073 //
1074 // Revision 1.60  2014/07/31 14:45:17  abbott
1075 // Summary: Merged io.H and UtilsTemplate.H into new header VectorOperations.H
1076 // Author: JAA
1077 //
1078 // Revision 1.59  2014/07/30 14:03:34  abbott
1079 // Summary: Changed myAmbientRing into myRing
1080 // Author: JAA
1081 //
1082 // Revision 1.58  2014/07/28 15:42:26  abbott
1083 // Summary: Changed myCoeffEmbeddingHom into myCoeffEmbeddingHomCtor
1084 // Author: JAA
1085 //
1086 // Revision 1.57  2014/07/14 15:05:58  abbott
1087 // Summary: Added include of utils.H
1088 // Author: JAA
1089 //
1090 // Revision 1.56  2014/07/11 15:35:25  bigatti
1091 // -- default implementation of myOutputSelf(OpenMathOutput& OMOut)
1092 //
1093 // Revision 1.55  2014/07/09 13:01:17  abbott
1094 // Summary: Removed AsDenseUPolyRing
1095 // Author: JAA
1096 //
1097 // Revision 1.54  2014/07/08 15:21:56  abbott
1098 // Summary: Updated comment
1099 // Author: JAA
1100 //
1101 // Revision 1.53  2014/07/08 13:14:40  abbott
1102 // Summary: Removed AsQuotientRing; added new defn of BaseRing
1103 // Author: JAA
1104 //
1105 // Revision 1.52  2014/07/08 08:34:41  abbott
1106 // Summary: Removed AsFractionField
1107 // Author: JAA
1108 //
1109 // Revision 1.51  2014/06/17 10:23:29  abbott
1110 // Summary: Added (void)(var) to avoid compiler warning about unused param in myIndetPower
1111 // Author: JAA
1112 //
1113 // Revision 1.50  2014/05/06 13:20:41  abbott
1114 // Summary: Changed names (my)MaxExponents into (my)Deg
1115 // Author: JAA
1116 //
1117 // Revision 1.49  2014/04/30 16:04:56  abbott
1118 // Summary: Replaced X.size() by len(X)
1119 // Author: JAA
1120 //
1121 // Revision 1.48  2014/04/15 14:24:21  abbott
1122 // Summary: Improved/cleaned IdealImpl:myPrimeTest
1123 // Author: JAA
1124 //
1125 // Revision 1.47  2013/06/28 17:03:51  abbott
1126 // Modified semantics of IdealBase::myDivMod;
1127 // it now returns a boolean.
1128 // Several consequential changes.
1129 //
1130 // Revision 1.46  2013/05/31 09:15:21  abbott
1131 // Changed arg type of fn "coeff" from MachineInt to long becaue it is an index.
1132 //
1133 // Revision 1.45  2012/10/24 12:12:36  abbott
1134 // Changed return type of coeff and myLC.
1135 // Replaced several ctor calls so that they build RingElemAlias.
1136 //
1137 // Revision 1.44  2012/10/17 12:03:19  abbott
1138 // Replaced  RefRingElem  by RingElem&
1139 //
1140 // Revision 1.43  2012/05/30 16:04:55  bigatti
1141 // -- applied "3" convention on bool3 functions and member fields
1142 //
1143 // Revision 1.42  2012/05/29 07:45:23  abbott
1144 // Implemented simplification change to bool3:
1145 //  changed names of the constants,
1146 //  changed names of the testing fns.
1147 //
1148 // Revision 1.41  2012/05/28 09:18:21  abbott
1149 // Created IntOperations which gathers together all operations on
1150 // integers (both big and small).  Many consequential changes.
1151 //
1152 // Revision 1.40  2012/05/24 14:53:35  bigatti
1153 // -- changed symbol "index" into "subscripts"
1154 //
1155 // Revision 1.39  2012/05/22 10:02:37  abbott
1156 // Removed IsGCDDomain; substituted by IsTrueGCDDomain.
1157 // Added IsFractionFieldOfGCDDomain.
1158 //
1159 // Revision 1.38  2012/04/27 15:08:58  abbott
1160 // Corrected myContentFrF
1161 //
1162 // Revision 1.37  2012/02/10 10:26:40  bigatti
1163 // -- changed RingZ.H, RingQ.H --> RingZZ.H, RingQQ.H
1164 //
1165 // Revision 1.36  2012/02/08 17:12:37  bigatti
1166 // -- changed: Z,Q -> ZZ,QQ
1167 //
1168 // Revision 1.35  2012/01/26 16:47:00  bigatti
1169 // -- changed back_inserter into insert
1170 //
1171 // Revision 1.34  2011/11/09 14:03:40  bigatti
1172 // -- renamed MachineInteger --> MachineInt
1173 //
1174 // Revision 1.33  2011/08/24 10:24:17  bigatti
1175 // -- renamed QQ --> BigRat
1176 // -- sorted #include
1177 //
1178 // Revision 1.32  2011/08/14 15:52:17  abbott
1179 // Changed ZZ into BigInt (phase 1: just the library sources).
1180 //
1181 // Revision 1.31  2011/06/23 16:04:47  abbott
1182 // Added IamExact mem fn for rings.
1183 // Added myRecvTwinFloat mem fn for rings.
1184 // Added first imple of RingHom from RingTwinFloat to other rings.
1185 //
1186 // Revision 1.30  2011/04/27 08:21:48  bigatti
1187 // -- added gcd with coefficients in GCDDomain
1188 //
1189 // Revision 1.29  2011/03/16 15:38:31  bigatti
1190 // -- added myIsIndetPosPower(f)
1191 //
1192 // Revision 1.28  2011/03/10 16:39:34  abbott
1193 // Replaced (very many) size_t by long in function interfaces (for rings,
1194 // PPMonoids and modules).  Also replaced most size_t inside fn defns.
1195 //
1196 // Revision 1.27  2011/03/01 14:10:47  bigatti
1197 // -- added ClearDenom/myClearDenom
1198 //
1199 // Revision 1.26  2011/02/23 16:04:50  bigatti
1200 // -- more fixes to get gcd==1 when coprime
1201 //
1202 // Revision 1.25  2011/01/18 14:38:43  bigatti
1203 // -- moved **_forC5 functions into CoCoA-5/CoCoALibSupplement:
1204 //    myMonomials_forC5, mySupport_forC5, monomials_forC5, support_forC5,
1205 //    LPP_forC5, LT_forC5, LM_forC5
1206 //
1207 // Revision 1.24  2010/11/30 11:30:49  bigatti
1208 // -- moved IndetsCalled into unique implementation in PolyRing
1209 // -- renamed IndetName --> IndetSymbol
1210 // -- added myIndetSymbol
1211 //
1212 // Revision 1.23  2010/11/25 12:31:22  bigatti
1213 // -- added myIndetsCalled
1214 //
1215 // Revision 1.22  2010/11/05 15:59:49  bigatti
1216 // -- added myMonomials_forC5, mySupport_forC5
1217 //
1218 // Revision 1.21  2010/10/01 15:45:17  bigatti
1219 // -- added mySymbolValue
1220 //
1221 // Revision 1.20  2010/06/10 08:00:02  bigatti
1222 // -- fixed naming conventions
1223 //
1224 // Revision 1.19  2010/02/04 10:12:04  bigatti
1225 // -- added "mul" for ideal (implemented only for SparsePolyRing)
1226 //
1227 // Revision 1.18  2009/10/02 13:27:26  bigatti
1228 // -- unique implementation of myDiv in PolyRing.C
1229 //
1230 // Revision 1.17  2009/09/24 16:24:19  abbott
1231 // Added include directive (after removing it from RingFp.H).
1232 //
1233 // Revision 1.16  2009/07/24 12:26:43  abbott
1234 // Added CommonDenom function for polynomials.
1235 //
1236 // Revision 1.15  2009/07/02 16:32:11  abbott
1237 // Consequential changes stemming from new class QQ, and modified interface to the member
1238 // function RingBase::myIsRational.  Also some new conversion functions.
1239 //
1240 // Revision 1.14  2009/05/22 10:24:12  bigatti
1241 // -- updated def of IsQuotientOfZ in myOutput
1242 //
1243 // Revision 1.13  2008/12/17 12:11:52  abbott
1244 // Changed type from long to MachineInt in operations which use a machine integer
1245 // in place of a RingElem.  The change is "superficial" but affects many files.
1246 //
1247 // Revision 1.12  2008/12/12 15:00:53  bigatti
1248 // -- added { } to disambiguate "if"
1249 //
1250 // Revision 1.11  2008/04/21 12:55:39  abbott
1251 // Fixed some minor bugs, and improved code layout slightly.
1252 //
1253 // Revision 1.10  2008/03/12 16:47:14  bigatti
1254 // -- added: myExgcd, myPrimeTest, myMaximalTest
1255 //
1256 // Revision 1.9  2007/12/21 12:29:08  bigatti
1257 // -- abstract implementation in DenseUPolyRing of myDiv, myIsDivisible, myIsInvertible, myGcd
1258 // -- abstract implementation in DenseUPolyRing of ideal operations
1259 // -- some cleaning
1260 //
1261 // Revision 1.8  2007/12/07 15:27:01  bigatti
1262 // -- default implementation of "IamOne" in ideal.C
1263 //
1264 // Revision 1.7  2007/12/05 11:06:24  bigatti
1265 // -- changed "size_t StdDeg/myStdDeg(f)" into "long"  (and related functions)
1266 // -- changed "log/myLog(f, i)" into "MaxExponent/myMaxExponent(f, i)"
1267 // -- fixed bug in "IsOne(ideal)" in SparsePolyRing.C
1268 //
1269 // Revision 1.6  2007/12/04 14:13:23  bigatti
1270 // -- added forgotten declaration.... sorry
1271 //
1272 // Revision 1.5  2007/12/04 13:44:50  bigatti
1273 // -- fixed problem with myMinCapacity in constructor
1274 // -- commented out myPowerSmallExp in RingDenseUPolyCleanImpl
1275 // -- refined myPowerSmallExp in DenseUPolyRing
1276 //
1277 // Revision 1.4  2007/10/30 17:14:08  abbott
1278 // Changed licence from GPL-2 only to GPL-3 or later.
1279 // New version for such an important change.
1280 //
1281 // Revision 1.3  2007/10/15 12:40:31  bigatti
1282 // -- new implementation for myAddMul
1283 // -- new: coeffs between deg+1 and size are now guaranteed to be 0
1284 //
1285 // Revision 1.2  2007/10/10 14:02:37  bigatti
1286 // -- added myMulBy1MinusXExp
1287 // -- fixed a few little bugs
1288 //
1289 // Revision 1.1  2007/10/05 15:28:56  bigatti
1290 // -- added abstract class DenseUPolyRing for representing dense
1291 //    univariate polynomials
1292 // -- added concrete class RingDenseUPolyClean, the cleanest
1293 //    implementation
1294 // -- just for testing, still horribly inefficient and incomplete
1295 //
1296