1 //   Copyright (c)  2004-2011  John Abbott
2 
3 //   This file is part of the source of CoCoALib, the CoCoA Library.
4 
5 //   CoCoALib is free software: you can redistribute it and/or modify
6 //   it under the terms of the GNU General Public License as published by
7 //   the Free Software Foundation, either version 3 of the License, or
8 //   (at your option) any later version.
9 
10 //   CoCoALib is distributed in the hope that it will be useful,
11 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //   GNU General Public License for more details.
14 
15 //   You should have received a copy of the GNU General Public License
16 //   along with CoCoALib.  If not, see <http://www.gnu.org/licenses/>.
17 
18 
19 // Implementation of class PPMonoidEvImpl
20 
21 #include "CoCoA/PPMonoidEv.H"
22 
23 #include "CoCoA/BigIntOps.H"
24 #include "CoCoA/DivMask.H"
25 #include "CoCoA/MemPool.H"
26 #include "CoCoA/PPMonoid.H"
27 #include "CoCoA/PPOrdering.H"
28 #include "CoCoA/assert.H"
29 #include "CoCoA/convert.H"
30 #include "CoCoA/degree.H"
31 #include "CoCoA/error.H"
32 #include "CoCoA/matrix.H"
33 #include "CoCoA/symbol.H"
34 
35 #include <algorithm>
36 using std::min;
37 using std::max;
38 //using std::swap;
39 #include <cstring>
40 using std::memcpy;
41 #include <iostream>
42 using std::ostream;
43 #include<limits>
44 using std::numeric_limits;
45 #include <memory>
46 using std::unique_ptr;
47 #include <vector>
48 using std::vector;
49 
50 
51 namespace CoCoA
52 {
53 
54   /*-- class PPMonoidEvSmallExpImpl ---------------------------------------*/
55   /*-- class PPMonoidEvImpl ---------------------------------------*/
56   /**
57 
58   \brief Implementation power product monoid with exponent vector
59 
60   PPMonoidEvSmallExpImpl implements a power product monoid for safe testing.
61   It stores the exponents as a C vector of SmallExponent_t.
62   It is not designed to be efficient (but it might be ;-)
63 
64   */
65   /*-----------------------------------------------------------------*/
66 
67   class PPMonoidEvSmallExpImpl: public PPMonoidBase
68   {
69     typedef PPMonoidElemRawPtr RawPtr;           // just to save typing
70     typedef PPMonoidElemConstRawPtr ConstRawPtr; // just to save typing
71 
72     static const unsigned long ourMaxExp;        // defined below; value is just numeric_limits<SmallExponent_t>::max()
73 
74     class CmpBase
75     {
76     public:
77       CmpBase(long NumIndets, long GradingDim);
78       virtual ~CmpBase();
79     public:
80       virtual int myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const =0;
81       virtual void myWDeg(degree& d, const SmallExponent_t* v) const =0;
82       //      virtual int myCmpWDeg(const SmallExponent_t* v1, const SmallExponent_t* v2) const =0;
83       virtual int myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long) const =0;
myCmpWDeg(const SmallExponent_t * v1,const SmallExponent_t * v2)84       int myCmpWDeg(const SmallExponent_t* v1, const SmallExponent_t* v2) const { return myCmpWDegPartial(v1, v2, myGradingDim); }
85 
86     protected:
87       long myNumIndets;
88       long myGradingDim;
89     };
90 
91     class LexImpl: public CmpBase
92     {
93     public:
94       LexImpl(long NumIndets);
95       virtual int myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const;
96       virtual void myWDeg(degree& d, const SmallExponent_t* v) const;
97       virtual int myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long) const;
98     };
99 
100 
101     class StdDegLexImpl: public CmpBase
102     {
103     public:
104       StdDegLexImpl(long NumIndets);
105       virtual int myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const;
106       virtual void myWDeg(degree& d, const SmallExponent_t* v) const;
107       virtual int myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long) const;
108     };
109 
110 
111     class StdDegRevLexImpl: public CmpBase
112     {
113     public:
114       StdDegRevLexImpl(long NumIndets);
115       virtual int myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const;
116       virtual void myWDeg(degree& d, const SmallExponent_t* v) const;
117       virtual int myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long) const;
118     };
119 
120 
121     class MatrixOrderingImpl: public CmpBase
122     {
123     public:
124       MatrixOrderingImpl(long NumIndets, long GradingDim, const ConstMatrixView& OrderMatrix);
125       virtual int myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const;
126       virtual void myWDeg(degree& d, const SmallExponent_t* v) const;
127       virtual int myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long) const;
128     private:
129       std::vector< std::vector<BigInt> > myOrderMatrix;
130     };
131 
132 
133   public:
134     PPMonoidEvSmallExpImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord);
135     ~PPMonoidEvSmallExpImpl();
136   private: // disable copy ctor and assignment
137     explicit PPMonoidEvSmallExpImpl(const PPMonoidEvSmallExpImpl& copy);  // NEVER DEFINED -- copy ctor disabled
138     PPMonoidEvSmallExpImpl& operator=(const PPMonoidEvSmallExpImpl& rhs); // NEVER DEFINED -- assignment disabled
139 
140   public:
141     void contents() const; // FOR DEBUGGING ONLY
142 
143     const std::vector<PPMonoidElem>& myIndets() const;               ///< std::vector whose n-th entry is n-th indet as PPMonoidElem
144 
145     // The functions below are operations on power products owned by PPMonoidEvSmallExpImpl
146     const PPMonoidElem& myOne() const;
147     using PPMonoidBase::myNew;    // disable warnings of overloading
148     PPMonoidElemRawPtr myNew() const;                                ///< ctor from nothing
149     PPMonoidElemRawPtr myNew(PPMonoidElemConstRawPtr rawpp) const;   ///< ctor by assuming ownership
150     PPMonoidElemRawPtr myNew(const std::vector<long>& expv) const;   ///< ctor from exp vector
151     void myDelete(RawPtr rawpp) const;                               ///< dtor, frees pp
152     void mySwap(RawPtr rawpp1, RawPtr rawpp2) const;                 ///< swap(pp1, pp2);
153     void myAssignOne(RawPtr rawpp) const;                            ///< pp = 1
154     void myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const;           ///< p = pp1
155     void myAssign(RawPtr rawpp, const std::vector<long>& expv) const;///< pp = expv (assign from exp vector, all exps >= 0)
156 
157     void myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = pp1*pp2
158     using PPMonoidBase::myMulIndetPower;    // disable warnings of overloading
159     void myMulIndetPower(RawPtr rawpp, long indet, long exp) const;           ///< pp *= indet^exp, assumes exp >= 0
160     void myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = pp1/pp2
161     void myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1/gcd(pp1,pp2)
162     void myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = gcd(pp1,pp2)
163     void myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = lcm(pp1,pp2)
164     void myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const;                   ///< pp = radical(pp1)
165     void myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long exp) const;   ///< pp = pp1^exp, assumes exp >= 0
166     void myPowerOverflowCheck(ConstRawPtr rawpp1, long exp) const;            ///< throw if pp1^exp would overflow, assumes exp >= 0
167 
168 
169     bool myIsOne(ConstRawPtr rawpp) const;                                   ///< is pp = 1?
170     bool myIsIndet(long& index, ConstRawPtr rawpp) const;                    ///< true iff pp is an indet
171     bool myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;          ///< are pp1 & pp2 coprime?
172     bool myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;            ///< is pp1 equal to pp2?
173     bool myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;        ///< does pp2 divide pp1?
174     bool myIsSqFree(ConstRawPtr rawpp) const;                                ///< is pp equal to its radical?
175 
176     int myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;                 ///< -1,0,1 as pp1 < = > pp2
177     long myStdDeg(ConstRawPtr rawpp) const;                                  ///< standard degree of pp
178     void myWDeg(degree& d, ConstRawPtr rawpp) const;                         ///< d = grading(pp)
179     int myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;             ///< <0, =0, >0 as wdeg(pp1) < = > wdeg(pp2)
180     int myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long) const; ///< as myCmpWDeg wrt the first weights
181     long myExponent(ConstRawPtr rawpp, long indet) const;                    ///< exponent of indet in pp
182     void myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const;    ///< EXP = exponent of indet in pp
183     void myExponents(std::vector<long>& expv, ConstRawPtr rawpp) const;      ///< expv[i] = exponent(pp,i)
184     void myBigExponents(std::vector<BigInt>& v, ConstRawPtr rawpp) const;    ///< get exponents, SHOULD BE myExponents ???
185     void myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const;          ///< v[i] = true if i-th indet has exponent != 0
186     void myOutputSelf(std::ostream& out) const;                              ///< out << PPM
187     // INHERITED DEFINITION of virtual  void myOutput(std::ostream& out, ConstRawPtr rawpp) const;
188     void myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const;           ///< print pp in debugging format???
189 
190 
191   private: // auxiliary functions
192     SmallExponent_t* myExpv(RawPtr) const;
193     const SmallExponent_t* myExpv(ConstRawPtr) const;
194 
195     void myComputeDivMask(DivMask& dm, const DivMaskRule& DivMaskImpl, ConstRawPtr rawpp) const; ///< used by PPWithMask
196     bool myCheckExponents(const std::vector<long>& expv) const;
197 
198   private: // data members
199     ///@name Class members
200     //@{
201     const long myEntrySize;       ///< size in ?bytes???
202     mutable MemPool myMemMgr;     // IMPORTANT: this must come *before* myIndetVector and myOnePtr.
203     vector<PPMonoidElem> myIndetVector; ///< the indets as PPMonoidElems
204     unique_ptr<CmpBase> myOrdPtr;         ///< actual implementation of the ordering [should be const???]
205     unique_ptr<PPMonoidElem> myOnePtr;
206     //@}
207   };
208 
209   // static variable
210   const unsigned long PPMonoidEvSmallExpImpl::ourMaxExp = numeric_limits<SmallExponent_t>::max();
211 
212 
213   // dtor not inline for some compiler (?) on PPC
~CmpBase()214   PPMonoidEvSmallExpImpl::CmpBase::~CmpBase() {}
215 
216 
217   // File local inline functions
218 
myExpv(RawPtr rawpp)219   inline SmallExponent_t* PPMonoidEvSmallExpImpl::myExpv(RawPtr rawpp) const
220   {
221     return static_cast<SmallExponent_t*>(rawpp.myRawPtr());
222   }
223 
224 
myExpv(ConstRawPtr rawpp)225   inline const SmallExponent_t* PPMonoidEvSmallExpImpl::myExpv(ConstRawPtr rawpp) const
226   {
227     return static_cast<const SmallExponent_t*>(rawpp.myRawPtr());
228   }
229 
230 
myCheckExponents(const std::vector<long> & expv)231   bool PPMonoidEvSmallExpImpl::myCheckExponents(const std::vector<long>& expv) const
232   {
233     // Check expv.size == myNumIndets.
234     // Check exps are non-neg and not too big.
235     if (len(expv) != myNumIndets) return false;
236     for (long i=0; i < myNumIndets; ++i)
237       if (expv[i] < 0 || static_cast<unsigned long>(expv[i]) > numeric_limits<SmallExponent_t>::max()) return false;
238     return true;
239   }
240 
241 
242   //----   Constructors & destructor   ----//
243 
PPMonoidEvSmallExpImpl(const std::vector<symbol> & IndetNames,const PPOrdering & ord)244   PPMonoidEvSmallExpImpl::PPMonoidEvSmallExpImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord):
245       PPMonoidBase(ord, IndetNames),
246       myEntrySize(sizeof(SmallExponent_t)*myNumIndets),
247       myMemMgr(myEntrySize, "PPMonoidEvSmallExpImpl.myMemMgr"),
248       myIndetVector()
249   {
250     // Put the correct implementation in myOrdPtr...  [VERY UGLY CODE!!!]
251     if (IsLex(ord))
252       myOrdPtr.reset(new LexImpl(myNumIndets));
253     else if (IsStdDegLex(ord))
254       myOrdPtr.reset(new StdDegLexImpl(myNumIndets));
255     else if (IsStdDegRevLex(ord))
256       myOrdPtr.reset(new StdDegRevLexImpl(myNumIndets));
257     else
258       myOrdPtr.reset(new MatrixOrderingImpl(myNumIndets, GradingDim(ord), OrdMat(ord)));
259 
260     myRefCountInc();  // this is needed for exception cleanliness, in case one of the lines below throws
261     myOnePtr.reset(new PPMonoidElem(PPMonoid(this)));
262     {
263       // IMPORTANT: this block destroys pp *before* the call to myRefCountZero.
264       PPMonoidElem pp(PPMonoid(this));
265       vector<long> expv(myNumIndets);
266       for (long i=0; i < myNumIndets; ++i)
267       {
268         expv[i] = 1;
269         myAssign(raw(pp), expv);
270         myIndetVector.push_back(pp);
271         expv[i] = 0;
272       }
273     }
274     myRefCountZero();
275   }
276 
277 
~PPMonoidEvSmallExpImpl()278   PPMonoidEvSmallExpImpl::~PPMonoidEvSmallExpImpl()
279   {}
280 
281 /////////////////////////////////////////////////////////////////////////////
282 
283 
284 
myIndets()285   const std::vector<PPMonoidElem>& PPMonoidEvSmallExpImpl::myIndets() const
286   {
287     return myIndetVector;
288   }
289 
290 
myOne()291   const PPMonoidElem& PPMonoidEvSmallExpImpl::myOne() const
292   {
293     return *myOnePtr;
294   }
295 
296 
myNew()297   PPMonoidElemRawPtr PPMonoidEvSmallExpImpl::myNew() const
298   {
299     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
300     myAssignOne(rawpp); // cannot throw
301     return rawpp;
302   }
303 
myNew(PPMonoidElemConstRawPtr rawcopypp)304   PPMonoidElemRawPtr PPMonoidEvSmallExpImpl::myNew(PPMonoidElemConstRawPtr rawcopypp) const
305   {
306     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
307     myAssign(rawpp, rawcopypp); // cannot throw
308     return rawpp;
309   }
310 
311 
myNew(const std::vector<long> & expv)312   PPMonoidElemRawPtr PPMonoidEvSmallExpImpl::myNew(const std::vector<long>& expv) const
313   {
314     CoCoA_ASSERT(myCheckExponents(expv));
315     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
316     myAssign(rawpp, expv); // cannot throw
317     return rawpp;
318   }
319 
320 
myAssignOne(RawPtr rawpp)321   void PPMonoidEvSmallExpImpl::myAssignOne(RawPtr rawpp) const
322   {
323     SmallExponent_t* const expv = myExpv(rawpp);
324     for (long i = 0; i < myNumIndets; ++i)
325       expv[i] = 0;
326   }
327 
328 
myAssign(RawPtr rawpp,ConstRawPtr rawpp1)329   void PPMonoidEvSmallExpImpl::myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const
330   {
331     if (rawpp == rawpp1) return;
332 
333 //     SmallExponent_t* const expv = myExpv(rawpp);
334 //     const SmallExponent_t* const expv1 = myExpv(rawpp1);
335 //     std::copy(expv1, expv1+myNumIndets, expv);
336     memcpy(myExpv(rawpp), myExpv(rawpp1), myNumIndets*sizeof(SmallExponent_t));
337   }
338 
myAssign(RawPtr rawpp,const vector<long> & expv1)339   void PPMonoidEvSmallExpImpl::myAssign(RawPtr rawpp, const vector<long>& expv1) const
340   {
341     CoCoA_ASSERT(myCheckExponents(expv1));
342 
343     SmallExponent_t* const expv = myExpv(rawpp);
344     for (long i = 0; i < myNumIndets; ++i)
345       expv[i] = NumericCast<SmallExponent_t>(expv1[i]);
346   }
347 
348 
myDelete(RawPtr rawpp)349   void PPMonoidEvSmallExpImpl::myDelete(RawPtr rawpp) const
350   {
351     myMemMgr.free(rawpp.myRawPtr());
352   }
353 
354 
mySwap(RawPtr rawpp1,RawPtr rawpp2)355   void PPMonoidEvSmallExpImpl::mySwap(RawPtr rawpp1, RawPtr rawpp2) const
356   {
357     if (rawpp1 == rawpp2) return;
358     SmallExponent_t* const expv1 = myExpv(rawpp1);
359     SmallExponent_t* const expv2 = myExpv(rawpp2);
360     for (long i = 0; i < myNumIndets; ++i)
361       std::swap(expv1[i], expv2[i]);
362   }
363 
364 
myMul(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)365   void PPMonoidEvSmallExpImpl::myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
366   {
367     // No worries about aliasing.
368     SmallExponent_t* const expv = myExpv(rawpp);
369     const SmallExponent_t* const expv1 = myExpv(rawpp1);
370     const SmallExponent_t* const expv2 = myExpv(rawpp2);
371     for (long i=0; i < myNumIndets; ++i)
372     {
373       CoCoA_ASSERT("Exponent Overflow" && expv1[i] <= std::numeric_limits<SmallExponent_t>::max()-expv2[i]);
374       expv[i] = expv1[i] + expv2[i];
375     }
376   }
377 
378 
myMulIndetPower(RawPtr rawpp,long indet,long exp)379   void PPMonoidEvSmallExpImpl::myMulIndetPower(RawPtr rawpp, long indet, long exp) const  // assumes exp >= 0
380   {
381     CoCoA_ASSERT(exp >= 0);
382     CoCoA_ASSERT(0 <= indet && indet < myNumIndets);
383     SmallExponent_t* const expv = myExpv(rawpp);
384     // If CoCoA_DEBUG active, check for exponent overflow...
385     CoCoA_ASSERT("Exponent Overflow" && ourMaxExp - expv[indet] >= static_cast<unsigned long>(exp));
386     expv[indet] += static_cast<SmallExponent_t>(exp);  // cast to keep M$ compiler quiet
387   }
388 
389 
myDiv(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)390   void PPMonoidEvSmallExpImpl::myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
391   {
392     // No worries about aliasing.
393     SmallExponent_t* const expv = myExpv(rawpp);
394     const SmallExponent_t* const expv1 = myExpv(rawpp1);
395     const SmallExponent_t* const expv2 = myExpv(rawpp2);
396     for (long i=0; i < myNumIndets; ++i)
397     {
398       CoCoA_ASSERT("Exponent Underflow" && expv1[i] >= expv2[i]);
399       expv[i] = expv1[i] - expv2[i];
400     }
401   }
402 
403 
myColon(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)404   void PPMonoidEvSmallExpImpl::myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
405   {
406     // No worries about aliasing.
407     SmallExponent_t* const expv = myExpv(rawpp);
408     const SmallExponent_t* const expv1 = myExpv(rawpp1);
409     const SmallExponent_t* const expv2 = myExpv(rawpp2);
410 
411     for (long i = 0; i < myNumIndets; ++i)
412       if (expv1[i] > expv2[i])
413         expv[i] = expv1[i] - expv2[i];
414       else
415         expv[i] = 0;
416   }
417 
418 
myGcd(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)419   void PPMonoidEvSmallExpImpl::myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
420   {
421     // No worries about aliasing.
422     SmallExponent_t* const expv = myExpv(rawpp);
423     const SmallExponent_t* const expv1 = myExpv(rawpp1);
424     const SmallExponent_t* const expv2 = myExpv(rawpp2);
425 
426     for (long i = 0; i < myNumIndets; ++i)
427       expv[i] = min(expv1[i], expv2[i]);
428   }
429 
430 
myLcm(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)431   void PPMonoidEvSmallExpImpl::myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
432   {
433     // No worries about aliasing.
434     SmallExponent_t* const expv = myExpv(rawpp);
435     const SmallExponent_t* const expv1 = myExpv(rawpp1);
436     const SmallExponent_t* const expv2 = myExpv(rawpp2);
437 
438     for (long i = 0; i < myNumIndets; ++i)
439       expv[i] = max(expv1[i], expv2[i]);
440   }
441 
442 
myRadical(RawPtr rawpp,ConstRawPtr rawpp1)443   void PPMonoidEvSmallExpImpl::myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const
444   {
445     SmallExponent_t* const expv = myExpv(rawpp);
446     const SmallExponent_t* const expv1 = myExpv(rawpp1);
447 
448     for (long i = 0; i < myNumIndets; ++i)
449       expv[i] = (expv1[i] > 0);
450   }
451 
452 
myPowerSmallExp(RawPtr rawpp,ConstRawPtr rawpp1,long LongExp)453   void PPMonoidEvSmallExpImpl::myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long LongExp) const  // assumes exp >= 0
454   {
455     CoCoA_ASSERT(LongExp >= 0);
456 #ifdef CoCoA_DEBUG
457     myPowerOverflowCheck(rawpp1, LongExp);
458 #endif
459     if (static_cast<unsigned long>(LongExp) > ourMaxExp)
460       CoCoA_ERROR(ERR::ExpTooBig, "PPMonoidEvSmallExpImpl::myPowerSmallExp");
461     const SmallExponent_t exp = static_cast<SmallExponent_t>(LongExp);
462 
463     SmallExponent_t* const expv = myExpv(rawpp);
464     const SmallExponent_t* const expv1 = myExpv(rawpp1);
465     for (long i = 0; i < myNumIndets; ++i)
466       expv[i] = exp * expv1[i];
467   }
468 
469 
myPowerOverflowCheck(ConstRawPtr rawpp,long LongExp)470   void PPMonoidEvSmallExpImpl::myPowerOverflowCheck(ConstRawPtr rawpp, long LongExp) const
471   {
472     if (LongExp == 0 || LongExp == 1) return;
473     CoCoA_ASSERT(LongExp >= 0);
474     const char* const FnName = "PPMonoidEvSmallExpImpl::myPowerOverflowCheck";
475     if (static_cast<unsigned long>(LongExp) > ourMaxExp)
476       CoCoA_ERROR(ERR::ExpTooBig, FnName);
477     const SmallExponent_t exp = static_cast<SmallExponent_t>(LongExp);
478     const SmallExponent_t limit = ourMaxExp/exp;
479 
480     const SmallExponent_t* const expv = myExpv(rawpp);
481     for (long i = 0; i < myNumIndets; ++i)
482     {
483       if (expv[i] > limit)
484         CoCoA_ERROR(ERR::ExpTooBig, FnName);
485     }
486   }
487 
488 
myIsOne(ConstRawPtr rawpp)489   bool PPMonoidEvSmallExpImpl::myIsOne(ConstRawPtr rawpp) const
490   {
491     const SmallExponent_t* const expv = myExpv(rawpp);
492 
493     for (long i = 0; i < myNumIndets; ++i)
494       if (expv[i] != 0) return false;
495 
496     return true;
497   }
498 
499 
myIsIndet(long & index,ConstRawPtr rawpp)500   bool PPMonoidEvSmallExpImpl::myIsIndet(long& index, ConstRawPtr rawpp) const
501   {
502     const SmallExponent_t* const expv = myExpv(rawpp);
503     long j = myNumIndets;
504     for (long i = 0; i < myNumIndets; ++i)
505     {
506       if (expv[i] == 0) continue;
507       if (j != myNumIndets || expv[i] != 1) return false;
508       j = i;
509     }
510     if (j == myNumIndets) return false;
511     index = j;
512     return true;
513   }
514 
515 
myIsCoprime(ConstRawPtr rawpp1,ConstRawPtr rawpp2)516   bool PPMonoidEvSmallExpImpl::myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
517   {
518     const SmallExponent_t* const expv1 = myExpv(rawpp1);
519     const SmallExponent_t* const expv2 = myExpv(rawpp2);
520 
521     for (long i = 0; i < myNumIndets; ++i)
522       if (expv1[i] != 0 && expv2[i] != 0) return false;
523 
524     return true;
525   }
526 
527 
myIsEqual(ConstRawPtr rawpp1,ConstRawPtr rawpp2)528   bool PPMonoidEvSmallExpImpl::myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
529   {
530     const SmallExponent_t* const expv1 = myExpv(rawpp1);
531     const SmallExponent_t* const expv2 = myExpv(rawpp2);
532 
533     for (long i = 0; i < myNumIndets; ++i)
534       if (expv1[i] != expv2[i]) return false;
535     return true;
536   }
537 
538 
myIsDivisible(ConstRawPtr rawpp1,ConstRawPtr rawpp2)539   bool PPMonoidEvSmallExpImpl::myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
540   {
541     const SmallExponent_t* const expv1 = myExpv(rawpp1);
542     const SmallExponent_t* const expv2 = myExpv(rawpp2);
543 
544     for (long i = 0; i < myNumIndets; ++i)
545       if (expv1[i] < expv2[i]) return false;
546 
547     return true;
548   }
549 
550 
myIsSqFree(ConstRawPtr rawpp)551   bool PPMonoidEvSmallExpImpl::myIsSqFree(ConstRawPtr rawpp) const
552   {
553     const SmallExponent_t* const expv = myExpv(rawpp);
554 
555     for (long i = 0; i < myNumIndets; ++i)
556       if (expv[i] > 1) return false;
557 
558     return true;
559   }
560 
561 
myCmp(ConstRawPtr rawpp1,ConstRawPtr rawpp2)562   int PPMonoidEvSmallExpImpl::myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
563   {
564     return myOrdPtr->myCmpExpvs(myExpv(rawpp1), myExpv(rawpp2));
565   }
566 
567 
myStdDeg(ConstRawPtr rawpp)568   long PPMonoidEvSmallExpImpl::myStdDeg(ConstRawPtr rawpp) const
569   {
570     const SmallExponent_t* const expv = myExpv(rawpp);
571     long d=0;
572     for (long i=0; i < myNumIndets; ++i)
573       d += expv[i];
574     return d;
575   }
576 
577 
myWDeg(degree & d,ConstRawPtr rawpp)578   void PPMonoidEvSmallExpImpl::myWDeg(degree& d, ConstRawPtr rawpp) const
579   {
580     myOrdPtr->myWDeg(d, myExpv(rawpp));
581   }
582 
583 
myCmpWDeg(ConstRawPtr rawpp1,ConstRawPtr rawpp2)584   int PPMonoidEvSmallExpImpl::myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
585   {
586     return myOrdPtr->myCmpWDeg(myExpv(rawpp1), myExpv(rawpp2));
587   }
588 
589 
myCmpWDegPartial(ConstRawPtr rawpp1,ConstRawPtr rawpp2,long i)590   int PPMonoidEvSmallExpImpl::myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long i) const
591   {
592     return myOrdPtr->myCmpWDegPartial(myExpv(rawpp1), myExpv(rawpp2), i);
593   }
594 
595 
myExponent(ConstRawPtr rawpp,long indet)596   long PPMonoidEvSmallExpImpl::myExponent(ConstRawPtr rawpp, long indet) const
597   {
598     CoCoA_ASSERT(indet < myNumIndets);
599     return NumericCast<long>(myExpv(rawpp)[indet]);
600   }
601 
myBigExponent(BigInt & EXP,ConstRawPtr rawpp,long indet)602   void PPMonoidEvSmallExpImpl::myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const
603   {
604     CoCoA_ASSERT(indet < myNumIndets);
605     EXP = myExpv(rawpp)[indet];
606   }
607 
608 
myExponents(std::vector<long> & v,ConstRawPtr rawpp)609   void PPMonoidEvSmallExpImpl::myExponents(std::vector<long>& v, ConstRawPtr rawpp) const
610   {
611     CoCoA_ASSERT(len(v) == myNumIndets);
612     const SmallExponent_t* const expv = myExpv(rawpp);
613     for (long i=0; i < myNumIndets; ++i)
614       v[i] = NumericCast<long>(expv[i]);
615   }
616 
617 
myBigExponents(std::vector<BigInt> & expv,ConstRawPtr rawpp)618   void PPMonoidEvSmallExpImpl::myBigExponents(std::vector<BigInt>& expv, ConstRawPtr rawpp) const
619   {
620     CoCoA_ASSERT(len(expv) == myNumIndets);
621     const SmallExponent_t* const v = myExpv(rawpp);
622     for (long i=0; i < myNumIndets; ++i)  expv[i] = v[i];
623   }
624 
625 
myIndetsIn(std::vector<bool> & v,ConstRawPtr rawpp)626   void PPMonoidEvSmallExpImpl::myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const
627   {
628     CoCoA_ASSERT(len(v) == myNumIndets);
629     const SmallExponent_t* const expv = myExpv(rawpp);
630     for (long i=0; i < myNumIndets; ++i)
631       if (expv[i] != 0)
632         v[i] = true;
633   }
634 
myComputeDivMask(DivMask & dm,const DivMaskRule & DivMaskImpl,ConstRawPtr rawpp)635   void PPMonoidEvSmallExpImpl::myComputeDivMask(DivMask& dm, const DivMaskRule& DivMaskImpl, ConstRawPtr rawpp) const
636   {
637     DivMaskImpl->myAssignFromExpv(dm, myExpv(rawpp), myNumIndets);
638   }
639 
640 
myOutputSelf(std::ostream & out)641   void PPMonoidEvSmallExpImpl::myOutputSelf(std::ostream& out) const
642   {
643     if (!out) return;  // short-cut for bad ostreams
644     out << "PPMonoidEv(" << myNumIndets << ", " << myOrd <<")";
645   }
646 
647 
myDebugPrint(std::ostream & out,ConstRawPtr rawpp)648   void PPMonoidEvSmallExpImpl::myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const
649   {
650     if (!out) return;  // short-cut for bad ostreams
651     out << "DEBUG PP: myNumIndets=" << myNumIndets << ", exps=[";
652     for (long i=0; i < myNumIndets; ++i)
653       out << myExponent(rawpp, i) << " ";
654     out << "]" << std::endl;
655   }
656 
657 
658 //--- orderings ----------------------------------------
659 
CmpBase(long NumIndets,long GradingDim)660   PPMonoidEvSmallExpImpl::CmpBase::CmpBase(long NumIndets, long GradingDim):
661     myNumIndets(NumIndets),
662     myGradingDim(GradingDim)
663   {
664     CoCoA_ASSERT(NumIndets > 0);
665     CoCoA_ASSERT(NumIndets < 1000000); // complain about ridiculously large number of indets
666     CoCoA_ASSERT(GradingDim >= 0);
667     CoCoA_ASSERT(GradingDim <= NumIndets);
668   }
669 
670 
671 //--- LexImpl
672 
LexImpl(long NumIndets)673   PPMonoidEvSmallExpImpl::LexImpl::LexImpl(long NumIndets):
674     CmpBase(NumIndets, 0)
675   {
676   }
677 
678 
myCmpExpvs(const SmallExponent_t * v1,const SmallExponent_t * v2)679   int PPMonoidEvSmallExpImpl::LexImpl::myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const
680   {
681     for (long i=0; i<myNumIndets; ++i)
682       if (v1[i] != v2[i])
683       {
684         if (v1[i] > v2[i]) return 1; else return -1;
685       }
686     return 0;
687   }
688 
689 
myWDeg(degree &,const SmallExponent_t *)690   void PPMonoidEvSmallExpImpl::LexImpl::myWDeg(degree& /*d*/, const SmallExponent_t* /*v*/) const
691   {
692     // deliberately does nothing because GradingDim=0
693     //??? should it assign:  d = []
694   }
695 
696 
myCmpWDegPartial(const SmallExponent_t *,const SmallExponent_t *,long)697   int PPMonoidEvSmallExpImpl::LexImpl::myCmpWDegPartial(const SmallExponent_t* /*v1*/, const SmallExponent_t* /*v2*/, long /*i*/) const
698   {
699     return 0; // GradingDim=0, and all degrees in Z^0 are equal
700   }
701 
702 //--- StdDegLexImpl
703 
StdDegLexImpl(long NumIndets)704   PPMonoidEvSmallExpImpl::StdDegLexImpl::StdDegLexImpl(long NumIndets):
705     CmpBase(NumIndets, 1)
706   {
707   }
708 
709 
myWDeg(degree & d,const SmallExponent_t * v)710   void PPMonoidEvSmallExpImpl::StdDegLexImpl::myWDeg(degree& d, const SmallExponent_t* v) const
711   {
712     long deg=0;
713     for (long i=0; i < myNumIndets; ++i)
714       deg += v[i];
715     SetComponent(d, 0, deg);
716   }
717 
718 
myCmpExpvs(const SmallExponent_t * v1,const SmallExponent_t * v2)719   int PPMonoidEvSmallExpImpl::StdDegLexImpl::myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const
720   {
721     long deg1=0, deg2=0;
722     for (long i=0; i < myNumIndets; ++i)
723     {
724       deg1 += v1[i];
725       deg2 += v2[i];
726     }
727     if (deg1 != deg2)
728     {
729       if (deg1 > deg2) return 1; else return -1;
730     }
731 
732     for (long i=0; i < myNumIndets; ++i)
733       if (v1[i] != v2[i])
734       {
735         if (v1[i] > v2[i]) return 1; else return -1;
736       }
737     return 0;
738   }
739 
740 
myCmpWDegPartial(const SmallExponent_t * v1,const SmallExponent_t * v2,long i)741   int PPMonoidEvSmallExpImpl::StdDegLexImpl::myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long i) const
742   {
743     if (i==0) return 0; // ie: wrt to 0-grading
744     long deg1=0, deg2=0;
745     for (long i=0; i < myNumIndets; ++i)
746     {
747       deg1 += v1[i];
748       deg2 += v2[i];
749     }
750     if (deg1 != deg2)
751     {
752       if (deg1 > deg2) return 1; else return -1;
753     }
754     return 0;
755   }
756 
757 
758 //--- StdDegRevLexImpl
759 
StdDegRevLexImpl(long NumIndets)760   PPMonoidEvSmallExpImpl::StdDegRevLexImpl::StdDegRevLexImpl(long NumIndets):
761     CmpBase(NumIndets, 1)
762   {
763   }
764 
765 
myWDeg(degree & d,const SmallExponent_t * v)766   void PPMonoidEvSmallExpImpl::StdDegRevLexImpl::myWDeg(degree& d, const SmallExponent_t* v) const
767   {
768     long deg=0;
769     for (long i=0; i < myNumIndets; ++i)
770       deg += v[i];
771     SetComponent(d, 0, deg);
772   }
773 
774 
myCmpExpvs(const SmallExponent_t * v1,const SmallExponent_t * v2)775   int PPMonoidEvSmallExpImpl::StdDegRevLexImpl::myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const
776   {
777     long deg1=0, deg2=0;
778     for (long i=0; i < myNumIndets; ++i)
779     {
780       deg1 += v1[i];
781       deg2 += v2[i];
782     }
783     if (deg1 != deg2)
784     {
785       if (deg1 > deg2) return 1; else return -1;
786     }
787 
788     for (long i = myNumIndets-1; i>0; --i)
789       if (v1[i] != v2[i])
790       {
791         if (v1[i] > v2[i]) return -1; else return 1;
792       }
793     return 0;
794   }
795 
796 
myCmpWDegPartial(const SmallExponent_t * v1,const SmallExponent_t * v2,long PartialGrDim)797   int PPMonoidEvSmallExpImpl::StdDegRevLexImpl::myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long PartialGrDim) const
798   {
799     CoCoA_ASSERT(PartialGrDim==0 || PartialGrDim==1);
800     if (PartialGrDim==0) return 0; // ie: wrt to 0-grading
801     long deg1=0, deg2=0;
802     for (long i=0; i < myNumIndets; ++i)
803     {
804       deg1 += v1[i];
805       deg2 += v2[i];
806     }
807     if (deg1 != deg2)
808     {
809       if (deg1 > deg2) return 1; else return -1;
810     }
811     return 0;
812   }
813 
814 
815 //--- MatrixOrderingImpl
816 
MatrixOrderingImpl(long NumIndets,long GradingDim,const ConstMatrixView & OrderMatrix)817   PPMonoidEvSmallExpImpl::MatrixOrderingImpl::MatrixOrderingImpl(long NumIndets, long GradingDim, const ConstMatrixView& OrderMatrix):
818     CmpBase(NumIndets, GradingDim)
819   {
820     CoCoA_ASSERT(NumIndets > 0);
821     CoCoA_ASSERT(0 <= GradingDim && GradingDim <= NumIndets);
822     CoCoA_ASSERT(NumRows(OrderMatrix) == NumIndets);
823     CoCoA_ASSERT(NumCols(OrderMatrix) == NumIndets);
824 
825     myOrderMatrix.resize(NumIndets, vector<BigInt>(NumIndets));
826     for (long i=0; i < NumIndets; ++i)
827       for (long j=0; j < NumIndets; ++j)
828         myOrderMatrix[i][j] = ConvertTo<BigInt>(OrderMatrix(i,j));
829   }
830 
831 
myWDeg(degree & d,const SmallExponent_t * v)832   void PPMonoidEvSmallExpImpl::MatrixOrderingImpl::myWDeg(degree& d, const SmallExponent_t* v) const
833   {
834     BigInt deg;
835     for (long g=0; g < myGradingDim; ++g)
836     {
837       deg = 0;
838       for (long i=0; i < myNumIndets; ++i)
839         deg += v[i] * myOrderMatrix[g][i];
840       SetComponent(d, g, deg);
841     }
842   }
843 
844 
MatrixOrderingCmpArrays(const vector<vector<BigInt>> & M,const SmallExponent_t * v1,const SmallExponent_t * v2,long UpTo)845   static int MatrixOrderingCmpArrays(const vector<vector<BigInt> >& M, const SmallExponent_t* v1, const SmallExponent_t* v2, long UpTo)
846   {
847     CoCoA_ASSERT(0 <= UpTo && UpTo <= len(M));
848     BigInt s1, s2; // automatically set to 0
849     const long ncols = len(M[0]);
850     for (long r=0; r < UpTo; ++r)
851     {
852       for (long i=0; i < ncols; ++i)
853       {
854         s1 += v1[i]*M[r][i];
855         s2 += v2[i]*M[r][i];
856       }
857       if (s1 != s2)
858       {
859         if (s1 > s2) return 1; else return -1;
860       }
861       s1 = 0;
862       s2 = 0;
863     }
864     return 0;
865   }
866 
867 
myCmpExpvs(const SmallExponent_t * v1,const SmallExponent_t * v2)868   int PPMonoidEvSmallExpImpl::MatrixOrderingImpl::myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const
869   {
870     return MatrixOrderingCmpArrays(myOrderMatrix, v1, v2, myNumIndets);
871   }
872 
873 
874 //   int PPMonoidEvSmallExpImpl::MatrixOrderingImpl::myCmpWDeg(const SmallExponent_t* v1, const SmallExponent_t* v2) const
875 //   {
876 //     return MatrixOrderingCmpArrays(myOrderMatrix, v1, v2, myGradingDim);
877 //   }
878 
879 
myCmpWDegPartial(const SmallExponent_t * v1,const SmallExponent_t * v2,long PartialGrDim)880   int PPMonoidEvSmallExpImpl::MatrixOrderingImpl::myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long PartialGrDim) const
881   {
882     return MatrixOrderingCmpArrays(myOrderMatrix, v1, v2, PartialGrDim);
883   }
884 
885   //////////////////////////////////////////////////////////////////
886   // BIG EXPONENTS
887 
888   class PPMonoidEvBigExpImpl: public PPMonoidBase
889   {
890     typedef PPMonoidElemRawPtr RawPtr;           // just to save typing
891     typedef PPMonoidElemConstRawPtr ConstRawPtr; // just to save typing
892 
893     class CmpBase
894     {
895     public:
896       CmpBase(long NumIndets, long GradingDim);
~CmpBase()897       virtual ~CmpBase() {};
898     public:
899       virtual int myCmpExpvs(const BigInt* v1, const BigInt* v2) const =0;
900       virtual void myWDeg(degree& d, const BigInt* v) const =0;
901       virtual int myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const =0;
902       //      virtual int myCmpWDeg(const BigInt* v1, const BigInt* v2) const =0;
myCmpWDeg(const BigInt * v1,const BigInt * v2)903       int myCmpWDeg(const BigInt* v1, const BigInt* v2) const { return myCmpWDegPartial(v1, v2, myGradingDim); }
904     protected:
905       long myNumIndets;
906       long myGradingDim;
907     };
908 
909     class LexImpl: public CmpBase
910     {
911     public:
912       LexImpl(long NumIndets);
913       virtual int myCmpExpvs(const BigInt* v1, const BigInt* v2) const;
914       virtual void myWDeg(degree& d, const BigInt* v) const;
915       virtual int myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const;
916     };
917 
918 
919     class StdDegLexImpl: public CmpBase
920     {
921     public:
922       StdDegLexImpl(long NumIndets);
923       virtual int myCmpExpvs(const BigInt* v1, const BigInt* v2) const;
924       virtual void myWDeg(degree& d, const BigInt* v) const;
925       virtual int myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const;
926     };
927 
928 
929     class StdDegRevLexImpl: public CmpBase
930     {
931     public:
932       StdDegRevLexImpl(long NumIndets);
933       virtual int myCmpExpvs(const BigInt* v1, const BigInt* v2) const;
934       virtual void myWDeg(degree& d, const BigInt* v) const;
935       virtual int myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const;
936     };
937 
938 
939     class MatrixOrderingImpl: public CmpBase
940     {
941     public:
942       MatrixOrderingImpl(long NumIndets, long GradingDim, const ConstMatrixView& OrderMatrix);
943       virtual int myCmpExpvs(const BigInt* v1, const BigInt* v2) const;
944       virtual void myWDeg(degree& d, const BigInt* v) const;
945       virtual int myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const;
946     private:
947       std::vector< std::vector<BigInt> > myOrderMatrix;
948     };
949 
950 
951   public:
952     PPMonoidEvBigExpImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord);
953     ~PPMonoidEvBigExpImpl();
954   private: // disable copy ctor and assignment
955     explicit PPMonoidEvBigExpImpl(const PPMonoidEvBigExpImpl& copy);  // NEVER DEFINED -- copy ctor disabled
956     PPMonoidEvBigExpImpl& operator=(const PPMonoidEvBigExpImpl& rhs); // NEVER DEFINED -- assignment disabled
957 
958   public:
959     void contents() const; // FOR DEBUGGING ONLY
960 
961     const std::vector<PPMonoidElem>& myIndets() const;               ///< std::vector whose n-th entry is n-th indet as PPMonoidElem
962 
963     // The functions below are operations on power products owned by PPMonoidEvBigExpImpl
964     const PPMonoidElem& myOne() const;
965     PPMonoidElemRawPtr myNew() const;                                ///< ctor from nothing
966     PPMonoidElemRawPtr myNew(PPMonoidElemConstRawPtr rawpp) const;   ///< ctor by assuming ownership
967     PPMonoidElemRawPtr myNew(const std::vector<long>& expv) const;   ///< ctor from exp vector
968     PPMonoidElemRawPtr myNew(const std::vector<BigInt>& EXPV) const; ///< ctor from exp vector
969     void myDelete(RawPtr rawpp) const;                               ///< dtor, frees pp
970     void mySwap(RawPtr rawpp1, RawPtr rawpp2) const;                 ///< swap(pp1, pp2);
971     void myAssignOne(RawPtr rawpp) const;                            ///< pp = 1
972     void myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const;           ///< p = pp1
973     void myAssign(RawPtr rawpp, const std::vector<long>& expv) const;///< pp = expv (assign from exp vector)
974 
975     void myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = pp1*pp2
976     using PPMonoidBase::myMulIndetPower;    // disable warnings of overloading
977     void myMulIndetPower(RawPtr rawpp, long indet, long exp) const;           ///< pp *= indet^exp, assumes exp >= 0
978     void myMulIndetPower(RawPtr rawpp, long indet, const BigInt& EXP) const;  ///< pp *= indet^EXP
979     void myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = pp1/pp2
980     void myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1/gcd(pp1,pp2)
981     void myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = gcd(pp1,pp2)
982     void myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = lcm(pp1,pp2)
983     void myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const;                   ///< pp = radical(pp1)
984     void myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long exp) const;   ///< pp = pp1^exp, assumes exp >= 0
985     void myPowerOverflowCheck(ConstRawPtr rawpp1, long exp) const;            ///< throw if pp1^exp would overflow, assumes exp >= 0
986 
987 
988     bool myIsOne(ConstRawPtr rawpp) const;                                ///< is pp = 1?
989     bool myIsIndet(long& index, ConstRawPtr rawpp) const;                 ///< true iff pp is an indet
990     bool myIsIndetPosPower(long& indet, BigInt& EXP, ConstRawPtr rawpp) const;
991     bool myIsIndetPosPower(long& indet, long& pow, ConstRawPtr rawpp) const;
992     bool myIsIndetPosPower(ConstRawPtr rawpp) const;
993     bool myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;       ///< are pp1 & pp2 coprime?
994     bool myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;         ///< is pp1 equal to pp2?
995     bool myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;     ///< does pp2 divide pp1?
996     bool myIsSqFree(ConstRawPtr rawpp) const;                             ///< is pp equal to its radical?
997 
998     int myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;              ///< -1,0,1 as pp1 < = > pp2
999     long myStdDeg(ConstRawPtr rawpp) const;                               ///< standard degree of pp
1000     void myWDeg(degree& d, ConstRawPtr rawpp) const;                      ///< d = grading(pp)
1001     int myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;          ///< <0, =0, >0 as wdeg(pp1) < = > wdeg(pp2)
1002     int myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long GrDim ) const; ///< as myCmpWDeg wrt the first GrDim weights
1003     long myExponent(ConstRawPtr rawpp, long indet) const;                 ///< exponent of indet in pp
1004     void myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const; ///< EXP = exponent of indet in pp
1005     void myExponents(std::vector<long>& expv, ConstRawPtr rawpp) const;   ///< expv[i] = exponent(pp,i)
1006     void myBigExponents(std::vector<BigInt>& v, ConstRawPtr rawpp) const; ///< get exponents, SHOULD BE myExponents ???
1007     void myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const;       ///< v[i] = true if i-th indet has exponent != 0
1008     void myOutputSelf(std::ostream& out) const;                           ///< out << PPM
1009     // INHERITED DEFINITION of virtual  void myOutput(std::ostream& out, ConstRawPtr rawpp) const;
1010     void myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const;        ///< print pp in debugging format???
1011 
1012 
1013   private: // auxiliary functions
1014     BigInt* myExpv(RawPtr) const;
1015     const BigInt* myExpv(ConstRawPtr) const;
1016 
1017     void myComputeDivMask(DivMask& dm, const DivMaskRule& DivMaskImpl, ConstRawPtr rawpp) const; ///< used by PPWithMask
1018     bool myCheckExponents(const std::vector<long>& expv) const;
1019     bool myCheckExponents(const std::vector<BigInt>& EXPV) const;
1020 
1021   private: // data members
1022     ///@name Class members
1023     //@{
1024     const long myEntrySize;     ///< size in ????
1025     mutable MemPool myMemMgr;     // IMPORTANT: this must come *before* myIndetVector and myOnePtr.
1026     std::vector<PPMonoidElem> myIndetVector; ///< the indets as PPMonoidElems
1027     std::unique_ptr<CmpBase> myOrdPtr;         ///< actual implementation of the ordering [should be const???]
1028     std::unique_ptr<PPMonoidElem> myOnePtr;
1029     //@}
1030   };
1031 
1032 
1033   // File local inline functions
1034 
myExpv(RawPtr rawpp)1035   inline BigInt* PPMonoidEvBigExpImpl::myExpv(RawPtr rawpp) const
1036   {
1037     return static_cast<BigInt*>(rawpp.myRawPtr());
1038   }
1039 
1040 
myExpv(ConstRawPtr rawpp)1041   inline const BigInt* PPMonoidEvBigExpImpl::myExpv(ConstRawPtr rawpp) const
1042   {
1043     return static_cast<const BigInt*>(rawpp.myRawPtr());
1044   }
1045 
1046 
myCheckExponents(const std::vector<long> & expv)1047   bool PPMonoidEvBigExpImpl::myCheckExponents(const std::vector<long>& expv) const
1048   {
1049     // Check len(expv) == myNumIndets.
1050     // Check exps are non-neg and not too big.
1051     if (len(expv) != myNumIndets) return false;
1052     for (long i=0; i < myNumIndets; ++i)
1053       if (expv[i] < 0) return false;
1054     return true;
1055   }
1056 
myCheckExponents(const std::vector<BigInt> & expv)1057   bool PPMonoidEvBigExpImpl::myCheckExponents(const std::vector<BigInt>& expv) const
1058   {
1059     // Check len(expv) == myNumIndets.
1060     // Check exps are non-neg and not too big.
1061     if (len(expv) != myNumIndets) return false;
1062     for (long i=0; i < myNumIndets; ++i)
1063       if (expv[i] < 0) return false;
1064     return true;
1065   }
1066 
1067 
1068   //----   Constructors & destructor   ----//
1069 
PPMonoidEvBigExpImpl(const std::vector<symbol> & IndetNames,const PPOrdering & ord)1070   PPMonoidEvBigExpImpl::PPMonoidEvBigExpImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord):
1071       PPMonoidBase(ord, IndetNames),
1072       myEntrySize(sizeof(BigInt)*NumIndets(ord)),
1073       myMemMgr(myEntrySize, "PPMonoidEvBigExpImpl.myMemMgr"),
1074       myIndetVector()
1075   {
1076     // Put the correct implementation in myOrdPtr...  [VERY UGLY CODE!!!]
1077     if (IsLex(ord))
1078       myOrdPtr.reset(new LexImpl(myNumIndets));
1079     else if (IsStdDegLex(ord))
1080       myOrdPtr.reset(new StdDegLexImpl(myNumIndets));
1081     else if (IsStdDegRevLex(ord))
1082       myOrdPtr.reset(new StdDegRevLexImpl(myNumIndets));
1083     else
1084       myOrdPtr.reset(new MatrixOrderingImpl(myNumIndets, GradingDim(ord), OrdMat(ord)));
1085 
1086     myRefCountInc();  // this is needed for exception cleanliness, in case one of the lines below throws
1087     myOnePtr.reset(new PPMonoidElem(PPMonoid(this)));
1088     {
1089       // IMPORTANT: this block destroys pp *before* the call to myRefCountZero.
1090       PPMonoidElem pp(PPMonoid(this));
1091       vector<long> expv(myNumIndets);
1092       for (long i=0; i < myNumIndets; ++i)
1093       {
1094         expv[i] = 1;
1095         myAssign(raw(pp), expv);
1096         myIndetVector.push_back(pp);
1097         expv[i] = 0;
1098       }
1099     }
1100     myRefCountZero();
1101   }
1102 
1103 
~PPMonoidEvBigExpImpl()1104   PPMonoidEvBigExpImpl::~PPMonoidEvBigExpImpl()
1105   {}
1106 
1107 /////////////////////////////////////////////////////////////////////////////
1108 
1109 
1110 
myIndets()1111   const std::vector<PPMonoidElem>& PPMonoidEvBigExpImpl::myIndets() const
1112   {
1113     return myIndetVector;
1114   }
1115 
1116 
myOne()1117   const PPMonoidElem& PPMonoidEvBigExpImpl::myOne() const
1118   {
1119     return *myOnePtr;
1120   }
1121 
1122 
myNew()1123   PPMonoidElemRawPtr PPMonoidEvBigExpImpl::myNew() const
1124   {
1125     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
1126     BigInt* const expv = myExpv(rawpp);
1127     for (long i=0; i < myNumIndets; ++i) // BUG BUG: if this throws, rawpp is leaked
1128       new(&expv[i]) BigInt;
1129     myAssignOne(rawpp); // cannot throw
1130     return rawpp;
1131   }
1132 
myNew(PPMonoidElemConstRawPtr rawcopypp)1133   PPMonoidElemRawPtr PPMonoidEvBigExpImpl::myNew(PPMonoidElemConstRawPtr rawcopypp) const
1134   {
1135     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
1136     BigInt* const expv = myExpv(rawpp);
1137     for (long i=0; i < myNumIndets; ++i) // BUG BUG: if this throws, rawpp is leaked
1138       new(&expv[i]) BigInt;
1139     myAssign(rawpp, rawcopypp); // cannot throw
1140     return rawpp;
1141   }
1142 
1143 
myNew(const std::vector<long> & expv)1144   PPMonoidElemRawPtr PPMonoidEvBigExpImpl::myNew(const std::vector<long>& expv) const
1145   {
1146     CoCoA_ASSERT(myCheckExponents(expv));
1147     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
1148     BigInt* const expv1 = myExpv(rawpp);
1149     for (long i=0; i < myNumIndets; ++i) // BUG BUG: if this throws, rawpp is leaked
1150       new(&expv1[i]) BigInt;
1151     myAssign(rawpp, expv); // cannot throw
1152     return rawpp;
1153   }
1154 
1155 
myNew(const std::vector<BigInt> & EXPV)1156   PPMonoidElemRawPtr PPMonoidEvBigExpImpl::myNew(const std::vector<BigInt>& EXPV) const
1157   {
1158     CoCoA_ASSERT(myCheckExponents(EXPV));
1159     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
1160     BigInt* const expv = myExpv(rawpp);
1161     for (long i=0; i < myNumIndets; ++i) // BUG BUG: if this throws, rawpp is leaked
1162       new(&expv[i]) BigInt;
1163     for (long i = 0; i < myNumIndets; ++i)
1164       expv[i] = EXPV[i];
1165     return rawpp;
1166   }
1167 
1168 
myAssignOne(RawPtr rawpp)1169   void PPMonoidEvBigExpImpl::myAssignOne(RawPtr rawpp) const
1170   {
1171     BigInt* const expv = myExpv(rawpp);
1172     for (long i = 0; i < myNumIndets; ++i)
1173       expv[i] = 0;
1174   }
1175 
1176 
myAssign(RawPtr rawpp,ConstRawPtr rawpp1)1177   void PPMonoidEvBigExpImpl::myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const
1178   {
1179     if (rawpp == rawpp1) return;
1180 
1181     BigInt* const expv = myExpv(rawpp);
1182     const BigInt* const expv1 = myExpv(rawpp1);
1183     std::copy(&expv1[0], &expv1[myNumIndets], &expv[0]);
1184   }
1185 
myAssign(RawPtr rawpp,const vector<long> & expv1)1186   void PPMonoidEvBigExpImpl::myAssign(RawPtr rawpp, const vector<long>& expv1) const
1187   {
1188     CoCoA_ASSERT(myCheckExponents(expv1));
1189 
1190     BigInt* const expv = myExpv(rawpp);
1191     for (long i = 0; i < myNumIndets; ++i)
1192       expv[i] = expv1[i];
1193   }
1194 
1195 
myDelete(RawPtr rawpp)1196   void PPMonoidEvBigExpImpl::myDelete(RawPtr rawpp) const
1197   {
1198     BigInt* const expv = myExpv(rawpp);;
1199     for (long i=0; i < myNumIndets; ++i)
1200       expv[i].~BigInt();
1201     myMemMgr.free(rawpp.myRawPtr());
1202   }
1203 
1204 
mySwap(RawPtr rawpp1,RawPtr rawpp2)1205   void PPMonoidEvBigExpImpl::mySwap(RawPtr rawpp1, RawPtr rawpp2) const
1206   {
1207     if (rawpp1 == rawpp2) return;
1208     BigInt* const expv1 = myExpv(rawpp1);
1209     BigInt* expv2 = myExpv(rawpp2);
1210     for (long i = 0; i < myNumIndets; ++i)
1211       std::swap(expv1[i], expv2[i]);
1212   }
1213 
1214 
myMul(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)1215   void PPMonoidEvBigExpImpl::myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
1216   {
1217     BigInt* const expv = myExpv(rawpp);
1218     const BigInt* const expv1 = myExpv(rawpp1);
1219     const BigInt* const expv2 = myExpv(rawpp2);
1220     for (long i = 0; i < myNumIndets; ++i)
1221       expv[i] = expv1[i] + expv2[i];
1222   }
1223 
1224 
myMulIndetPower(RawPtr rawpp,long indet,long exp)1225   void PPMonoidEvBigExpImpl::myMulIndetPower(RawPtr rawpp, long indet, long exp) const  // assumes exp >= 0
1226   {
1227     CoCoA_ASSERT(exp >= 0);
1228     CoCoA_ASSERT(0 <= indet && indet < myNumIndets);
1229     BigInt* const expv = myExpv(rawpp);
1230     expv[indet] += exp;
1231   }
1232 
1233 
1234   // This fn overrides the default defn in PPMonoid.C (which throws for big exps)
myMulIndetPower(RawPtr rawpp,long indet,const BigInt & EXP)1235   void PPMonoidEvBigExpImpl::myMulIndetPower(RawPtr rawpp, long indet, const BigInt& EXP) const
1236   {
1237     CoCoA_ASSERT(0 <= indet && indet < myNumIndets);
1238     CoCoA_ASSERT(EXP >= 0);
1239     BigInt* const expv = myExpv(rawpp);
1240     expv[indet] += EXP;
1241   }
1242 
1243 
myDiv(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)1244   void PPMonoidEvBigExpImpl::myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
1245   {
1246     BigInt* const expv = myExpv(rawpp);
1247     const BigInt* const expv1 = myExpv(rawpp1);
1248     const BigInt* const expv2 = myExpv(rawpp2);
1249     for (long i = 0; i < myNumIndets; ++i)
1250       expv[i] = expv1[i] - expv2[i]; // assert that result is positive?
1251   }
1252 
1253 
myColon(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)1254   void PPMonoidEvBigExpImpl::myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
1255   {
1256     // No worries about aliasing.
1257     BigInt* const expv = myExpv(rawpp);
1258     const BigInt* const expv1 = myExpv(rawpp1);
1259     const BigInt* const expv2 = myExpv(rawpp2);
1260 
1261     for (long i = 0; i < myNumIndets; ++i)
1262       if (expv1[i] > expv2[i])
1263         expv[i] = expv1[i] - expv2[i];
1264       else
1265         expv[i] = 0;
1266   }
1267 
1268 
myGcd(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)1269   void PPMonoidEvBigExpImpl::myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
1270   {
1271     // No worries about aliasing.
1272     BigInt* const expv = myExpv(rawpp);
1273     const BigInt* const expv1 = myExpv(rawpp1);
1274     const BigInt* const expv2 = myExpv(rawpp2);
1275 
1276     for (long i = 0; i < myNumIndets; ++i)
1277       expv[i] = min(expv1[i], expv2[i]);
1278   }
1279 
1280 
myLcm(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)1281   void PPMonoidEvBigExpImpl::myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
1282   {
1283     // No worries about aliasing.
1284     BigInt* const expv = myExpv(rawpp);
1285     const BigInt* const expv1 = myExpv(rawpp1);
1286     const BigInt* const expv2 = myExpv(rawpp2);
1287 
1288     for (long i = 0; i < myNumIndets; ++i)
1289       expv[i] = max(expv1[i], expv2[i]);
1290   }
1291 
1292 
myRadical(RawPtr rawpp,ConstRawPtr rawpp1)1293   void PPMonoidEvBigExpImpl::myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const
1294   {
1295     BigInt* const expv = myExpv(rawpp);
1296     const BigInt* const expv1 = myExpv(rawpp1);
1297 
1298     for (long i = 0; i < myNumIndets; ++i)
1299       expv[i] = (expv1[i] > 0);
1300   }
1301 
1302 
myPowerSmallExp(RawPtr rawpp,ConstRawPtr rawpp1,long exp)1303   void PPMonoidEvBigExpImpl::myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long exp) const  // assumes exp >= 0
1304   {
1305     CoCoA_ASSERT(exp >= 0);
1306     BigInt* const expv = myExpv(rawpp);
1307     const BigInt* const expv1 = myExpv(rawpp1);
1308 
1309     for (long i = 0; i < myNumIndets; ++i)
1310       expv[i] = exp * expv1[i];
1311   }
1312 
1313 
myPowerOverflowCheck(ConstRawPtr,long exp)1314   void PPMonoidEvBigExpImpl::myPowerOverflowCheck(ConstRawPtr /*rawpp*/, long exp) const
1315   {
1316     (void)(exp); // just to avoid compiler warning
1317     CoCoA_ASSERT(exp >= 0);
1318     // nothing to check -- exps here cannot overflow :-)
1319   }
1320 
1321 
myIsOne(ConstRawPtr rawpp)1322   bool PPMonoidEvBigExpImpl::myIsOne(ConstRawPtr rawpp) const
1323   {
1324     const BigInt* const expv = myExpv(rawpp);
1325 
1326     for (long i = 0; i < myNumIndets; ++i)
1327       if (!IsZero(expv[i])) return false;
1328 
1329     return true;
1330   }
1331 
1332 
myIsIndet(long & index,ConstRawPtr rawpp)1333   bool PPMonoidEvBigExpImpl::myIsIndet(long& index, ConstRawPtr rawpp) const
1334   {
1335     const BigInt* const expv = myExpv(rawpp);
1336     long j = myNumIndets;
1337     for (long i = 0; i < myNumIndets; ++i)
1338     {
1339       if (IsZero(expv[i])) continue;
1340       if (j != myNumIndets || !IsOne(expv[i])) return false;
1341       j = i;
1342     }
1343     if (j == myNumIndets) return false;
1344     index = j;
1345     return true;
1346   }
1347 
1348 
myIsIndetPosPower(long & index,BigInt & EXP,ConstRawPtr rawpp)1349   bool PPMonoidEvBigExpImpl::myIsIndetPosPower(long& index, BigInt& EXP, ConstRawPtr rawpp) const
1350   {
1351     const BigInt* const expv = myExpv(rawpp);
1352     long j = myNumIndets;
1353     for (long i = 0; i < myNumIndets; ++i)
1354     {
1355       if (IsZero(expv[i])) continue;
1356       if (j != myNumIndets) return false;
1357       j = i;
1358     }
1359     if (j == myNumIndets) return false;
1360     index = j;
1361     EXP = expv[index];
1362     return true;
1363   }
1364 
myIsIndetPosPower(long & index,long & pow,ConstRawPtr rawpp)1365   bool PPMonoidEvBigExpImpl::myIsIndetPosPower(long& index, long& pow, ConstRawPtr rawpp) const
1366   {
1367     BigInt POW;
1368     long TmpIndex, TmpPow;
1369     if (!myIsIndetPosPower(TmpIndex, POW, rawpp)) return false;
1370     if (!IsConvertible(TmpPow, POW))
1371       CoCoA_ERROR(ERR::ArgTooBig, "PPMonoidEvBigExpImpl::myIsIndetPosPower");
1372     index = TmpIndex;
1373     pow = TmpPow;
1374     return true;
1375   }
1376 
myIsIndetPosPower(ConstRawPtr rawpp)1377   bool PPMonoidEvBigExpImpl::myIsIndetPosPower(ConstRawPtr rawpp) const
1378   {
1379     const BigInt* const expv = myExpv(rawpp);
1380     long j = myNumIndets;
1381     for (long i = 0; i < myNumIndets; ++i)
1382     {
1383       if (IsZero(expv[i])) continue;
1384       if (j != myNumIndets) return false;
1385       j = i;
1386     }
1387     return j != myNumIndets;
1388   }
1389 
1390 
myIsCoprime(ConstRawPtr rawpp1,ConstRawPtr rawpp2)1391   bool PPMonoidEvBigExpImpl::myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
1392   {
1393     const BigInt* const expv1 = myExpv(rawpp1);
1394     const BigInt* const expv2 = myExpv(rawpp2);
1395 
1396     for (long i = 0; i < myNumIndets; ++i)
1397       if (!IsZero(expv1[i]) && !IsZero(expv2[i])) return false;
1398 
1399     return true;
1400   }
1401 
1402 
myIsEqual(ConstRawPtr rawpp1,ConstRawPtr rawpp2)1403   bool PPMonoidEvBigExpImpl::myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
1404   {
1405     const BigInt* const expv1 = myExpv(rawpp1);
1406     const BigInt* const expv2 = myExpv(rawpp2);
1407 
1408     for (long i = 0; i < myNumIndets; ++i)
1409       if (expv1[i] != expv2[i]) return false;
1410     return true;
1411   }
1412 
1413 
myIsDivisible(ConstRawPtr rawpp1,ConstRawPtr rawpp2)1414   bool PPMonoidEvBigExpImpl::myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
1415   {
1416     const BigInt* const expv1 = myExpv(rawpp1);
1417     const BigInt* const expv2 = myExpv(rawpp2);
1418 
1419     for (long i = 0; i < myNumIndets; ++i)
1420       if (expv1[i] < expv2[i]) return false;
1421 
1422     return true;
1423   }
1424 
1425 
myIsSqFree(ConstRawPtr rawpp)1426   bool PPMonoidEvBigExpImpl::myIsSqFree(ConstRawPtr rawpp) const
1427   {
1428     const BigInt* const expv = myExpv(rawpp);
1429 
1430     for (long i = 0; i < myNumIndets; ++i)
1431       if (expv[i] > 1) return false;
1432 
1433     return true;
1434   }
1435 
1436 
myCmp(ConstRawPtr rawpp1,ConstRawPtr rawpp2)1437   int PPMonoidEvBigExpImpl::myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
1438   {
1439     return myOrdPtr->myCmpExpvs(myExpv(rawpp1), myExpv(rawpp2));
1440   }
1441 
1442 
myStdDeg(ConstRawPtr rawpp)1443   long PPMonoidEvBigExpImpl::myStdDeg(ConstRawPtr rawpp) const
1444   {
1445     const BigInt* const expv = myExpv(rawpp);
1446     BigInt d;
1447     for (long i=0; i < myNumIndets; ++i)
1448       d += expv[i];
1449     long ans;
1450     if (!IsConvertible(ans, d))
1451       CoCoA_ERROR(ERR::ArgTooBig, "PPMonoidEvBigExpImpl::myStdDeg");
1452     return ans;
1453   }
1454 
1455 
myWDeg(degree & d,ConstRawPtr rawpp)1456   void PPMonoidEvBigExpImpl::myWDeg(degree& d, ConstRawPtr rawpp) const
1457   {
1458     myOrdPtr->myWDeg(d, myExpv(rawpp));
1459   }
1460 
1461 
myCmpWDeg(ConstRawPtr rawpp1,ConstRawPtr rawpp2)1462   int PPMonoidEvBigExpImpl::myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
1463   {
1464     return myOrdPtr->myCmpWDeg(myExpv(rawpp1), myExpv(rawpp2));
1465   }
1466 
1467 
myCmpWDegPartial(ConstRawPtr rawpp1,ConstRawPtr rawpp2,long GrDim)1468   int PPMonoidEvBigExpImpl::myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long GrDim) const
1469   {
1470     return myOrdPtr->myCmpWDegPartial(myExpv(rawpp1), myExpv(rawpp2), GrDim);
1471   }
1472 
1473 
myExponent(ConstRawPtr rawpp,long indet)1474   long PPMonoidEvBigExpImpl::myExponent(ConstRawPtr rawpp, long indet) const
1475   {
1476     CoCoA_ASSERT(0 <= indet && indet < myNumIndets);
1477     long ans;
1478     if (!IsConvertible(ans, myExpv(rawpp)[indet]))
1479       CoCoA_ERROR(ERR::ArgTooBig, "PPMonoidEvBigExpImpl::myExponent");
1480     return ans;
1481   }
1482 
myBigExponent(BigInt & EXP,ConstRawPtr rawpp,long indet)1483   void PPMonoidEvBigExpImpl::myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const
1484   {
1485     CoCoA_ASSERT(0 <= indet && indet < myNumIndets);
1486     EXP = myExpv(rawpp)[indet];
1487   }
1488 
1489 
myExponents(vector<long> & v,ConstRawPtr rawpp)1490   void PPMonoidEvBigExpImpl::myExponents(vector<long>& v, ConstRawPtr rawpp) const
1491   {
1492     CoCoA_ASSERT(len(v) == myNumIndets);
1493     const BigInt* const expv = myExpv(rawpp);
1494     bool OK = true;
1495     for (long i=0; i < myNumIndets; ++i)
1496     {
1497       if (!IsConvertible(v[i], expv[i]))
1498       {
1499         OK = false;
1500         if (expv[i] > 0)
1501           v[i] = numeric_limits<long>::max();
1502         else
1503           v[i] = numeric_limits<long>::min();
1504       }
1505       if (!OK)
1506         CoCoA_ERROR(ERR::ArgTooBig, "PPMonoidEvBigExpImpl::myExponents");
1507     }
1508   }
1509 
1510 
myBigExponents(vector<BigInt> & expv,ConstRawPtr rawpp)1511   void PPMonoidEvBigExpImpl::myBigExponents(vector<BigInt>& expv, ConstRawPtr rawpp) const
1512   {
1513     CoCoA_ASSERT(len(expv) == myNumIndets);
1514     const BigInt* const v = myExpv(rawpp);
1515     for (long i=0; i < myNumIndets; ++i)  expv[i] = v[i];
1516   }
1517 
1518 
myIndetsIn(std::vector<bool> & v,ConstRawPtr rawpp)1519   void PPMonoidEvBigExpImpl::myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const
1520   {
1521     CoCoA_ASSERT(len(v) == myNumIndets);
1522     const BigInt* const expv = myExpv(rawpp);
1523     for (long i=0; i < myNumIndets; ++i)
1524       if (!IsZero(expv[i]))
1525         v[i] = true;
1526   }
1527 
1528 
myComputeDivMask(DivMask &,const DivMaskRule &,ConstRawPtr)1529   void PPMonoidEvBigExpImpl::myComputeDivMask(DivMask& /*dm*/, const DivMaskRule& /*DivMaskImpl*/, ConstRawPtr /*rawpp*/) const
1530   {
1531     CoCoA_ERROR(ERR::NYI, "PPMonoidEvBigExpImpl::myComputeDivMask");
1532 // BUG BUG can't do this (yet)    DivMaskImpl->myAssignFromExpv(dm, myExpv(rawpp), myNumIndets);
1533   }
1534 
1535 
myOutputSelf(std::ostream & out)1536   void PPMonoidEvBigExpImpl::myOutputSelf(std::ostream& out) const
1537   {
1538     if (!out) return;  // short-cut for bad ostreams
1539     out << "PPMonoidBigEv(" << myNumIndets << ", " << myOrd <<")";
1540   }
1541 
1542 
myDebugPrint(std::ostream & out,ConstRawPtr rawpp)1543   void PPMonoidEvBigExpImpl::myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const
1544   {
1545     if (!out) return;  // short-cut for bad ostreams
1546     out << "DEBUG PP: myNumIndets=" << myNumIndets << ", exps=[";
1547     for (long i=0; i < myNumIndets; ++i)
1548       out << myExponent(rawpp, i) << " ";
1549     out << "]" << std::endl;
1550   }
1551 
1552 
1553 //--- orderings ----------------------------------------
1554 
CmpBase(long NumIndets,long GradingDim)1555   PPMonoidEvBigExpImpl::CmpBase::CmpBase(long NumIndets, long GradingDim):
1556     myNumIndets(NumIndets),
1557     myGradingDim(GradingDim)
1558   {
1559     CoCoA_ASSERT(NumIndets > 0);
1560     CoCoA_ASSERT(NumIndets < 1000000); // complain about ridiculously large number of indets
1561     CoCoA_ASSERT(0 <= GradingDim && GradingDim <= NumIndets);
1562   }
1563 
1564 
1565 //--- LexImpl
1566 
LexImpl(long NumIndets)1567   PPMonoidEvBigExpImpl::LexImpl::LexImpl(long NumIndets):
1568     CmpBase(NumIndets, 0)
1569   {
1570   }
1571 
1572 
myCmpExpvs(const BigInt * v1,const BigInt * v2)1573   int PPMonoidEvBigExpImpl::LexImpl::myCmpExpvs(const BigInt* v1, const BigInt* v2) const
1574   {
1575     for (long i=0; i<myNumIndets; ++i)
1576       if (v1[i] != v2[i]) return (v1[i]>v2[i] ? 1 : -1 );
1577     return 0;
1578   }
1579 
1580 
myWDeg(degree &,const BigInt *)1581   void PPMonoidEvBigExpImpl::LexImpl::myWDeg(degree& /*d*/, const BigInt* /*v*/) const
1582   {
1583     // deliberately does nothing because GradingDim=0
1584     //??? should it assign:  d = []
1585   }
1586 
1587 
myCmpWDegPartial(const BigInt *,const BigInt *,long)1588   int PPMonoidEvBigExpImpl::LexImpl::myCmpWDegPartial(const BigInt* /*v1*/, const BigInt* /*v2*/, long /*GrDim*/) const
1589   {
1590     return 0; // GradingDim=0, and all degrees in Z^0 are equal
1591   }
1592 
1593 //--- StdDegLexImpl
1594 
StdDegLexImpl(long NumIndets)1595   PPMonoidEvBigExpImpl::StdDegLexImpl::StdDegLexImpl(long NumIndets):
1596     CmpBase(NumIndets, 1)
1597   {
1598   }
1599 
1600 
myWDeg(degree & d,const BigInt * v)1601   void PPMonoidEvBigExpImpl::StdDegLexImpl::myWDeg(degree& d, const BigInt* v) const
1602   {
1603     BigInt deg;
1604     for (long i=0; i < myNumIndets; ++i)
1605       deg += v[i];
1606     SetComponent(d, 0, deg);
1607   }
1608 
1609 
myCmpExpvs(const BigInt * v1,const BigInt * v2)1610   int PPMonoidEvBigExpImpl::StdDegLexImpl::myCmpExpvs(const BigInt* v1, const BigInt* v2) const
1611   {
1612     BigInt deg1;
1613     BigInt deg2;
1614     for (long i=0; i < myNumIndets; ++i)
1615     {
1616       deg1 += v1[i];
1617       deg2 += v2[i];
1618     }
1619     if (deg1 != deg2) return (deg1>deg2 ? 1 : -1 );
1620 
1621     for (long i=0; i < myNumIndets; ++i)
1622       if (v1[i] != v2[i]) return (v1[i]>v2[i] ? 1 : -1 );
1623     return 0;
1624   }
1625 
1626 
myCmpWDegPartial(const BigInt * v1,const BigInt * v2,long GrDim)1627   int PPMonoidEvBigExpImpl::StdDegLexImpl::myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const
1628   {
1629     CoCoA_ASSERT(0 <= GrDim && GrDim <= 1);
1630     if (GrDim == 0) return 0; // ie: wrt to 0-grading
1631     BigInt deg1;
1632     BigInt deg2;
1633     for (long i=0; i < myNumIndets; ++i)
1634     {
1635       deg1 += v1[i];
1636       deg2 += v2[i];
1637     }
1638     if (deg1 != deg2) return (deg1>deg2 ? 1 : -1 );
1639     return 0;
1640   }
1641 
1642 
1643 //--- StdDegRevLexImpl
1644 
StdDegRevLexImpl(long NumIndets)1645   PPMonoidEvBigExpImpl::StdDegRevLexImpl::StdDegRevLexImpl(long NumIndets):
1646     CmpBase(NumIndets, 1)
1647   {
1648   }
1649 
1650 
myWDeg(degree & d,const BigInt * v)1651   void PPMonoidEvBigExpImpl::StdDegRevLexImpl::myWDeg(degree& d, const BigInt* v) const
1652   {
1653     BigInt deg;
1654     for (long i=0; i < myNumIndets; ++i)
1655       deg += v[i];
1656     SetComponent(d, 0, deg);
1657   }
1658 
1659 
myCmpExpvs(const BigInt * v1,const BigInt * v2)1660   int PPMonoidEvBigExpImpl::StdDegRevLexImpl::myCmpExpvs(const BigInt* v1, const BigInt* v2) const
1661   {
1662     BigInt deg1;
1663     BigInt deg2;
1664     for (long i=0; i < myNumIndets; ++i)
1665     {
1666       deg1 += v1[i];
1667       deg2 += v2[i];
1668     }
1669     if (deg1 != deg2) return (deg1>deg2 ? 1 : -1 );
1670 
1671     for (long i = myNumIndets-1; i>0; --i)
1672       if (v1[i] != v2[i]) return (v1[i]>v2[i] ? -1 : 1 );
1673     return 0;
1674   }
1675 
1676 
myCmpWDegPartial(const BigInt * v1,const BigInt * v2,long GrDim)1677   int PPMonoidEvBigExpImpl::StdDegRevLexImpl::myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const
1678   {
1679     CoCoA_ASSERT(0 <= GrDim && GrDim <= 1);
1680     if (GrDim == 0) return 0; // ie: wrt to 0-grading
1681     BigInt deg1;
1682     BigInt deg2;
1683     for (long i=0; i < myNumIndets; ++i)
1684     {
1685       deg1 += v1[i];
1686       deg2 += v2[i];
1687     }
1688     if (deg1 != deg2) return (deg1>deg2 ? 1 : -1 );
1689     return 0;
1690   }
1691 
1692 
1693 //--- MatrixOrderingImpl
1694 
MatrixOrderingImpl(long NumIndets,long GradingDim,const ConstMatrixView & OrderMatrix)1695   PPMonoidEvBigExpImpl::MatrixOrderingImpl::MatrixOrderingImpl(long NumIndets, long GradingDim, const ConstMatrixView& OrderMatrix):
1696     CmpBase(NumIndets, GradingDim)
1697   {
1698     CoCoA_ASSERT(0 <= NumIndets);
1699     CoCoA_ASSERT(0 <= GradingDim && GradingDim <= NumIndets);
1700     CoCoA_ASSERT(NumRows(OrderMatrix) == NumIndets);
1701     CoCoA_ASSERT(NumCols(OrderMatrix) == NumIndets);
1702 
1703     myOrderMatrix.resize(NumIndets, vector<BigInt>(NumIndets));
1704     for (long i=0; i < NumIndets; ++i)
1705       for (long j=0; j < NumIndets; ++j)
1706         myOrderMatrix[i][j] = ConvertTo<BigInt>(OrderMatrix(i,j));
1707   }
1708 
1709 
myWDeg(degree & d,const BigInt * v)1710   void PPMonoidEvBigExpImpl::MatrixOrderingImpl::myWDeg(degree& d, const BigInt* v) const
1711   {
1712     BigInt deg;
1713     for (long g=0; g < myGradingDim; ++g)
1714     {
1715       deg = 0;
1716       for (long i=0; i < myNumIndets; ++i)
1717         deg += v[i] * myOrderMatrix[g][i];
1718       SetComponent(d, g, deg);
1719     }
1720   }
1721 
1722 
MatrixOrderingCmpArrays(const vector<vector<BigInt>> & M,const BigInt * v1,const BigInt * v2,long UpTo)1723   static int MatrixOrderingCmpArrays(const vector<vector<BigInt> >& M, const BigInt* v1, const BigInt* v2, long UpTo)
1724   {
1725     CoCoA_ASSERT(0 <= UpTo && UpTo <= len(M));
1726     BigInt s1, s2; // automatically set to 0
1727     const long ncols = len(M[0]);
1728     for (long r=0; r < UpTo; ++r)
1729     {
1730       for (long i=0; i < ncols; ++i)
1731       {
1732         s1 += v1[i]*M[r][i];
1733         s2 += v2[i]*M[r][i];
1734       }
1735       if (s1 != s2) return (s1>s2 ? 1 : -1 );
1736       s1 = 0;
1737       s2 = 0;
1738     }
1739     return 0;
1740   }
1741 
1742 
myCmpExpvs(const BigInt * v1,const BigInt * v2)1743   int PPMonoidEvBigExpImpl::MatrixOrderingImpl::myCmpExpvs(const BigInt* v1, const BigInt* v2) const
1744   {
1745     return MatrixOrderingCmpArrays(myOrderMatrix, v1, v2, myNumIndets);
1746   }
1747 
1748 
myCmpWDegPartial(const BigInt * v1,const BigInt * v2,long GrDim)1749   int PPMonoidEvBigExpImpl::MatrixOrderingImpl::myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const
1750   {
1751     CoCoA_ASSERT(0 <= GrDim && GrDim <= myGradingDim);
1752     return MatrixOrderingCmpArrays(myOrderMatrix, v1, v2, GrDim);
1753   }
1754 
1755 
1756   //////////////////////////////////////////////////////////////////
1757   // Pseudo-ctors
1758 
NewPPMonoidEv(const std::vector<symbol> & IndetNames,const PPOrdering & ord,PPExpSize ExpSize)1759   PPMonoid NewPPMonoidEv(const std::vector<symbol>& IndetNames, const PPOrdering& ord, PPExpSize ExpSize)
1760   {
1761     // Sanity check on the indet names given.
1762     const long nvars = NumIndets(ord);
1763 
1764     if (len(IndetNames) != nvars)
1765       CoCoA_ERROR(ERR::BadNumIndets, "NewPPMonoidEv(IndetNames,ord)");
1766     if (!AreDistinct(IndetNames))
1767       CoCoA_ERROR(ERR::BadIndetNames, "NewPPMonoidEv(IndetNames,ord)");
1768     if (!AreArityConsistent(IndetNames))
1769       CoCoA_ERROR(ERR::BadIndetNames, "NewPPMonoidEv(IndetNames,ord)");
1770 
1771     if (ExpSize == SmallExps)
1772       return PPMonoid(new PPMonoidEvSmallExpImpl(IndetNames, ord));
1773     return PPMonoid(new PPMonoidEvBigExpImpl(IndetNames, ord));
1774   }
1775 
NewPPMonoidEv(const std::vector<symbol> & IndetNames,const PPOrderingCtor & OrdCtor,PPExpSize ExpSize)1776   PPMonoid NewPPMonoidEv(const std::vector<symbol>& IndetNames, const PPOrderingCtor& OrdCtor, PPExpSize ExpSize)
1777   {
1778     return NewPPMonoidEv(IndetNames, OrdCtor(len(IndetNames)), ExpSize);
1779   }
1780 
1781 
1782 
1783 } // end of namespace CoCoA
1784 
1785 
1786 // RCS header/log in the next few lines
1787 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/PPMonoidEv.C,v 1.50 2020/02/15 11:10:22 abbott Exp $
1788 // $Log: PPMonoidEv.C,v $
1789 // Revision 1.50  2020/02/15 11:10:22  abbott
1790 // Summary: IsIndetPosPower now gives false instead of error for input 1
1791 //
1792 // Revision 1.49  2020/02/11 16:56:41  abbott
1793 // Summary: Corrected last update (see redmine 969)
1794 //
1795 // Revision 1.48  2020/02/11 16:12:18  abbott
1796 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969
1797 //
1798 // Revision 1.47  2019/03/04 10:29:36  abbott
1799 // Summary: Changed auto_ptr into unqiue_ptr
1800 //
1801 // Revision 1.46  2018/05/18 12:15:04  bigatti
1802 // -- renamed IntOperations --> BigIntOps
1803 //
1804 // Revision 1.45  2017/04/18 12:50:06  abbott
1805 // Summary: Corrected ifdef use of CoCoA_THREADSAFE_HACK and CoCoA_DEBUG
1806 //
1807 // Revision 1.44  2016/11/03 12:25:25  abbott
1808 // Summary: Changed IsRadical (for PPMonoidElem) into IsSqFree
1809 //
1810 // Revision 1.43  2015/12/01 13:11:01  abbott
1811 // Summary: Changed mem fn PPOrderingCtor::myCtor into operator(); also for ModuleOrderingCtor; see issue 829
1812 //
1813 // Revision 1.42  2015/11/30 21:53:55  abbott
1814 // Summary: Major update to matrices for orderings (not yet complete, some tests fail)
1815 //
1816 // Revision 1.41  2015/06/30 12:54:07  abbott
1817 // Summary: Added new fn myIndetsIn
1818 // Author: JAA
1819 //
1820 // Revision 1.40  2015/04/16 20:19:39  abbott
1821 // Summary: Silly change to avoid a compiler warning about unused param
1822 // Author: JAA
1823 //
1824 // Revision 1.39  2015/04/16 16:36:33  abbott
1825 // Summary: Cleaned impls of myPowerOverflowCheck
1826 // Author: JAA
1827 //
1828 // Revision 1.38  2015/04/13 16:17:58  abbott
1829 // Summary: Corrected silly typo.
1830 // Author: JAA
1831 //
1832 // Revision 1.37  2015/04/13 14:42:07  abbott
1833 // Summary: Added myPowerOverflowCheck (1st version)
1834 // Author: JAA
1835 //
1836 // Revision 1.36  2014/07/31 13:10:45  bigatti
1837 // -- GetMatrix(PPO) --> OrdMat(PPO)
1838 // -- added OrdMat and GradingMat to PPOrdering, PPMonoid, SparsePolyRing
1839 //
1840 // Revision 1.35  2014/07/03 15:36:35  abbott
1841 // Summary: Cleaned up impl of PPMonoids: moved myIndetSymbols & myNumIndets to base class
1842 // Author: JAA
1843 //
1844 // Revision 1.34  2014/05/14 15:57:15  bigatti
1845 // -- added "using" for clang with superpedantic flag
1846 //
1847 // Revision 1.33  2014/01/28 09:59:10  abbott
1848 // Replaced two calls to IsInteger by calls to ConvertTo<BigInt>.
1849 //
1850 // Revision 1.32  2014/01/16 16:11:43  abbott
1851 // Added some missing const keywords (to local variables)
1852 //
1853 // Revision 1.31  2013/03/15 11:00:50  abbott
1854 // Added check for exponent overflow when powering a PP.
1855 // Merged PPMonoidEv and PPMonoidEvZZ implementations into a single file.
1856 // Implemented new interface for pseudo-ctors for PPMonoidEv which uses a "flag"
1857 // to say whether exponents are big or not.
1858 //
1859 // Revision 1.30  2012/05/28 09:18:21  abbott
1860 // Created IntOperations which gathers together all operations on
1861 // integers (both big and small).  Many consequential changes.
1862 //
1863 // Revision 1.29  2012/02/10 17:04:23  abbott
1864 // Removed a commented out decl of a member fn: myNew(vector<BigInt>)
1865 //
1866 // Revision 1.28  2012/01/26 16:50:55  bigatti
1867 // -- changed back_inserter into insert
1868 //
1869 // Revision 1.27  2011/08/14 15:52:17  abbott
1870 // Changed ZZ into BigInt (phase 1: just the library sources).
1871 //
1872 // Revision 1.26  2011/05/03 12:13:12  abbott
1873 // Added static const data member ourMaxExp.
1874 // Code is more readable, and compiler doesn't grumble any more.
1875 //
1876 // Revision 1.25  2011/03/22 23:12:16  abbott
1877 // Removed some spurious junk at the start of the file.
1878 // Corrected copyright years.
1879 //
1880 // Revision 1.24  2011/03/22 22:38:15  abbott
1881 // Fixed some wrong static_casts inside some CoCoA_ASSERTs.
1882 //
1883 // Revision 1.23  2011/03/10 17:47:42  bigatti
1884 // -- fixed a CoCoA_ASSERT
1885 //
1886 // Revision 1.22  2011/03/10 17:26:19  bigatti
1887 // -- changed unsigned long into long in soe CoCoA_ASSERT
1888 //
1889 // Revision 1.21  2011/03/10 16:39:34  abbott
1890 // Replaced (very many) size_t by long in function interfaces (for rings,
1891 // PPMonoids and modules).  Also replaced most size_t inside fn defns.
1892 //
1893 // Revision 1.20  2011/03/01 14:14:54  bigatti
1894 // -- made CmpBase dtor non-inline for problems with g++ on some ppc
1895 //
1896 // Revision 1.19  2010/12/17 16:09:51  abbott
1897 // Corrected used of myIndetSymbols in some assertions.
1898 //
1899 // Revision 1.18  2010/11/30 11:18:11  bigatti
1900 // -- renamed IndetName --> IndetSymbol
1901 //
1902 // Revision 1.17  2010/11/05 16:21:08  bigatti
1903 // -- added ZZExponents
1904 //
1905 // Revision 1.16  2010/10/06 14:10:24  abbott
1906 // Added increments to the ref count in ring and PPMonoid ctors to make
1907 // them exception safe.
1908 //
1909 // Revision 1.15  2010/02/03 16:13:52  abbott
1910 // Added new single word tags for specifying the ordering in PPMonoid
1911 // pseudo-ctors.
1912 //
1913 // Revision 1.14  2010/02/02 16:44:31  abbott
1914 // Added radical & IsRadical (via mem fns myRadical & myIsRadical)
1915 // for PPMonoidElems.
1916 //
1917 // Revision 1.13  2009/12/23 18:53:52  abbott
1918 // Major change to conversion functions:
1919 //   convert(..) is now a procedure instead of a function
1920 //   IsConvertible(..) replaces the former convert(..) function
1921 //   Added new NumericCast conversion function (placeholder for BOOST feature)
1922 //   Consequent changes in code which uses these features.
1923 //
1924 // Revision 1.12  2009/09/22 14:01:33  bigatti
1925 // -- added myCmpWDegPartial (ugly name, I know....)
1926 // -- cleaned up and realigned code in PPMonoid*.C files
1927 //
1928 // Revision 1.11  2009/07/02 16:34:18  abbott
1929 // Minor change to keep the compiler quiet.
1930 //
1931 // Revision 1.10  2008/03/26 16:52:04  abbott
1932 // Added exponent overflow checks (also for ordvs) when CoCoA_DEBUG is active.
1933 //
1934 // Revision 1.9  2007/12/05 11:06:24  bigatti
1935 // -- changed "size_t StdDeg/myStdDeg(f)" into "long"  (and related functions)
1936 // -- changed "log/myLog(f, i)" into "MaxExponent/myMaxExponent(f, i)"
1937 // -- fixed bug in "IsOne(ideal)" in SparsePolyRing.C
1938 //
1939 // Revision 1.8  2007/12/04 14:27:07  bigatti
1940 // -- changed "log(pp, i)" into "exponent(pp, i)"
1941 //
1942 // Revision 1.7  2007/10/30 17:14:07  abbott
1943 // Changed licence from GPL-2 only to GPL-3 or later.
1944 // New version for such an important change.
1945 //
1946 // Revision 1.6  2007/09/25 16:32:30  abbott
1947 // Several minor changes to silence gcc-4.3:
1948 //    more #includes,
1949 //    and fixed a template problemm in RegisterServerOps.C
1950 //
1951 // Revision 1.5  2007/05/31 14:54:31  bigatti
1952 // -- now using AreDistinct and AreArityConsistent for sanity check on
1953 //    indet names
1954 //
1955 // Revision 1.3  2007/05/03 10:35:23  abbott
1956 // Added new PPMonoidEvZZ with (virtually) unlimited exponents.
1957 // Modified test-PPMonoid1.C accordingly.
1958 // Added warning in doc about silent/unchecked exponent overflow in other
1959 // PPMonoids.
1960 //
1961 // Revision 1.2  2007/03/23 18:38:42  abbott
1962 // Separated the "convert" functions (and CheckedCast) into their own files.
1963 // Many consequential changes.  Also corrected conversion to doubles.
1964 //
1965 // Revision 1.1.1.1  2007/03/09 15:16:11  abbott
1966 // Imported files
1967 //
1968 // Revision 1.15  2007/03/08 18:22:29  cocoa
1969 // Just whitespace cleaning.
1970 //
1971 // Revision 1.14  2007/03/08 17:43:11  cocoa
1972 // Swapped order of args to the NewPPMonoid pseudo ctors.
1973 //
1974 // Revision 1.13  2007/03/08 11:07:12  cocoa
1975 // Made pseudo ctors for polynomial rings more uniform.  This allowed me to
1976 // remove an include of CoCoA/symbol.H  from the RingDistrM*.H files, but then
1977 // I had to put the include in several .C files.
1978 //
1979 // Revision 1.12  2006/12/07 17:23:46  cocoa
1980 // -- for compilation with _Wextra: commented out names of unused arguments
1981 //
1982 // Revision 1.11  2006/12/06 17:35:58  cocoa
1983 // -- style: RawPtr args are now called "raw.."
1984 //
1985 // Revision 1.10  2006/11/27 13:06:23  cocoa
1986 // Anna and Michael made me check without writing a proper message.
1987 //
1988 // Revision 1.9  2006/11/24 17:04:32  cocoa
1989 // -- reorganized includes of header files
1990 //
1991 // Revision 1.8  2006/11/23 17:39:11  cocoa
1992 // -- added #include
1993 //
1994 // Revision 1.7  2006/11/16 11:27:20  cocoa
1995 // -- reinserted myRefCountZero(): sometimes really necessary, in general safe
1996 //
1997 // Revision 1.6  2006/11/14 17:29:20  cocoa
1998 // -- commented out myRefCountZero() (not necessary???)
1999 //
2000 // Revision 1.5  2006/10/16 23:18:59  cocoa
2001 // Corrected use of std::swap and various special swap functions.
2002 // Improved myApply memfn for homs of RingDistrMPolyInlPP.
2003 //
2004 // Revision 1.4  2006/10/06 14:04:14  cocoa
2005 // Corrected position of #ifndef in header files.
2006 // Separated CoCoA_ASSERT into assert.H from config.H;
2007 // many minor consequential changes (have to #include assert.H).
2008 // A little tidying of #include directives (esp. in Max's code).
2009 //
2010 // Revision 1.3  2006/08/07 21:23:25  cocoa
2011 // Removed almost all publicly visible references to SmallExponent_t;
2012 // changed to long in all PPMonoid functions and SparsePolyRing functions.
2013 // DivMask remains to sorted out.
2014 //
2015 // Revision 1.2  2006/06/21 17:07:10  cocoa
2016 // Fixed IsIndet bug -- why are there three almost identical copies of code?
2017 //
2018 // Revision 1.1.1.1  2006/05/30 11:39:37  cocoa
2019 // Imported files
2020 //
2021 // Revision 1.9  2006/04/27 13:45:30  cocoa
2022 // Changed name of NewIdentityRingHom to NewIdentityHom.
2023 // Changed name of member functions which print out their own object
2024 // into myOutputSelf (to distinguish from "transitive" myOutput fns).
2025 //
2026 // Revision 1.8  2006/03/27 12:21:25  cocoa
2027 // Minor silly changes to reduce number of complaints from some compiler or other.
2028 //
2029 // Revision 1.7  2006/03/15 18:09:31  cocoa
2030 // Changed names of member functions which print out their object
2031 // into myOutputSelf -- hope this will appease the Intel C++ compiler.
2032 //
2033 // Revision 1.6  2006/03/14 17:21:18  cocoa
2034 // Moved concrete PPMonoid impls entirely into their respective .C files.
2035 // Now the corresponding .H files are very compact.
2036 //
2037 // Revision 1.5  2006/03/12 21:28:33  cocoa
2038 // Major check in after many changes
2039 //
2040 // Revision 1.4  2006/02/20 22:41:20  cocoa
2041 // All forms of the log function for power products now return SmallExponent_t
2042 // (instead of int).  exponents now resizes the vector rather than requiring
2043 // the user to pass in the correct size.
2044 //
2045 // Revision 1.3  2006/01/17 10:23:08  cocoa
2046 // Updated DivMask; many consequential changes.
2047 // A few other minor fixes.
2048 //
2049 // Revision 1.2  2005/11/17 13:25:13  cocoa
2050 // -- "unsigned int" --> "SmallExponent_t" in ctor PPMonoidEvImpl(o, IndetNames)
2051 //
2052 // Revision 1.1.1.1  2005/10/17 10:46:54  cocoa
2053 // Imported files
2054 //
2055 // Revision 1.9  2005/10/11 16:37:30  cocoa
2056 // Added new small prime finite field class (see RingFpDouble).
2057 //
2058 // Cleaned makefiles and configuration script.
2059 //
2060 // Tidied PPMonoid code (to eliminate compiler warnings).
2061 //
2062 // Fixed bug in RingFloat::myIsInteger.
2063 //
2064 // Revision 1.8  2005/08/08 16:36:32  cocoa
2065 // Just checking in before going on holiday.
2066 // Don't really recall what changes have been made.
2067 // Added IsIndet function for RingElem, PPMonoidElem,
2068 // and a member function of OrdvArith.
2069 // Improved the way failed assertions are handled.
2070 //
2071 // Revision 1.7  2005/07/19 15:30:20  cocoa
2072 // A first attempt at iterators over sparse polynomials.
2073 // Main additions are to SparsePolyRing, DistrMPoly*.
2074 // Some consequential changes to PPMonoid*.
2075 //
2076 // Revision 1.6  2005/07/08 15:09:28  cocoa
2077 // Added new symbol class (to represent names of indets).
2078 // Integrated the new class into concrete polynomial rings
2079 // and PPMonoid -- many consequential changes.
2080 // Change ctors for the "inline" sparse poly rings: they no
2081 // longer expect a PPMonoid, but build their own instead
2082 // (has to be a PPMonoidOv).
2083 //
2084 // Revision 1.5  2005/07/01 16:08:15  cocoa
2085 // Friday check-in.  Major change to structure under PolyRing:
2086 // now SparsePolyRing and DUPolyRing are separated (in preparation
2087 // for implementing iterators).
2088 //
2089 // A number of other relatively minor changes had to be chased through
2090 // (e.g. IndetPower).
2091 //
2092 // Revision 1.4  2005/06/23 15:42:41  cocoa
2093 // Fixed typo in GNU fdl -- all doc/*.txt files affected.
2094 // Minor corrections to PPMonoid (discovered while writing doc).
2095 //
2096 // Revision 1.3  2005/06/22 14:47:56  cocoa
2097 // PPMonoids and PPMonoidElems updated to mirror the structure
2098 // used for rings and RingElems.  Many consequential changes.
2099 //
2100 // Revision 1.2  2005/05/04 16:50:31  cocoa
2101 // -- new code for MatrixOrderingImpl
2102 // -- changed: CmpBase also requires GradingDim
2103 //
2104 // Revision 1.1.1.1  2005/05/03 15:47:31  cocoa
2105 // Imported files
2106 //
2107 // Revision 1.4  2005/04/29 15:42:02  cocoa
2108 // Improved documentation for GMPAllocator.
2109 // Added example program for GMPAllocator.
2110 // Added example program for simple ops on polynomials.
2111 // Added two new ctors for (principal) ideals (from long, and from ZZ).
2112 // Added (crude) printing for PPMonoids.
2113 // Updated library.H (#included GMPAllocator.H).
2114 //
2115 // Revision 1.3  2005/04/20 15:40:48  cocoa
2116 // Major change: modified the standard way errors are to be signalled
2117 // (now via a macro which records filename and line number).  Updated
2118 // documentation in error.txt accordingly.
2119 //
2120 // Improved the documentation in matrix.txt (still more work to be done).
2121 //
2122 // Revision 1.2  2005/04/19 14:06:04  cocoa
2123 // Added GPL and GFDL licence stuff.
2124 //
2125 // Revision 1.1.1.1  2005/01/27 15:12:13  cocoa
2126 // Imported files
2127 //
2128 // Revision 1.3  2004/11/25 16:14:21  cocoa
2129 // (1) Fixed definition of specialization of std::swap template function
2130 //     so that it compiles with gcc 3.4.3
2131 // (2) Implemented monomial function for polynomial rings.
2132 // (3) Added one(PPM) and PPM->myOne() functions.
2133 //
2134 // Revision 1.2  2004/11/12 15:49:29  cocoa
2135 // Tidying prior to 0.90 release.
2136 // (a) documentation improved (or marked as poor)
2137 // (b) sundry minor improvements to the code
2138 //
2139 // Revision 1.1  2004/11/11 13:45:22  cocoa
2140 // -- renamed: was PPMonoidSafe
2141 //
2142 // Revision 1.3  2004/11/03 17:52:05  cocoa
2143 // -- added just a warning to remind me to implement matrix ordering
2144 //
2145 // Revision 1.2  2004/11/02 14:56:33  cocoa
2146 // -- changed *Print* into *Output* (myPrint --> myOutput)
2147 // -- changed *Var* into *Indet* (myPrintVarName --> myOutputIndetName)
2148 // -- removed suffix "IgnoreDivMask"
2149 // -- added myComputeDivMask
2150 // -- improved storing of IndetNames
2151 // -- changed ExpvElem into SmallExponent_t
2152 //
2153 // Revision 1.1  2004/10/29 15:31:25  cocoa
2154 // -- new PPMonoid for compatibility with OrdvArith (without DivMask)
2155 //
2156