1 //   Copyright (c)  2018  John Abbott and Anna M. Bigatti
2 //   Authors:  2018  John Abbott and Anna M. Bigatti
3 //             2017  Alice Moallemy (translation CoCoA5-->CoCoALib)
4 
5 //   This file is part of the source of CoCoALib, the CoCoA Library.
6 
7 //   CoCoALib is free software: you can redistribute it and/or modify
8 //   it under the terms of the GNU General Public License as published by
9 //   the Free Software Foundation, either version 3 of the License, or
10 //   (at your option) any later version.
11 
12 //   CoCoALib is distributed in the hope that it will be useful,
13 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //   GNU General Public License for more details.
16 
17 //   You should have received a copy of the GNU General Public License
18 //   along with CoCoALib.  If not, see <http://www.gnu.org/licenses/>.
19 
20 
21 // Source code for ideals in SparsePolyRing (functions and member functions)
22 
23 #include "CoCoA/SparsePolyOps-ideal.H"
24 
25 #include "CoCoA/BigIntOps.H"
26 #include "CoCoA/BigRat.H"
27 #include "CoCoA/CpuTimeLimit.H"
28 #include "CoCoA/DUPFp.H"
29 #include "CoCoA/DenseMatrix.H" // for MultiplicationMat/myDiv
30 #include "CoCoA/MatrixOps.H" // for LinSolve
31 #include "CoCoA/MatrixView.H" // for ZeroMat
32 #include "CoCoA/PPMonoidHom.H"
33 #include "CoCoA/PolyRing.H"
34 #include "CoCoA/QuotientRing.H" // for IsQuotientRing
35 #include "CoCoA/RingFp.H" // for IsRingFp
36 #include "CoCoA/RingHom.H"
37 #include "CoCoA/RingQQ.H" // for IsQQ
38 #include "CoCoA/RingZZ.H" // for IsZZ
39 #include "CoCoA/SmallFpImpl.H"
40 #include "CoCoA/SparsePolyIter.H"
41 #include "CoCoA/SparsePolyOps-MinPoly.H" // for MinPolyDef
42 #include "CoCoA/SparsePolyOps-ideal-monomial.H"
43 #include "CoCoA/SparsePolyRing.H"
44 #include "CoCoA/TmpGOperations.H"  // for myIntersect, my Elim..
45 #include "CoCoA/TmpPPVector.H"  // for interreducing in GBasisByHomog
46 #include "CoCoA/TmpUniversalInvolutiveBasisContainer.H" // for ideal ctor
47 #include "CoCoA/apply.H"
48 #include "CoCoA/assert.H"
49 #include "CoCoA/error.H"
50 #include "CoCoA/factor.H"  // for myGcd
51 #include "CoCoA/random.H" // for RandomLongStream
52 #include "CoCoA/time.H"
53 #include "CoCoA/verbose.H"
54 //#include "CoCoA/ideal.H"     // for myGcd
55 //#include "CoCoA/matrix.H" // for OrdMat, myDivMod
56 
57 #include <algorithm>
58 //using std::max;     // for MaxExponent, StdDeg
59 using std::remove;  // for myColon
60 using std::sort;    // for AreGoodIndetNames, QuotientBasisSorted
61 //#include <functional>
62 //using std::not1;    // for AreLPPSqFree
63 //using std::ptr_fun; // for AreLPPSqFree
64 #include <iostream>
65 // using std::ostream in SparsePolyRingBase::myOutput
66 //#include <iterator>
67 //using std::back_inserter;
68 #include <list>
69 //#include <vector>
70 using std::vector;
71 
72 namespace CoCoA
73 {
74 
75 
myGens()76   const std::vector<RingElem>& SparsePolyRingBase::IdealImpl::myGens() const
77   { return myGensValue; }
78 
79 
myTidyGens(const CpuTimeLimit & CheckForTimeOut)80   const std::vector<RingElem>& SparsePolyRingBase::IdealImpl::myTidyGens(const CpuTimeLimit& CheckForTimeOut) const
81   { return myGBasis(CheckForTimeOut); }
82 
83 
GBasis(const ideal & I,const CpuTimeLimit & timeout)84   const std::vector<RingElem>& GBasis(const ideal& I,
85                                       const CpuTimeLimit& timeout)
86   {
87     if (!IsSparsePolyRing(RingOf(I)))
88       CoCoA_ERROR(ERR::NotSparsePolyRing, "GBasis(I)");
89     return TidyGens(I, timeout);
90   }
91 
92 
GBasisByHomog(const ideal & I,const CpuTimeLimit & timeout)93   const std::vector<RingElem>& GBasisByHomog(const ideal& I,
94                                               const CpuTimeLimit& timeout)
95   {
96     if (!IsSparsePolyRing(RingOf(I)))
97       CoCoA_ERROR(ERR::NotSparsePolyRing, "GBasisByHomog(I, timeout)");
98     const SparsePolyRingBase::IdealImpl* const ptrI =
99       SparsePolyRingBase::IdealImpl::ourGetPtr(I);
100     return ptrI->myGBasisByHomog(timeout);
101   }
102 
103 
GBasisSelfSatCore(const ideal & I)104   std::vector<RingElem> GBasisSelfSatCore(const ideal& I)
105   {
106     if (!IsSparsePolyRing(RingOf(I)))
107       CoCoA_ERROR(ERR::NotSparsePolyRing, "GBasisSelfSatCore(I)");
108     const SparsePolyRingBase::IdealImpl* const ptrI =
109       SparsePolyRingBase::IdealImpl::ourGetPtr(I);
110     return ptrI->myGBasisSelfSatCore();
111   }
112 
113 
GBasisRealSolve(const ideal & I)114   std::vector<RingElem> GBasisRealSolve(const ideal& I)
115   {
116     if (!IsSparsePolyRing(RingOf(I)))
117       CoCoA_ERROR(ERR::NotSparsePolyRing, "GBasisRealSolve(I)");
118     const SparsePolyRingBase::IdealImpl* const ptrI =
119       SparsePolyRingBase::IdealImpl::ourGetPtr(I);
120     return ptrI->myGBasisRealSolve();
121   }
122 
123 
ReducedGBasis(const ideal & I)124   const std::vector<RingElem>& ReducedGBasis(const ideal& I)
125   {
126     if (IsCommutative(RingOf(I))) return GBasis(I); // the same (2017)
127     CoCoA_ERROR(ERR::NYI, "ReducedGBasis non-commutative");
128     return GBasis(I); // just to keep the compiler quiet
129   }
130 
131 
MinGens(const ideal & I)132   const std::vector<RingElem>& MinGens(const ideal& I)
133   {
134     if (!IsSparsePolyRing(RingOf(I)))
135       CoCoA_ERROR(ERR::NotSparsePolyRing, "MinGens(I)");
136     const SparsePolyRingBase::IdealImpl* const ptrI =
137       SparsePolyRingBase::IdealImpl::ourGetPtr(I);
138     return ptrI->myMinGens();
139   }
140 
141 
myPrimaryDecomposition()142   std::vector<ideal> SparsePolyRingBase::IdealImpl::myPrimaryDecomposition() const
143   {
144     //if (IhaveMonomialGens()) return myPrimaryDecomposition_MonId();
145     if (IhaveSqFreeMonomialGens()) return myPrimaryDecomposition_MonId();
146     if (IamZeroDim()) return myPrimaryDecomposition_0dim();
147     CoCoA_ERROR(ERR::NYI, "myPrimaryDecomposition() -- general ideal");
148     return vector<ideal>(); // just to keep compiler quiet
149   }
150 
151 
LT(const ideal & I)152   ideal LT(const ideal& I)
153   {
154     if (!IsSparsePolyRing(RingOf(I)))
155       CoCoA_ERROR(ERR::NotSparsePolyRing, "LT(I)");
156     std::vector<RingElem> GB = TidyGens(I);
157     std::vector<RingElem> v;
158     const SparsePolyRing P = RingOf(I);
159     for (long i=0; i<len(GB); ++i)
160       v.push_back(monomial(P, LPP(GB[i])));
161     return ideal(P, v);
162   }
163 
164 
LF(const ideal & I)165   ideal LF(const ideal& I)
166   {
167     if (!IsSparsePolyRing(RingOf(I)))
168       CoCoA_ERROR(ERR::NotSparsePolyRing, "LF(I)");
169     const SparsePolyRing P = RingOf(I);
170     if ( GradingDim(P)==0 ) CoCoA_ERROR("GradingDim must be non-0", "LF(I)");
171     std::vector<RingElem> GB = TidyGens(I);
172     std::vector<RingElem> v;
173     for (long i=0; i<len(GB); ++i)  v.push_back(LF(GB[i]));
174     return ideal(P, v);
175   }
176 
177 
homog(const ideal & I,ConstRefRingElem x)178   ideal homog(const ideal& I, ConstRefRingElem x)
179   {
180     if (!IsSparsePolyRing(RingOf(I)))
181       CoCoA_ERROR(ERR::NotSparsePolyRing, "homog(I, x)");
182     if (AreGensMonomial(I)) return I;
183     if (IsZero(I)) return I;
184     std::vector<RingElem> HomogIdealGens;
185     std::vector<RingElem> v(1,x);
186     ComputeHomogenization(HomogIdealGens, gens(I), v);
187     return ideal(HomogIdealGens);
188   }
189 
190 
IdealOfGBasis(const ideal & I)191   ideal IdealOfGBasis(const ideal& I)
192   {
193     ideal J(RingOf(I), GBasis(I));
194     SetGBasisAsGens(J);
195 //     if (!uncertain3(IamPrime3Flag)) ...
196 //     if (!uncertain3(IamMaximal3Flag
197     return J;
198   }
199 
200 
IdealOfMinGens(const ideal & I)201   ideal IdealOfMinGens(const ideal& I)
202   {
203     ideal J = I;
204     MinGens(J); // so GBasis and such are stored in original ideal
205     MakeUnique(J)->myMinimalize();
206     return J;
207   }
208 
209 
210   // Anna: must be friend for ourGetPtr
HasGBasis(const ideal & I)211   bool HasGBasis(const ideal& I)
212   {
213     if (!IsSparsePolyRing(RingOf(I)))
214       CoCoA_ERROR(ERR::NotSparsePolyRing, "HasGBasis(I)");
215     const SparsePolyRingBase::IdealImpl* const ptrI =
216       SparsePolyRingBase::IdealImpl::ourGetPtr(I);
217     return ptrI->IhaveGBasis();
218   }
219 
220 
221   // Anna: must be friend for ourGetPtr
AreGensMonomial(const ideal & I)222   bool AreGensMonomial(const ideal& I)
223   {
224     if (!IsSparsePolyRing(RingOf(I)))
225       CoCoA_ERROR(ERR::NotSparsePolyRing, "AreGensMonomial(I)");
226     const SparsePolyRingBase::IdealImpl* const ptrI =
227       SparsePolyRingBase::IdealImpl::ourGetPtr(I);
228     return ptrI->IhaveMonomialGens();
229   }
230 
231 
232   // Anna: must be friend for ourGetPtr
AreGensSqFreeMonomial(const ideal & I)233   bool AreGensSqFreeMonomial(const ideal& I)
234   {
235     if (!IsSparsePolyRing(RingOf(I)))
236       CoCoA_ERROR(ERR::NotSparsePolyRing, "AreGensSqFreeMonomial(I)");
237     const SparsePolyRingBase::IdealImpl* const ptrI =
238       SparsePolyRingBase::IdealImpl::ourGetPtr(I);
239     return ptrI->IhaveSqFreeMonomialGens();
240   }
241 
242 
243   // Anna: must be friend for ourGetPtr
SetGBasisAsGens(const ideal & I)244   void SetGBasisAsGens(const ideal& I)
245   {
246     if (!IsSparsePolyRing(RingOf(I)))
247       CoCoA_ERROR(ERR::NotSparsePolyRing, "GBasisAsGens(I)");
248     const SparsePolyRingBase::IdealImpl* const ptrI =
249       SparsePolyRingBase::IdealImpl::ourGetPtr(I);
250     ptrI->mySetGBasisAsGens();
251   }
252 
253 
254 //   namespace  //anonymous  for QuotientBasis
255 //   {
256 
257 //     bool IsDivisible(ConstRefPPMonoidElem pp, const std::list<PPMonoidElem>& ByL)
258 //     {
259 //       for (std::list<PPMonoidElem>::const_iterator i=ByL.begin(); i != ByL.end(); ++i)
260 //         if (IsDivisible(pp, *i)) return true;
261 //       return false;
262 //     }
263 
264 
265 // //     // ??? copied from ex-QuotientBasis.C
266 // //     bool IsDivisible(ConstRefPPMonoidElem pp, const std::vector<PPMonoidElem>& ByL)
267 // //     {
268 // //       const long n = len(ByL);
269 // //       for (long i=0; i < n; ++i)
270 // //         if ( IsDivisible(pp, ByL[i]) ) return true;
271 // //       return false;
272 // //     }
273 
274 
275 //     // Apparently STL bind2nd cannot have (const?) reference arguments.
276 //     // Apparently BOOST bind would work: what about C++-11?
277 //     // This is a hack for STL
278 //     class IsDivHack
279 //     {
280 //     public:
281 //       IsDivHack (const std::list<PPMonoidElem>& L): myL(L) {}
282 //       bool operator () (ConstRefPPMonoidElem pp) {return IsDivisible(pp, myL);}
283 
284 //     private:
285 //       const std::list<PPMonoidElem> & myL;
286 //     };
287 
288 
289 //     void QuotientBasisRec(std::vector<PPMonoidElem>& ans,
290 //                           const std::list<PPMonoidElem>& L,
291 //                           ConstRefPPMonoidElem prefix,
292 //                           long idx)
293 //     {
294 //       PPMonoid PPM = owner((L.front()));
295 //       const PPMonoidElem& X = indets(PPM)[idx];
296 //       PPMonoidElem prefixXd(prefix);  // prefix * x[idx]^d
297 //       int MaxDeg = 0;
298 //       if (idx == NumIndets(PPM)-1)
299 //       {
300 //         MaxDeg = exponent((L.front()), idx);
301 //         for (int d=0; d < MaxDeg;  ++d, prefixXd *= X)  ans.push_back(prefixXd);
302 //         return;
303 //       }
304 //       for (std::list<PPMonoidElem>::const_iterator it=L.begin(); it != L.end() ; ++it)
305 //         if (exponent((*it),idx) > MaxDeg)  MaxDeg = exponent((*it),idx);
306 //       std::list<PPMonoidElem> CutOff, tmp;
307 //       PPMonoidElem Xd(PPM);  // x[idx]^d
308 //       for (int d=0; d < MaxDeg; ++d, prefixXd *= X, Xd *= X)
309 //       {
310 //         for (std::list<PPMonoidElem>::const_iterator it=L.begin(); it != L.end(); ++it)
311 //           if (exponent(*it,idx) == d)  tmp.push_back(((*it)/Xd));
312 //         CutOff.remove_if(IsDivHack(tmp));
313 //         CutOff.splice(CutOff.end(), tmp);
314 //         QuotientBasisRec(ans, CutOff, prefixXd, idx+1);
315 //       }
316 //     }
317 //   } // anonymous namespace
318 
319 
320 //   std::vector<PPMonoidElem> QuotientBasis(const ideal& I)
321 //   {
322 //     const char* const fn = "QuotientBasis";
323 //     if (!IsSparsePolyRing(RingOf(I))) CoCoA_ERROR(ERR::NotSparsePolyRing, fn);
324 //     if (!IsZeroDim(I)) CoCoA_ERROR("ideal must be 0-dimensional", fn);
325 //     vector<RingElem> GB = GBasis(I);
326 //     std::list<PPMonoidElem> LeadingPPs;
327 //     vector<PPMonoidElem> ans;
328 //     for (long i=0; i < len(GB); ++i)  LeadingPPs.push_back(LPP(GB[i]));
329 //     QuotientBasisRec(ans, LeadingPPs, PPMonoidElem(PPM(RingOf(I))), 0);
330 //     return ans;
331 //   }
332 
333 
334 //   std::vector<PPMonoidElem> QuotientBasisSorted(const ideal& I)
335 //   {
336 //     const char* const fn = "QuotientBasis";
337 //     if (!IsSparsePolyRing(RingOf(I))) CoCoA_ERROR(ERR::NotSparsePolyRing, fn);
338 //     if (!IsZeroDim(I)) CoCoA_ERROR("ideal must be 0-dimensional", fn);
339 //     vector<PPMonoidElem> QB = QuotientBasis(I);
340 //     std::sort(QB.begin(), QB.end());
341 //     return QB;
342 //   }
343 
344 
345 
346 
347 
348   //-- IdealImpl ----------------------------------------
349 
myIdealCtor(const std::vector<RingElem> & gens)350   ideal SparsePolyRingBase::myIdealCtor(const std::vector<RingElem>& gens) const
351   {
352     return ideal(new IdealImpl(SparsePolyRing(this), gens)); //??? ugly ???
353   }
354 
355 
IdealImpl(const SparsePolyRing & P,const std::vector<RingElem> & gens)356   SparsePolyRingBase::IdealImpl::IdealImpl(const SparsePolyRing& P, const std::vector<RingElem>& gens):
357       myP(P),
358       myGensValue(gens),
359       myInvBasisContainerPtr(new Involutive::UniversalInvolutiveBasisContainer(gens)),
360       IhaveGBasisValue(false)
361   {
362     // IhaveMonomialGens3Value = uncertain3; // default for bool3
363     // IhaveSqFreeMonomial3Gens = uncertain3; // default for bool3
364     if (!IsField(CoeffRing(P)))
365       CoCoA_ERROR("ERR:NYI ideal of polynomials with coeffs not in a field", "ideal(SparsePolyRing, gens)");//???
366   }
367 
368 
myClone()369   IdealBase* SparsePolyRingBase::IdealImpl::myClone() const
370   {
371     return new IdealImpl(*this);
372   }
373 
374 
myRing()375   const SparsePolyRing& SparsePolyRingBase::IdealImpl::myRing() const
376   {
377     return myP;
378   }
379 
380 
IamZero()381   bool SparsePolyRingBase::IdealImpl::IamZero() const
382   {
383     for (long i=0; i<len(myGens()); ++i)
384       if (!IsZero(myGens()[i])) return false;
385     return true;
386   }
387 
388 
389 
390   namespace // anonymous --------------------------------
391   {
AreLPPSqFree(const std::vector<RingElem> & v)392     bool AreLPPSqFree(const std::vector<RingElem>& v)
393     {
394       const long n = len(v);
395       for (long i=0; i < n; ++i)
396         if (!IsSqFree(LPP(v[i]))) return false;
397       return true;
398 //   We *DO NOT USE* STL algorithm because std::ptr_fun does not work if the fn has formal params which are of reference type
399 //       return find_if(v.begin(), v.end(),
400 //                      not1(ptr_fun(CoCoA::IsSqFreeLPP)))
401 // 	//                     not1(ptr_fun(static_cast<bool(*)(ConstRefRingElem)>(CoCoA::IsRadLPP))))
402 //         == v.end();
403     }
404 
405     } // anonymous end ----------------------------------
406 
407 
IhaveGBasis()408   bool SparsePolyRingBase::IdealImpl::IhaveGBasis() const
409   { return IhaveGBasisValue; }
410 
411 
IhaveMonomialGens()412   bool SparsePolyRingBase::IdealImpl::IhaveMonomialGens() const
413   {
414     if (IsUncertain3(IhaveMonomialGens3Value))
415       IhaveMonomialGens3Value = AreMonomials(myGensValue);
416     return IsTrue3(IhaveMonomialGens3Value);
417   }
418 
419 
IhaveSqFreeMonomialGens()420   bool SparsePolyRingBase::IdealImpl::IhaveSqFreeMonomialGens() const
421   {
422     if (IsUncertain3(IhaveSqFreeMonomialGens3Value))
423     {
424       if (!IhaveMonomialGens()) IhaveSqFreeMonomialGens3Value = false3;
425       else IhaveSqFreeMonomialGens3Value = AreLPPSqFree(myGensValue);
426     }
427     return IsTrue3(IhaveSqFreeMonomialGens3Value);
428   }
429 
430 
mySetGBasisAsGens()431   void SparsePolyRingBase::IdealImpl::mySetGBasisAsGens() const
432   {
433     myGBasisValue = myGensValue;
434     IhaveGBasisValue = true;
435   }
436 
437 
myReset()438   void SparsePolyRingBase::IdealImpl::myReset() const
439   {
440     IamMaximal3Flag = uncertain3;
441     IamPrimary3Flag = uncertain3;
442     IamPrime3Flag = uncertain3;
443     IamRadical3Flag = uncertain3;
444     IhaveSqFreeMonomialGens3Value = uncertain3;
445     IhaveMonomialGens3Value = uncertain3;
446     IhaveGBasisValue = false;
447     myGBasisValue.clear();
448     myMinGensValue.clear();
449   }
450 
451 
myTestIsMaximal()452   void SparsePolyRingBase::IdealImpl::myTestIsMaximal() const
453   {
454     if (IamZero()) { myAssignMaximalFlag(false); return; }// <0> in K[X]
455     if (!IsField(CoeffRing(myP)))
456       CoCoA_ERROR(ERR::ExpectedCoeffsInField, "myTestIsMaximal()");//???
457     if (NumIndets(myP) == 1)  // univariate poly ring
458     { myAssignMaximalFlag(IsIrred(myGBasis(NoCpuTimeLimit())[0])); return; }
459     if (IamZeroDim())
460       myTestIsMaximal_0dim(); // assigns flags
461     else
462       myAssignMaximalFlag(false);
463   }
464 
465 
myTestIsPrimary()466   void SparsePolyRingBase::IdealImpl::myTestIsPrimary() const
467   {
468     //    std::cout << "gens" << myGensValue << std::endl;
469     if (!IsField(CoeffRing(myP)))
470       CoCoA_ERROR(ERR::ExpectedCoeffsInField, "myTestIsPrimary()");//???
471     if (NumIndets(myP) == 1)  // univariate poly ring
472     {
473       const factorization<RingElem> F = factor(myGBasis(NoCpuTimeLimit())[0]); // PID
474       myAssignPrimaryFlag(len(F.myFactors()) == 1);
475       if (IamPrimary())
476         myAssignMaximalFlag(F.myMultiplicities()[0] == 1); // since we have the info
477       return;
478     }
479     if (!IamZeroDim())
480       CoCoA_ERROR("Not Yet Implemented for general ideals", "myTestIsPrimary");
481     myTestIsPrimary_0dim();
482   }
483 
484 
myTestIsPrime()485   void SparsePolyRingBase::IdealImpl::myTestIsPrime() const
486   {
487     if (NumIndets(myP) == 1 && IsField(CoeffRing(myP)))
488     { myTestIsMaximal(); return; }
489     CoCoA_ERROR(ERR::NYI, "SparsePolyRingBase::IdealImpl::myTestIsPrime()");//???
490   }
491 
492 
myTestIsRadical()493   void SparsePolyRingBase::IdealImpl::myTestIsRadical() const
494   {
495     if (!IsField(CoeffRing(myP)))
496       CoCoA_ERROR(ERR::ExpectedCoeffsInField, "myTestIsRadical()");//???
497     if (IhaveMonomialGens()) { myTestIsRadical_MonId(); return; }
498     if (NumIndets(myP) == 1)  // univariate poly ring
499     {
500       const factorization<RingElem> F = factor(myGBasis(NoCpuTimeLimit())[0]); // PID
501       if (len(F.myFactors()) != 1) myAssignPrimeFlag(false);
502       if (F.myMultiplicities()[0] == 1) myAssignMaximalFlag(true);
503       return;
504     }
505     if (!IamZeroDim())
506       CoCoA_ERROR("Not Yet Implemented for general ideals", "myTestIsRadical");
507     myTestIsRadical_0dim();
508   }
509 
510 
myReduceMod(RingElemRawPtr rawf)511   void SparsePolyRingBase::IdealImpl::myReduceMod(RingElemRawPtr rawf) const
512   {
513     //??? very basic default implementation
514     RingElem tmp = NR(RingElemAlias(myP, rawf), myGBasis(NoCpuTimeLimit()));
515     myP->mySwap(rawf, raw(tmp));
516   }
517 
518 
IhaveElem(RingElemConstRawPtr rawf)519   bool SparsePolyRingBase::IdealImpl::IhaveElem(RingElemConstRawPtr rawf) const
520   {
521     RingElem g = RingElemAlias(myP, rawf);
522     myReduceMod(raw(g));
523     return IsZero(g);
524   }
525 
526 
IamZeroDim()527   bool SparsePolyRingBase::IdealImpl::IamZeroDim() const
528   {
529     const vector<RingElem>& GB = myTidyGens(NoCpuTimeLimit());
530     const long GBlen = len(GB);
531     const int nvars = NumIndets(myRing());
532     vector<bool> AlreadySeen(nvars);
533     int NumIndetPowers = 0;
534     long index; BigInt IgnoreExp; // for rtn vals from IsIndetPosPower
535     for (long i=0; i < GBlen; ++i)
536     {
537       if (IsIndetPosPower(index, IgnoreExp, LPP(GB[i])) && !AlreadySeen[index])
538       {
539         AlreadySeen[index] = true;
540         if (++NumIndetPowers == nvars) return true;
541       }
542     }
543     return false;
544   }
545 
546 
ourGetPtr(const ideal & I)547   const SparsePolyRingBase::IdealImpl* SparsePolyRingBase::IdealImpl::ourGetPtr(const ideal& I)
548   {
549     return dynamic_cast<const SparsePolyRingBase::IdealImpl*>(I.myIdealPtr());
550   }
551 
552 
myAdd(const ideal & Jin)553   void SparsePolyRingBase::IdealImpl::myAdd(const ideal& Jin)
554   {
555     const IdealImpl* const J = ourGetPtr(Jin);
556     if (IsZero(Jin)) return;
557     myGensValue.insert(myGensValue.end(), gens(Jin).begin(), gens(Jin).end());
558     bool3 IhaveMG_old = IhaveMonomialGens3Value;
559     bool3 IhaveSFMG_old = IhaveSqFreeMonomialGens3Value;
560     myReset();
561     // we can recover some info about monomial gens:
562     IhaveMonomialGens3Value = IhaveMG_old;
563     IhaveSqFreeMonomialGens3Value = IhaveSFMG_old;
564     if (IsTrue3(IhaveMonomialGens3Value))
565       IhaveMonomialGens3Value = J->IhaveMonomialGens3Value;
566     if (IsTrue3(IhaveSqFreeMonomialGens3Value))
567       IhaveSqFreeMonomialGens3Value = J->IhaveSqFreeMonomialGens3Value;
568   }
569 
570 
myMul(const ideal & Jin)571   void SparsePolyRingBase::IdealImpl::myMul(const ideal& Jin)
572   {
573     if (IhaveMonomialGens() && AreGensMonomial(Jin))
574     {
575       myMul_MonId(Jin);
576       return;
577     }
578     vector<RingElem> tmpV;
579     const SparsePolyRingBase::IdealImpl* const J = ourGetPtr(Jin);
580     for (const auto& gI: myGensValue)
581       for (const auto& gJ: J->myGensValue)  tmpV.push_back(gI*gJ);
582     swap(tmpV, myGensValue);  // ANNA does this make copies???  2010-02-03
583     myReset(); // can we recover some info?
584   }
585 
586 
myIntersect(const ideal & J)587   void SparsePolyRingBase::IdealImpl::myIntersect(const ideal& J)
588   {
589     if (IamZero()) return;
590     CoCoA_ASSERT(!IsZero(J));
591     if (IhaveMonomialGens() && AreGensMonomial(J))
592     {
593       myIntersect_MonId(J);
594       return;
595     }
596     ComputeIntersection(myGensValue, myGensValue, gens(J));
597     myReset(); // can we recover some info?
598   }
599 
600 
myColon(const ideal & J)601   void SparsePolyRingBase::IdealImpl::myColon(const ideal& J)
602   {
603     if (IsZero(J))
604       myGensValue = vector<RingElem>(1, one(myRing()));
605     else
606     {
607       if (IhaveMonomialGens() && AreGensMonomial(J))
608       {
609         myColon_MonId(J);
610         return;
611       }
612       const RingElem Z(zero(myRing()));
613       myGensValue.erase(remove(myGensValue.begin(), myGensValue.end(),Z),
614                         myGensValue.end());
615       ComputeColon(myGensValue, myGensValue, gens(J));
616     }
617     myReset(); // can we recover some info?
618   }
619 
620 
mySaturate(const ideal & J)621   void SparsePolyRingBase::IdealImpl::mySaturate(const ideal& J)
622   {
623     ComputeSaturation(myGensValue, myGensValue, gens(J));
624     myReset();
625   }
626 
627 
myMinimalize()628   void SparsePolyRingBase::IdealImpl::myMinimalize()
629   {
630     if (GradingDim(myRing())==0 || !IsHomog(myGensValue))
631       CoCoA_ERROR("Input is not homogeneous", "myMinimalize");
632     myGBasis(NoCpuTimeLimit()); // this sets GBasis and MinGens
633     myGensValue = myMinGens(); // if monomial ideal min gens are in GBasis
634     if (IsFalse3(IhaveMonomialGens3Value))
635       IhaveMonomialGens3Value = uncertain3;
636     if (IsFalse3(IhaveSqFreeMonomialGens3Value))
637       IhaveSqFreeMonomialGens3Value = uncertain3;
638   }
639 
640 
myElim(const std::vector<RingElem> & ElimIndets)641   void SparsePolyRingBase::IdealImpl::myElim(const std::vector<RingElem>& ElimIndets)
642   {
643     //    if (IhaveGBasisValue) and elim ordering ...
644     if (IhaveMonomialGens())
645     {
646       myElim_MonId(ElimIndets);
647       return;
648     }
649     const RingElem Z(zero(myRing()));
650     myGensValue.erase(remove(myGensValue.begin(), myGensValue.end(),Z),
651                       myGensValue.end());
652     PPMonoidElem ElimIndetsProd(myRing()->myPPM());
653     const long n = len(ElimIndets);
654     for (long i=0 ; i<n ; ++i)
655     {
656       if (!IsIndet(ElimIndets[i]))
657         CoCoA_ERROR(ERR::NotIndet, "myElim");
658       ElimIndetsProd *= LPP(ElimIndets[i]);
659     }
660     ComputeElim(myGensValue, myGensValue, ElimIndetsProd);
661     myReset(); // can we recover some info?
662   }
663 
664 
665   namespace {  // anonymous ------------------------------
CoeffOfTermSparse(ConstRefRingElem f,ConstRefPPMonoidElem pp)666     RingElem CoeffOfTermSparse(ConstRefRingElem f, ConstRefPPMonoidElem pp)
667     {
668       for (SparsePolyIter itf=BeginIter(f); !IsEnded(itf); ++itf)
669         if (PP(itf) == pp) return coeff(itf);
670       return zero(CoeffRing(owner(f)));
671     }
672 
MultiplicationMat(ConstRefRingElem f,const ideal & I)673     matrix MultiplicationMat(ConstRefRingElem f, const ideal& I)
674     {
675       std::vector<PPMonoidElem> QB = QuotientBasis(I);
676       SparsePolyRing P = owner(f);
677       matrix Mf = NewDenseMat(CoeffRing(P), len(QB), len(QB));
678       for (long j=0; j<len(QB); ++j)
679       {
680         RingElem tmpf = f;
681         P->myMulByPP(raw(tmpf), raw(QB[j]));
682         tmpf = NF(tmpf, I);
683         for (long i=0; i<len(QB); ++i)
684           SetEntry(Mf,i,j, CoeffOfTermSparse(tmpf,QB[i]));
685       }
686       return Mf;
687     }
688 
689   } // anonymous end -------------------------------------------
690 
691 
myDivMod(RingElemRawPtr rawlhs,RingElemConstRawPtr rawnum,RingElemConstRawPtr rawden)692   bool SparsePolyRingBase::IdealImpl::myDivMod(RingElemRawPtr rawlhs, RingElemConstRawPtr rawnum, RingElemConstRawPtr rawden) const
693   {
694 // check for IsZeroDivisor(den) is done by operator/
695     const SparsePolyRing P = myRing();
696     //    if (IsField(CoeffRing(P)) && P->myIsConstant(rawden))
697     if (P->myIsConstant(rawden))
698     {
699       RingElem GDivF = RingElemAlias(P, rawnum);
700       P->myDivByCoeff(raw(GDivF), raw(P->myLC(rawden))); // exc safe?
701       P->mySwap(rawlhs, raw(GDivF));
702       return true;
703     }
704     if (IamZeroDim())
705     {
706       ideal I = ideal(const_cast<IdealImpl*>(this)); // Tappullus Horribilis
707       std::vector<PPMonoidElem> QB = QuotientBasis(I);
708       long LenQB = len(QB);
709       RingElem G = RingElemAlias(P,rawnum);
710       RingElem F = RingElemAlias(P,rawden);
711       matrix coeffsG = NewDenseMat(ZeroMat(CoeffRing(P), len(QB), 1));
712       for (long i=0; i<LenQB; ++i)
713         SetEntry(coeffsG,i,0, CoeffOfTermSparse(G, QB[i]));
714       matrix coeffsGDivF = LinSolve(MultiplicationMat(F,I), coeffsG);
715       RingElem GDivF(P);
716       for (long i=0; i<LenQB; ++i)
717         GDivF += monomial(P, coeffsGDivF(i,0), QB[i]);
718       P->mySwap(rawlhs, raw(GDivF));
719       return true;
720     }
721 
722 // The following should be a general solution...
723 ///    auto tmp = GenRepr(rawnum, ideal(rawden)+this);
724 ///    return tmp[0];
725 
726     CoCoA_ERROR(ERR::NYI, "SparsePolyRingBase::IdealImpl::myDivMod");
727     return false; // just to keep the compiler quiet!!
728   }
729 
730 
731 
732 
myGBasis(const CpuTimeLimit & CheckForTimeOut)733   const std::vector<RingElem>& SparsePolyRingBase::IdealImpl::myGBasis(const CpuTimeLimit& CheckForTimeOut) const
734   {
735     if (IhaveGBasis()) return myGBasisValue;
736     if (IhaveMonomialGens()) return myGBasis_MonId();
737     //CoCoA_ASSERT(myGBasisValue.empty()); // false for MinGens of points
738     if (IamZero())
739     {
740       CoCoA_ASSERT(myGBasisValue.empty());
741       CoCoA_ASSERT(myMinGensValue.empty());
742     }
743     else
744     {
745       if (len(myGensValue)==1)
746       {
747         myMinGensValue = myGensValue;
748         CoCoA_ASSERT(myGBasisValue.empty());
749         myGBasisValue.push_back(monic(myGensValue[0]));
750       }
751       else
752       {
753         vector<RingElem> MinGens;
754         ComputeGBasis(myGBasisValue, MinGens, myGensValue, CheckForTimeOut);
755         if (!MinGens.empty()) // MinGens is non-empty only if ideal is homog
756           myMinGensValue = MinGens;
757       }
758     }
759     IhaveGBasisValue = true;
760     return myGBasisValue;
761   }
762 
763 
764   namespace { // anonymous
765 
NewPolyRingForHomog(SparsePolyRing P)766     SparsePolyRing NewPolyRingForHomog(SparsePolyRing P)
767     {
768       long n = NumIndets(P);
769       if (IsStdDegRevLex(ordering(PPM(P))))
770         return NewPolyRing(CoeffRing(P), NewSymbols(n+1));
771       if (IsLex(ordering(PPM(P))))
772         return NewPolyRing(CoeffRing(P), NewSymbols(n+1), StdDegLex);
773       if (IsStdDegLex(ordering(PPM(P))))
774       {
775         RingElem I = one(RingZZ());
776         RingElem Z = zero(RingZZ());
777         PPOrdering O =
778           NewMatrixOrdering(MakeTermOrd(BlockMat2x2(
779                                                     RowMat(vector<RingElem>(n,I)),
780                                                     RowMat(vector<RingElem>(1,I)),
781                                                     StdDegLexMat(n),
782                                                     ColMat(vector<RingElem>(n,Z)))),
783                             1);
784         return NewPolyRing(CoeffRing(P), NewSymbols(n+1), O);
785       }
786 
787       // per DegLex bisogna anche ritornare la h (messa al posto opportuno) e gli omomorfismi
788 //       if (IsStdDegLex(ordering(PPM(P))))  ///   NONONO: h must be first.
789 //         return NewPolyRing(CoeffRing(P), NewSymbols(n+1), StdDegLex);
790       CoCoA_ERROR(ERR::NYI, "GBasisByHomog: only for DegRevLex, lex");
791       return P; // senseless, JUST TO KEEP COMPILER QUIET
792     }
793 
794   }
795 
796 
797 namespace { // anonymous
798 
LPPLessThan(const RingElem & f,const RingElem & g)799   bool LPPLessThan(const RingElem& f, const RingElem& g)
800   { return LPP(f) < LPP(g); }
801 
802 } // anonymous namespace
803 
myGBasisByHomog(const CpuTimeLimit & CheckForTimeOut)804   const std::vector<RingElem>& SparsePolyRingBase::IdealImpl::myGBasisByHomog(const CpuTimeLimit& CheckForTimeOut) const
805   {
806     if (IhaveMonomialGens()) return myGBasis_MonId();
807     if (IhaveGBasis()) return myGBasisValue;
808     CoCoA_ASSERT(myGBasisValue.empty());
809     if (IamZero()) return myGBasisValue;
810     // check GradingDim
811     // make correct ordering
812     const SparsePolyRing&  P = myRing();
813     SparsePolyRing Ph = NewPolyRingForHomog(P);
814     const long n = NumIndets(P);
815     const RingElem& h = indet(Ph, n);
816     const std::vector<RingElem>& X = indets(Ph);
817     const RingHom phi =PolyAlgebraHom(P,Ph,vector<RingElem>(X.begin(),X.begin()+n));
818     std::vector<RingElem> v = indets(P);  v.push_back(one(P));
819     const RingHom dehom = PolyAlgebraHom(Ph,P,v);
820     const std::vector<RingElem>& g = myGens();
821     std::vector<RingElem> gh; // use transform here???
822     for (long i=0; i<len(g); ++i)  gh.push_back(homog(phi(g[i]), h));
823     std::vector<RingElem> GB = apply(dehom, GBasis(ideal(gh),CheckForTimeOut));
824     gh.clear();
825     // interreduce GB
826     std::vector<RingElem> GBaux;
827     sort(GB.begin(), GB.end(), LPPLessThan);
828     //    PPVector LT_GB(PPM(P), NewDivMaskEvenPowers());
829     PPWithMask LT_GBi(one(PPM(P)), NewDivMaskEvenPowers());
830     PPVector LT_GB_min(PPM(P), NewDivMaskEvenPowers());
831     for (long i=0; i<len(GB); ++i)
832     {
833       //      PushBack(LT_GB, LPP(GB[i]));
834       LT_GBi = LPP(GB[i]);
835       if (!IsDivisible(LT_GBi, LT_GB_min))
836       {
837         PushBack(LT_GB_min, LT_GBi);
838         GBaux.push_back(monic(NR(GB[i], GBaux)));
839       }
840     }
841     swap(myGBasisValue, GBaux);
842     IhaveGBasisValue = true;
843     return myGBasisValue;
844   }
845 
846 
myGBasisSelfSatCore()847   std::vector<RingElem> SparsePolyRingBase::IdealImpl::myGBasisSelfSatCore() const
848   {
849     if (IhaveMonomialGens()) return myGBasis_MonId();
850     if (IhaveGBasis()) return myGBasisValue;
851     CoCoA_ASSERT(myGBasisValue.empty());
852     if (IamZero()) return myGBasisValue;
853     vector<RingElem> GBSelfSat;
854     ComputeGBasisSelfSatCore(GBSelfSat, myGensValue);
855     return GBSelfSat;
856   }
857 
858 
myGBasisRealSolve()859   std::vector<RingElem> SparsePolyRingBase::IdealImpl::myGBasisRealSolve() const
860   {
861     if (IamZero()) return myGBasisValue;
862     vector<RingElem> GBRealSolve;
863     ComputeGBasisRealSolve(GBRealSolve, myGensValue);
864     return GBRealSolve;
865   }
866 
867 
myMinGens()868   const std::vector<RingElem>& SparsePolyRingBase::IdealImpl::myMinGens() const
869   {
870     if (!myMinGensValue.empty()) return myMinGensValue;
871     if (IhaveMonomialGens()) return myGBasis_MonId(); // interreduced
872     if (GradingDim(myRing())==0 || !IsHomog(myGensValue))
873       CoCoA_ERROR("Input is not homogeneous", "myMinGens");
874     IhaveGBasisValue = false; // force Buchberger algorithm for getting MinGens
875     myGBasis(NoCpuTimeLimit());
876     return myMinGensValue;
877   }
878 
879 
IsZeroDim(const ideal & I)880   bool IsZeroDim(const ideal& I)
881   {
882     if (!IsSparsePolyRing(RingOf(I)))
883       CoCoA_ERROR(ERR::NotSparsePolyRing, "IsZeroDim(I)");
884     if (IsZero(I) || IsOne(I)) return false;
885     // Now we know I is non-trivial.
886 //     const SparsePolyRing P = RingOf(I);
887 //     const vector<RingElem>& GB = TidyGens(I);
888 //     const long GBlen = len(GB); // MUST BE A REDUCED GBASIS !!!
889 //     long NumIndetPowers = 0;
890 //     for (long i=0; i < GBlen; ++i)
891 //       if (IsIndetPosPower(LPP(GB[i])))
892 //         ++NumIndetPowers;
893 //     return (NumIndetPowers == NumIndets(P));
894     return SparsePolyRingBase::IdealImpl::ourGetPtr(I)->IamZeroDim();
895   }
896 
897 
IsHomog(const ideal & I)898   bool IsHomog(const ideal& I)
899   {
900     if (!IsSparsePolyRing(RingOf(I)))
901       CoCoA_ERROR(ERR::NotSparsePolyRing, "IsHomog(ideal)");
902     if (GradingDim(RingOf(I))==0)
903       CoCoA_ERROR(ERR::ZeroGradingDim, "IsHomog(ideal)");
904     if (IsZero(I) || IsOne(I)) return true;
905     // Now we know I is non-trivial.
906     const SparsePolyRing P = RingOf(I);
907     const vector<RingElem>& GB = TidyGens(I);
908     const long GBlen = len(GB); // MUST BE A REDUCED GBASIS !!!
909     for (long i=0; i < GBlen; ++i)
910       if (!IsHomog(GB[i]))  return false;
911     return true;
912   }
913 
914 
DenSigma(const ideal & I)915   RingElem DenSigma(const ideal& I)
916   {
917     if (!IsSparsePolyRing(RingOf(I)))
918       CoCoA_ERROR(ERR::NotSparsePolyRing, "DenSigma(I)");
919     if (!IsFractionField(CoeffRing(RingOf(I))))
920       CoCoA_ERROR("Coeff ring must be a fraction field of a GCDDomain", "DenSigma(I)");
921     return CommonDenom(ReducedGBasis(I));
922   }
923 
924   // template???
IsSigmaGoodPrime(const BigInt & p,const ideal & I)925   bool IsSigmaGoodPrime(const BigInt& p, const ideal& I)
926   {
927     if (!IsSparsePolyRing(RingOf(I)))
928       CoCoA_ERROR(ERR::NotSparsePolyRing, "IsSigmaGoodPrime(p,I)");
929     if (!IsQQ(CoeffRing(RingOf(I))))
930       CoCoA_ERROR("Coeff ring must be RingQQ", "IsSigmaGoodPrime(p,I)");
931     if (!IsPrime(p))
932       CoCoA_ERROR("First argument must be a prime number", "IsSigmaGoodPrime(p,I)");
933     return !IsDivisible(CommonDenom(ReducedGBasis(I)), p);
934   }
935 
936   // template???
IsSigmaGoodPrime(const long p,const ideal & I)937   bool IsSigmaGoodPrime(const long p, const ideal& I)
938   {
939     if (!IsSparsePolyRing(RingOf(I)))
940       CoCoA_ERROR(ERR::NotSparsePolyRing, "IsSigmaGoodPrime(p,I)");
941     if (!IsQQ(CoeffRing(RingOf(I))))
942       CoCoA_ERROR("Coeff ring must be RingQQ", "IsSigmaGoodPrime(p,I)");
943     if (!IsPrime(p))
944       CoCoA_ERROR("First argument must be a prime number", "IsSigmaGoodPrime(p,I)");
945     return !IsDivisible(CommonDenom(ReducedGBasis(I)), p);
946   }
947 
948 
949   //  namespace { // anonymous
radical_0dimDRL(const ideal & I)950     ideal radical_0dimDRL(const ideal& I)
951     {
952       const SparsePolyRingBase::IdealImpl* const ptrI =
953       SparsePolyRingBase::IdealImpl::ourGetPtr(I);
954       return ptrI->myRadical_0dimDRL(); // behaves differently from other memb fns
955     }
956   //  }
957 
958 
959   //namespace { // anonymous ??? vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
radical_0dim(const ideal & I)960   ideal radical_0dim(const ideal& I)
961   {
962     PolyRing P = RingOf(I);
963     //    if (HasStdDegRevLex(P))  return radical_0dimDRL(I);
964     if (HasGBasis(I)) return radical_0dimDRL(I);
965     PolyRing P_drl = NewPolyRing(CoeffRing(P), NewSymbols(NumIndets(P)));
966     RingHom phi = PolyAlgebraHom(P, P_drl, indets(P_drl));
967     RingHom psi = PolyAlgebraHom(P_drl, P, indets(P));
968     ideal RadI = radical_0dimDRL(ideal(apply(phi, gens(I))));
969     return ideal(apply(psi, gens(RadI)));
970   } // radical_0dim(I)
971 
972 
radical_MonId(const ideal & I)973   ideal radical_MonId(const ideal& I)
974   {
975     VerboseLog VERBOSE("radical_MonId");
976     VERBOSE(1000) << " starting " << std::endl;
977     const SparsePolyRingBase::IdealImpl* const ptrI =
978       SparsePolyRingBase::IdealImpl::ourGetPtr(I);
979     return ptrI->myRadical_MonId(); // behaves differently from other memb fns
980   }
981 
982   //}  // ^^^^^ anonymous namespace ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
983 
984 
985 // will be radical(I)
radical_tmp(const ideal & I)986   ideal radical_tmp(const ideal& I)
987   {
988     VerboseLog VERBOSE("radical_tmp");
989     VERBOSE(1000) << " starting " << std::endl;
990     if (IsTrue3(IsRadical3(I))) return I;
991     if (AreGensMonomial(I)) return radical_MonId(I); // monomial ideal
992     if (IsZeroDim(I)) return radical_0dim(I); // 0-dim ideal
993     CoCoA_ERROR(ERR::NYI, "radical_tmp for general poly ideals");
994     return I;  // just to keep compiler quiet
995   } // radical_0dim(I)
996 
997 
998 
999 } // end of namespace CoCoA
1000 
1001 // RCS header/log in the next few lines
1002 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/SparsePolyOps-ideal.C,v 1.44 2020/03/06 18:40:07 abbott Exp $
1003 // $Log: SparsePolyOps-ideal.C,v $
1004 // Revision 1.44  2020/03/06 18:40:07  abbott
1005 // Summary: Added some const
1006 //
1007 // Revision 1.43  2020/03/06 16:38:48  bigatti
1008 // -- added GBasisByHomog with DegLex
1009 //
1010 // Revision 1.42  2020/02/26 15:29:15  bigatti
1011 // -- commented out ASSERT for GBasis (called by MinGens redmine#1420)
1012 //
1013 // Revision 1.41  2020/02/14 09:01:10  bigatti
1014 // -- removed typo
1015 //
1016 // Revision 1.40  2020/02/14 08:58:52  bigatti
1017 // -- mingens: for gbasis computation with Buchberger,
1018 //    if myMinGensValue not set (IdealOfProjectivePoints)
1019 //
1020 // Revision 1.39  2020/02/13 14:01:23  bigatti
1021 // -- now using auto in for loops
1022 //
1023 // Revision 1.38  2020/02/12 10:27:38  bigatti
1024 // -- improved myAssignBLAHFlag
1025 //
1026 // Revision 1.37  2020/02/12 09:42:17  abbott
1027 // Summary: Corrected defn of myTestIsPrimary
1028 //
1029 // Revision 1.36  2020/02/12 09:01:47  bigatti
1030 // -- changed myTestIsMaximal etc to return void (and consequences)
1031 //
1032 // Revision 1.35  2020/01/26 14:37:24  abbott
1033 // Summary: Removed useless include (of NumTheory)
1034 //
1035 // Revision 1.34  2020/01/13 17:42:38  bigatti
1036 // -- minor change in GBasisByHomog
1037 //
1038 // Revision 1.33  2019/12/28 17:54:50  abbott
1039 // Summary: New defn of IamZeroDim now works with any GB (previous reqd minGB)
1040 //
1041 // Revision 1.32  2019/12/27 17:42:31  bigatti
1042 // -- fixed interreduction in GBasisByHomog
1043 // -- IsZeroDim --> IamZeroDim in member functions
1044 //
1045 // Revision 1.31  2019/10/21 16:40:46  bigatti
1046 // -- added VERBOSE(1000) for some functions (to see if they are called)
1047 //
1048 // Revision 1.30  2019/10/15 12:57:55  bigatti
1049 // -- renamed files for ideals
1050 //
1051 // Revision 1.29  2019/10/03 14:54:37  bigatti
1052 // -- added radical_MonId
1053 //
1054 // Revision 1.28  2019/10/02 10:40:47  bigatti
1055 // -- minor change in view of adding optimized radical for MonomialIdeals
1056 //
1057 // Revision 1.27  2019/09/27 14:56:55  abbott
1058 // Summary: Fixed redmine 1322; some cleaning
1059 //
1060 // Revision 1.26  2019/09/27 14:44:06  abbott
1061 // Summary: Corrected use of empty inside CoCoA_ASSERT
1062 //
1063 // Revision 1.25  2019/09/25 16:04:19  bigatti
1064 // -- gbasis for principal ideals now just computes monic(f)
1065 // -- added radical_tmp, checking the implemented cases (will become radical)
1066 //
1067 // Revision 1.24  2019/03/04 11:14:04  abbott
1068 // Summary: Added "just to keep compiler quiet"
1069 //
1070 // Revision 1.23  2018/12/17 15:21:41  bigatti
1071 // -- timeout in GBasisByHomog
1072 //
1073 // Revision 1.22  2018/09/28 15:54:04  abbott
1074 // Summary: Removed pseudo-ctors NewPolyRing which took just num of indets; now must specify their names
1075 //
1076 // Revision 1.21  2018/08/06 09:38:29  bigatti
1077 // -- renamed GBasisViaHomog --> GBasisByHomog
1078 //
1079 // Revision 1.20  2018/08/06 08:57:48  bigatti
1080 // -- added timeout for GBasisByHomog
1081 // -- now using GBasisByHomog in IsPrimary and radical
1082 //
1083 // Revision 1.19  2018/08/05 16:31:25  bigatti
1084 // -- added GBasisByHomog
1085 //
1086 // Revision 1.18  2018/06/27 12:15:19  abbott
1087 // Summary: Renamed RealSolveCore to RealSolve
1088 //
1089 // Revision 1.17  2018/06/27 08:50:39  abbott
1090 // Summary: Revised to work with new CpuTimeLimit
1091 //
1092 // Revision 1.16  2018/05/25 09:24:46  abbott
1093 // Summary: Major redesign of CpuTimeLimit (many consequences)
1094 //
1095 // Revision 1.15  2018/05/18 12:23:50  bigatti
1096 // -- renamed IntOperations --> BigIntOps
1097 //
1098 // Revision 1.14  2018/05/17 15:49:00  bigatti
1099 // -- sorted #includes
1100 // -- renamed MatrixOperations --> MatrixOps
1101 //
1102 // Revision 1.13  2018/04/18 15:39:34  abbott
1103 // Summary: Added missing return in NYI fn.
1104 //
1105 // Revision 1.12  2018/04/16 21:49:26  bigatti
1106 // -- added IamZeroDim
1107 // -- added myPrimaryDecomposition_0dim
1108 //
1109 // Revision 1.11  2018/04/10 14:59:32  bigatti
1110 // -- now member function for PrimaryDecomposition
1111 //
1112 // Revision 1.10  2018/04/10 14:51:43  bigatti
1113 // -- added virtual myPrimaryDecomposition (with default implementation)
1114 //
1115 // Revision 1.9  2018/04/10 14:20:47  bigatti
1116 // -- fixed includes
1117 //
1118 // Revision 1.8  2018/04/09 16:25:53  bigatti
1119 // -- functions for zer-dim ideals moved into SparsePolyOps-IdealZeroDim
1120 //
1121 // Revision 1.7  2018/04/06 17:28:22  bigatti
1122 // -- fixed includes
1123 //
1124 // Revision 1.6  2018/04/04 12:36:51  bigatti
1125 // -- radical: returning I itself, in IsRadical3 = true
1126 //
1127 // Revision 1.5  2018/03/29 13:09:04  bigatti
1128 // -- improved isprimary (with gbasis timeout)
1129 //
1130 // Revision 1.4  2018/03/29 09:36:40  bigatti
1131 // -- added member functions myTestIsRadical, myTestIsPrimary and flags
1132 //
1133 // Revision 1.3  2018/03/20 11:48:12  bigatti
1134 // -- new code for 0dim ideals (radical, primary...)
1135 //
1136 // Revision 1.2  2018/03/15 14:18:06  bigatti
1137 // -- added files SparsePolyOps-ideal.H and SparsePolyOps-involutive.H
1138 //
1139 // Revision 1.1  2018/03/12 14:38:41  bigatti
1140 // -- renamed SparsePoly-ideal/involutive into SparsePolyOps-ideal/involutive
1141 //
1142 // Revision 1.3  2018/03/09 14:54:01  bigatti
1143 // -- removed useless includes
1144 //
1145 // Revision 1.2  2018/02/27 17:26:07  bigatti
1146 // -- split off involutive part
1147 //
1148 // Revision 1.1  2018/02/27 17:12:37  bigatti
1149 // -- Renamed SparsePolyRing_ideal.C --> SparsePoly-ideal.C
1150 //
1151