1 //   Copyright (c)  2001-2017  John Abbott and Anna M. Bigatti
2 //   Author:  2005-2010  John Abbott
3 
4 //   This file is part of the source of CoCoALib, the CoCoA Library.
5 
6 //   CoCoALib is free software: you can redistribute it and/or modify
7 //   it under the terms of the GNU General Public License as published by
8 //   the Free Software Foundation, either version 3 of the License, or
9 //   (at your option) any later version.
10 
11 //   CoCoALib is distributed in the hope that it will be useful,
12 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //   GNU General Public License for more details.
15 
16 //   You should have received a copy of the GNU General Public License
17 //   along with CoCoALib.  If not, see <http://www.gnu.org/licenses/>.
18 
19 
20 // Implementation of classes PPMonoidOvImpl
21 
22 #include "CoCoA/PPMonoidOv.H"
23 
24 #include "CoCoA/BigInt.H"
25 #include "CoCoA/DivMask.H"
26 #include "CoCoA/MemPool.H"
27 #include "CoCoA/OrdvArith.H"
28 #include "CoCoA/PPMonoid.H"
29 #include "CoCoA/assert.H"
30 #include "CoCoA/convert.H"
31 #include "CoCoA/error.H"
32 #include "CoCoA/symbol.H"
33 #include "CoCoA/utils.H"
34 //#include "CoCoA/VectorOps.H" // for debugging only
35 
36 #include <algorithm>
37 using std::min;
38 using std::max;
39 #include <iostream>
40 using std::ostream;
41 #include<limits>
42 using std::numeric_limits;
43 #include <memory>
44 using std::unique_ptr;
45 #include <vector>
46 using std::vector;
47 
48 
49 namespace CoCoA
50 {
51 
52   class PPMonoidOvImpl: public PPMonoidBase
53   {
54     typedef PPMonoidElemRawPtr RawPtr;           // just to save typing
55     typedef PPMonoidElemConstRawPtr ConstRawPtr; // just to save typing
56     typedef OrdvArith::OrdvElem OrdvElem;        // just to save typing
57 
58     static const unsigned long ourMaxExp;        // defined below, it is just numeric_limits<SmallExponent_t>::max()
59 
60   public:
61     PPMonoidOvImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord);
62     ~PPMonoidOvImpl();
63   private: // disable copy ctor and assignment
64     PPMonoidOvImpl(const PPMonoidOvImpl& copy);           // NEVER DEFINED -- copy ctor disabled
65     PPMonoidOvImpl& operator=(const PPMonoidOvImpl& rhs); // NEVER DEFINED -- assignment disabled
66 
67   public:
68     void contents() const; // FOR DEBUGGING ONLY
69 
70     const std::vector<PPMonoidElem>& myIndets() const;                  ///< std::vector whose n-th entry is n-th indet as PPMonoidElem
71 
72     // The functions below are operations on power products owned by PPMonoidOvImpl
73     const PPMonoidElem& myOne() const;
74     using PPMonoidBase::myNew;    // disable warnings of overloading
75     PPMonoidElemRawPtr myNew() const;                                   ///< ctor from nothing
76     PPMonoidElemRawPtr myNew(PPMonoidElemConstRawPtr rawpp) const;      ///< ctor by assuming ownership
77     PPMonoidElemRawPtr myNew(const std::vector<long>& expv) const;      ///< ctor from exp vector
78 //NYI    PPMonoidElemRawPtr myNew(const std::vector<BigInt>& EXPV) const;///< ctor from exp vector
79     void myDelete(RawPtr rawpp) const;                                  ///< dtor, frees pp
80     void mySwap(RawPtr rawpp1, RawPtr rawpp2) const;                    ///< swap(pp1, pp2);
81     void myAssignOne(RawPtr rawpp) const;                               ///< pp = 1
82     void myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const;              ///< p = pp1
83     void myAssign(RawPtr rawpp, const std::vector<long>& expv) const;   ///< pp = expv (assign from exp vector)
84 
85     void myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = pp1*pp2
86     using PPMonoidBase::myMulIndetPower;    // disable warnings of overloading
87     void myMulIndetPower(RawPtr rawpp, long indet, long exp) const;           ///< pp *= indet^exp, assumes exp >= 0
88     void myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = pp1/pp2
89     void myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1/gcd(pp1,pp2)
90     void myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = gcd(pp1,pp2)
91     void myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = lcm(pp1,pp2)
92     void myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const;                  ///< pp = radical(pp1)
93     void myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long exp) const;  ///< pp = pp1^exp, assumes exp >=  0
94     void myPowerOverflowCheck(ConstRawPtr rawpp1, long exp) const;            ///< throw if pp1^exp would overflow, assumes exp >= 0
95 
96     bool myIsOne(ConstRawPtr rawpp) const;                                ///< is pp = 1?
97     bool myIsIndet(long& index, ConstRawPtr rawpp) const;                 ///< true iff pp is an indet
98     bool myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;       ///< are pp1 & pp2 coprime?
99     bool myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;         ///< is pp1 equal to pp2?
100     bool myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;     ///< does pp2 divide pp1?
101     bool myIsSqFree(ConstRawPtr rawpp) const;                             ///< is pp equal to its radical?
102 
103     int myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;              ///< -1,0,1 as pp1 < = > pp2
104     long myStdDeg(ConstRawPtr rawpp) const;                               ///< standard degree of pp
105     void myWDeg(degree& d, ConstRawPtr rawpp) const;                      ///< d = grading(pp)
106     int myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;          ///< <0, =0, >0 as wdeg(pp1) < = > wdeg(pp2)
107     int myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long) const; ///< as myCmpWDeg wrt the first weights
108     long myExponent(ConstRawPtr rawpp, long indet) const;                 ///< exponent of indet in pp
109     void myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const; ///< EXP = exponent of indet in pp
110     void myExponents(std::vector<long>& expv, ConstRawPtr rawpp) const;   ///< expv[i] = exponent(pp,i)
111     void myBigExponents(std::vector<BigInt>& v, ConstRawPtr rawpp) const; ///< get exponents, SHOULD BE myExponents ???
112     void myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const;       ///< v[i] = true if i-th indet has exponent != 0
113     void myOutputSelf(std::ostream& out) const;                           ///< out << PPM
114     // INHERITED DEFINITION of virtual  void myOutput(std::ostream& out, ConstRawPtr rawpp) const;
115     void myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const;        ///< print pp in debugging format???
116 
117 
118   private: // auxiliary functions
119     OrdvElem* myOrdv(RawPtr) const;
120     const OrdvElem* myOrdv(ConstRawPtr) const;
121 
122     void myComputeDivMask(DivMask& dm, const DivMaskRule& DivMaskImpl, ConstRawPtr rawpp) const; ///< used by PPWithMask
123     void myComputeExpv(std::vector<long>& expv, RawPtr rawpp) const;
124     bool myCheckExponents(const std::vector<long>& expv) const;
125 //???    void mySetExpv(RawPtr, const std::vector<long>& expv) const;
126 
127   private: // data members
128     ///@name Class members
129     //@{
130     OrdvArith::reference myOrdvArith;  //??? should be const
131     const long myEntrySize;
132     mutable vector<long> myExpv1;  // buffer space
133     mutable vector<long> myExpv2;  // buffer space
134     mutable MemPool myMemMgr;     // IMPORTANT: this must come *before* myIndetVector and myOnePtr.
135 //???    std::vector<long> myDelta;
136     vector<PPMonoidElem> myIndetVector; ///< the indets as PPMonoidElems
137     unique_ptr<PPMonoidElem> myOnePtr;
138     //@}
139   };
140 
141   // static constant value
142   const unsigned long PPMonoidOvImpl::ourMaxExp = numeric_limits<SmallExponent_t>::max();
143 
144   // File local inline functions
145 
myOrdv(RawPtr rawpp)146   inline PPMonoidOvImpl::OrdvElem* PPMonoidOvImpl::myOrdv(RawPtr rawpp) const
147   {
148     return static_cast<OrdvElem*>(rawpp.myRawPtr());
149 
150   }
151 
myOrdv(ConstRawPtr rawpp)152   inline const PPMonoidOvImpl::OrdvElem* PPMonoidOvImpl::myOrdv(ConstRawPtr rawpp) const
153   {
154     return static_cast<const OrdvElem*>(rawpp.myRawPtr());
155   }
156 
157 
myCheckExponents(const std::vector<long> & expv)158   bool PPMonoidOvImpl::myCheckExponents(const std::vector<long>& expv) const
159   {
160     // Check len(expv) == myNumIndets.
161     // Check exps are non-neg and not too big.
162     if (len(expv) != myNumIndets) return false;
163     for (long i=0; i < myNumIndets; ++i)
164       if (expv[i] < 0 || static_cast<unsigned long>(expv[i]) > numeric_limits<SmallExponent_t>::max()) return false;
165     return true;
166   }
167 
168 
169   //----   Constructors & destructor   ----//
170 
PPMonoidOvImpl(const std::vector<symbol> & IndetNames,const PPOrdering & ord)171   PPMonoidOvImpl::PPMonoidOvImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord):
172       PPMonoidBase(ord, IndetNames),
173       myOrdvArith(NewOrdvArith(ord)),
174       myEntrySize(sizeof(OrdvElem)*OrdvWords(myOrdvArith)),
175       myExpv1(myNumIndets),
176       myExpv2(myNumIndets),
177       myMemMgr(myEntrySize, "PPMonoidOvImpl.myMemMgr"),
178       myIndetVector()
179   {
180     //    std::cout << "------PPMonoidOvImpl: called NewOrdvArith" << std::endl;
181     myRefCountInc();  // this is needed for exception cleanliness, in case one of the lines below throws
182     myOnePtr.reset(new PPMonoidElem(PPMonoid(this)));
183     myIndetVector.reserve(myNumIndets);
184     {
185       // IMPORTANT: this block destroys pp *before* the call to myRefCountZero.
186       PPMonoidElem pp(PPMonoid(this));
187       vector<long> expv(myNumIndets);
188       for (long i=0; i < myNumIndets; ++i)
189       {
190         expv[i] = 1;
191         myAssign(raw(pp), expv);
192         myIndetVector.push_back(pp);
193         expv[i] = 0;
194       }
195     }
196     myRefCountZero();
197   }
198 
199 
~PPMonoidOvImpl()200   PPMonoidOvImpl::~PPMonoidOvImpl()
201   {}
202 
203 
204   // mySmartPtr is private
205 //   const OrdvArith::reference& OrdvA(const PPMonoid& PPM)
206 //   {
207 //     if (!IsPPMonoidOv(PPM))
208 //       CoCoA_ERROR("PPM must be PPMonoidOvImpl", OrdvA);
209 //     return dynamic_cast<const PPMonoidOvImpl*>(PPM.mySmartPtr()).myOrdvArith;
210 //   }
211 
212 
213 /////////////////////////////////////////////////////////////////////////////
214 
215 
myIndets()216   const std::vector<PPMonoidElem>& PPMonoidOvImpl::myIndets() const
217   {
218     return myIndetVector;
219   }
220 
221 
myOne()222   const PPMonoidElem& PPMonoidOvImpl::myOne() const
223   {
224     return *myOnePtr;
225   }
226 
227 
myNew()228   PPMonoidElemRawPtr PPMonoidOvImpl::myNew() const
229   {
230     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
231     myAssignOne(rawpp); // cannot throw
232     return rawpp;
233   }
234 
myNew(PPMonoidElemConstRawPtr rawcopypp)235   PPMonoidElemRawPtr PPMonoidOvImpl::myNew(PPMonoidElemConstRawPtr rawcopypp) const
236   {
237     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
238     myAssign(rawpp, rawcopypp); // cannot throw
239     return rawpp;
240   }
241 
242 
myNew(const std::vector<long> & expv)243   PPMonoidElemRawPtr PPMonoidOvImpl::myNew(const std::vector<long>& expv) const
244   {
245     CoCoA_ASSERT(myCheckExponents(expv));
246     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
247     myAssign(rawpp, expv); // cannot throw
248     return rawpp;
249   }
250 
251 
myAssignOne(RawPtr rawpp)252   void PPMonoidOvImpl::myAssignOne(RawPtr rawpp) const
253   {
254     myOrdvArith->myAssignZero(myOrdv(rawpp));
255   }
256 
257 
myAssign(RawPtr rawpp,ConstRawPtr rawpp1)258   void PPMonoidOvImpl::myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const
259   {
260     if (rawpp == rawpp1) return;
261     myOrdvArith->myAssign(myOrdv(rawpp), myOrdv(rawpp1));
262   }
263 
myAssign(RawPtr rawpp,const vector<long> & expv)264   void PPMonoidOvImpl::myAssign(RawPtr rawpp, const vector<long>& expv) const
265   {
266     CoCoA_ASSERT(myCheckExponents(expv));
267     myOrdvArith->myAssignFromExpv(myOrdv(rawpp), expv);
268   }
269 
270 
myDelete(RawPtr rawpp)271   void PPMonoidOvImpl::myDelete(RawPtr rawpp) const
272   {
273     myMemMgr.free(rawpp.myRawPtr());
274   }
275 
276 
mySwap(RawPtr rawpp1,RawPtr rawpp2)277   void PPMonoidOvImpl::mySwap(RawPtr rawpp1, RawPtr rawpp2) const
278   {
279     if (rawpp1 == rawpp2) return;
280     myOrdvArith->mySwap(myOrdv(rawpp1), myOrdv(rawpp2));
281   }
282 
283 
myMul(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)284   void PPMonoidOvImpl::myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
285   {
286     myOrdvArith->myMul(myOrdv(rawpp), myOrdv(rawpp1), myOrdv(rawpp2));
287   }
288 
289 
myMulIndetPower(RawPtr rawpp,long indet,long exp)290   void PPMonoidOvImpl::myMulIndetPower(RawPtr rawpp, long indet, long exp) const  // assumes exp >= 0
291   {
292     CoCoA_ASSERT(exp >= 0);
293     CoCoA_ASSERT(0 <= indet && indet < myNumIndets);
294     CoCoA_ASSERT("Exponent Overflow" && ourMaxExp - myExponent(rawpp, indet) >= static_cast<unsigned long>(exp));
295     myOrdvArith->myMulIndetPower(myOrdv(rawpp), indet, exp);
296   }
297 
298 
myDiv(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)299   void PPMonoidOvImpl::myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
300   {
301     myOrdvArith->myDiv(myOrdv(rawpp), myOrdv(rawpp1), myOrdv(rawpp2));
302   }
303 
304 
myColon(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)305   void PPMonoidOvImpl::myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
306   {
307 #ifdef CoCoA_THREADSAFE_HACK
308     vector<long> myExpv1(myNumIndets);
309     vector<long> myExpv2(myNumIndets);
310 #endif
311     myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp1));
312     myOrdvArith->myComputeExpv(myExpv2, myOrdv(rawpp2));
313 
314     for (long i = 0; i < myNumIndets; ++i)
315     {
316       if (myExpv1[i] > myExpv2[i])
317         myExpv1[i] -= myExpv2[i];
318       else
319         myExpv1[i] = 0;
320     }
321     myOrdvArith->myAssignFromExpv(myOrdv(rawpp), myExpv1);
322   }
323 
324 
myGcd(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)325   void PPMonoidOvImpl::myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
326   {
327 #ifdef CoCoA_THREADSAFE_HACK
328     vector<long> myExpv1(myNumIndets);
329     vector<long> myExpv2(myNumIndets);
330 #endif
331     myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp1));
332     myOrdvArith->myComputeExpv(myExpv2, myOrdv(rawpp2));
333 
334     for (long i = 0; i < myNumIndets; ++i)
335       myExpv1[i] = min(myExpv1[i], myExpv2[i]);
336 
337     myOrdvArith->myAssignFromExpv(myOrdv(rawpp), myExpv1);
338   }
339 
340 
myLcm(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)341   void PPMonoidOvImpl::myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
342   {
343 #ifdef CoCoA_THREADSAFE_HACK
344     vector<long> myExpv1(myNumIndets);
345     vector<long> myExpv2(myNumIndets);
346 #endif
347     myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp1));
348     myOrdvArith->myComputeExpv(myExpv2, myOrdv(rawpp2));
349 
350     for (long i = 0; i < myNumIndets; ++i)
351       myExpv1[i] = max(myExpv1[i], myExpv2[i]);
352 
353     myOrdvArith->myAssignFromExpv(myOrdv(rawpp), myExpv1);
354   }
355 
356 
myRadical(RawPtr rawpp,ConstRawPtr rawpp1)357   void PPMonoidOvImpl::myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const
358   {
359 #ifdef CoCoA_THREADSAFE_HACK
360     vector<long> myExpv1(myNumIndets);
361 #endif
362     myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp1));
363 
364     for (long i = 0; i < myNumIndets; ++i)
365       myExpv1[i] = (myExpv1[i] > 0);
366 
367     myOrdvArith->myAssignFromExpv(myOrdv(rawpp), myExpv1);
368   }
369 
370 
myPowerSmallExp(RawPtr rawpp,ConstRawPtr rawpp1,long exp)371   void PPMonoidOvImpl::myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long exp) const  // assumes exp >= 0
372   {
373     CoCoA_ASSERT(exp >= 0);
374 #ifdef CoCoA_DEBUG
375     myPowerOverflowCheck(rawpp1, exp);
376 #endif
377     myOrdvArith->myPower(myOrdv(rawpp), myOrdv(rawpp1), exp);
378   }
379 
380 
myPowerOverflowCheck(ConstRawPtr rawpp,long exp)381   void PPMonoidOvImpl::myPowerOverflowCheck(ConstRawPtr rawpp, long exp) const
382   {
383     CoCoA_ASSERT(exp >= 0);
384     myOrdvArith->myPowerOverflowCheck(myOrdv(rawpp), exp);
385   }
386 
387 
myIsOne(ConstRawPtr rawpp)388   bool PPMonoidOvImpl::myIsOne(ConstRawPtr rawpp) const
389   {
390     return myOrdvArith->myIsZero(myOrdv(rawpp));
391   }
392 
393 
myIsIndet(long & index,ConstRawPtr rawpp)394   bool PPMonoidOvImpl::myIsIndet(long& index, ConstRawPtr rawpp) const
395   {
396     return myOrdvArith->myIsIndet(index, myOrdv(rawpp));
397   }
398 
399 
myIsCoprime(ConstRawPtr rawpp1,ConstRawPtr rawpp2)400   bool PPMonoidOvImpl::myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
401   {
402 #ifdef CoCoA_THREADSAFE_HACK
403     vector<long> myExpv1(myNumIndets);
404     vector<long> myExpv2(myNumIndets);
405 #endif
406     myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp1));
407     myOrdvArith->myComputeExpv(myExpv2, myOrdv(rawpp2));
408 
409     for (long i = 0; i < myNumIndets; ++i)
410       if (myExpv1[i] != 0 && myExpv2[i] != 0) return false;
411 
412     return true;
413   }
414 
415 
myIsEqual(ConstRawPtr rawpp1,ConstRawPtr rawpp2)416   bool PPMonoidOvImpl::myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
417   {
418     return myOrdvArith->myCmp(myOrdv(rawpp1), myOrdv(rawpp2))==0;
419   }
420 
421 
myIsDivisible(ConstRawPtr rawpp1,ConstRawPtr rawpp2)422   bool PPMonoidOvImpl::myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
423   {
424 #ifdef CoCoA_THREADSAFE_HACK
425     vector<long> myExpv1(myNumIndets);
426     vector<long> myExpv2(myNumIndets);
427 #endif
428     myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp1));
429     myOrdvArith->myComputeExpv(myExpv2, myOrdv(rawpp2));
430 
431     for (long i = 0; i < myNumIndets; ++i)
432       if (myExpv1[i] < myExpv2[i]) return false;
433 
434     return true;
435   }
436 
437 
myIsSqFree(ConstRawPtr rawpp)438   bool PPMonoidOvImpl::myIsSqFree(ConstRawPtr rawpp) const
439   {
440 #ifdef CoCoA_THREADSAFE_HACK
441     vector<long> myExpv1(myNumIndets);
442 #endif
443     myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp));
444     for (long i = 0; i < myNumIndets; ++i)
445       if (myExpv1[i] > 1) return false;
446     return true;
447   }
448 
449 
myCmp(ConstRawPtr rawpp1,ConstRawPtr rawpp2)450   int PPMonoidOvImpl::myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
451   {
452     return myOrdvArith->myCmp(myOrdv(rawpp1), myOrdv(rawpp2));
453   }
454 
455 
456 // // should potentially skip the first few packed ordv entries???
457 // int PPMonoidOvImpl::myHomogCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
458 // {
459 //   return myOrdvArith->myCmp(myOrdv(rawpp1), myOrdv(rawpp2));
460 // }
461 
462 
myStdDeg(ConstRawPtr rawpp)463   long PPMonoidOvImpl::myStdDeg(ConstRawPtr rawpp) const
464   {
465     return myOrdvArith->myStdDeg(myOrdv(rawpp));
466   }
467 
468 
myWDeg(degree & d,ConstRawPtr rawpp)469   void PPMonoidOvImpl::myWDeg(degree& d, ConstRawPtr rawpp) const
470   {
471     myOrdvArith->myWDeg(d, myOrdv(rawpp));
472   }
473 
474 
myCmpWDeg(ConstRawPtr rawpp1,ConstRawPtr rawpp2)475   int PPMonoidOvImpl::myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
476   {
477     return myOrdvArith->myCmpWDeg(myOrdv(rawpp1), myOrdv(rawpp2));
478   }
479 
480 
myCmpWDegPartial(ConstRawPtr rawpp1,ConstRawPtr rawpp2,long i)481   int PPMonoidOvImpl::myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long i) const
482   {
483     return myOrdvArith->myCmpWDegPartial(myOrdv(rawpp1), myOrdv(rawpp2), i);
484   }
485 
486 
myExponent(ConstRawPtr rawpp,long indet)487   long PPMonoidOvImpl::myExponent(ConstRawPtr rawpp, long indet) const
488   {
489     CoCoA_ASSERT(0 <= indet && indet < myNumIndets);
490     return myOrdvArith->myExponent(myOrdv(rawpp), indet);
491   }
492 
myBigExponent(BigInt & EXP,ConstRawPtr rawpp,long indet)493   void PPMonoidOvImpl::myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const
494   {
495     CoCoA_ASSERT(0 <= indet && indet < myNumIndets);
496     EXP = myExponent(rawpp, indet);
497   }
498 
499 
myExponents(std::vector<long> & expv,ConstRawPtr rawpp)500   void PPMonoidOvImpl::myExponents(std::vector<long>& expv, ConstRawPtr rawpp) const
501   {
502     CoCoA_ASSERT(len(expv) == myNumIndets);
503     myOrdvArith->myComputeExpv(expv, myOrdv(rawpp));
504   }
505 
506 
myBigExponents(std::vector<BigInt> & expv,ConstRawPtr rawpp)507   void PPMonoidOvImpl::myBigExponents(std::vector<BigInt>& expv, ConstRawPtr rawpp) const
508   {
509     CoCoA_ASSERT(len(expv) == myNumIndets);
510     std::vector<long> v(myNumIndets);
511     myOrdvArith->myComputeExpv(v, myOrdv(rawpp));
512     for (long i=0; i < myNumIndets; ++i)  expv[i] = v[i];
513   }
514 
515 
myIndetsIn(std::vector<bool> & v,ConstRawPtr rawpp)516   void PPMonoidOvImpl::myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const
517   {
518     CoCoA_ASSERT(len(v) == myNumIndets);
519     // SLUG SLUG SLUG
520     vector<long> expv(myNumIndets);
521     myOrdvArith->myComputeExpv(expv, myOrdv(rawpp));
522     for (int i=0; i < myNumIndets; ++i)
523       if (expv[i] != 0) v[i] = true;
524   }
525 
526 
myComputeDivMask(DivMask & dm,const DivMaskRule & DivMaskImpl,ConstRawPtr rawpp)527   void PPMonoidOvImpl::myComputeDivMask(DivMask& dm, const DivMaskRule& DivMaskImpl, ConstRawPtr rawpp) const
528   {
529 #ifdef CoCoA_THREADSAFE_HACK
530     vector<long> myExpv1(myNumIndets);
531 #endif
532     myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp));
533     vector<SmallExponent_t> expv(myNumIndets);
534     for (long i=0; i < myNumIndets; ++i)
535       expv[i] = static_cast<SmallExponent_t>(myExpv1[i]); // no problem as exponent must be non-neg.
536     DivMaskImpl->myAssignFromExpv(dm, &expv[0], myNumIndets);
537   }
538 
539 
myOutputSelf(std::ostream & out)540   void PPMonoidOvImpl::myOutputSelf(std::ostream& out) const
541   {
542     if (!out) return;  // short-cut for bad ostreams
543     out << "PPMonoidOv(" << myNumIndets << ", " << myOrd << ")";
544   }
545 
546 
myDebugPrint(std::ostream & out,ConstRawPtr rawpp)547   void PPMonoidOvImpl::myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const
548   {
549     if (!out) return;  // short-cut for bad ostreams
550 
551 #ifdef CoCoA_THREADSAFE_HACK
552     vector<long> myExpv1(myNumIndets);
553 #endif
554     myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp));
555     out << "DEBUG PP: myNumIndets=" << myNumIndets << ", exps=[";
556     for (long i=0; i < myNumIndets; ++i)
557       out << myExpv1[i] << " ";
558     out << "]" << std::endl;
559   }
560 
561 
NewPPMonoidOv(const std::vector<symbol> & IndetNames,const PPOrdering & ord)562   PPMonoid NewPPMonoidOv(const std::vector<symbol>& IndetNames, const PPOrdering& ord)
563   {
564     // Sanity check on the indet names given.
565     const long nvars = NumIndets(ord);
566 
567     if (len(IndetNames) != nvars)
568       CoCoA_ERROR(ERR::BadNumIndets, "NewPPMonoidOv(IndetNames,ord)");
569     if (!AreDistinct(IndetNames))
570       CoCoA_ERROR(ERR::BadIndetNames, "NewPPMonoidOv(IndetNames,ord)");
571     if (!AreArityConsistent(IndetNames))
572       CoCoA_ERROR(ERR::BadIndetNames, "NewPPMonoidOv(IndetNames,ord)");
573 
574     return PPMonoid(new PPMonoidOvImpl(IndetNames, ord));
575   }
576 
NewPPMonoidOv(const std::vector<symbol> & IndetNames,const PPOrderingCtor & OrdCtor)577   PPMonoid NewPPMonoidOv(const std::vector<symbol>& IndetNames, const PPOrderingCtor& OrdCtor)
578   {
579     return NewPPMonoidOv(IndetNames, OrdCtor(len(IndetNames)));
580   }
581 
582 
IsPPMonoidOv(const PPMonoid & PPM)583   bool IsPPMonoidOv(const PPMonoid& PPM)
584   {
585     return dynamic_cast<const PPMonoidOvImpl*>(PPM.operator->()) != nullptr;
586   }
587 
588 } // end of namespace CoCoA
589 
590 
591 // RCS header/log in the next few lines
592 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/PPMonoidOv.C,v 1.38 2020/02/11 16:56:41 abbott Exp $
593 // $Log: PPMonoidOv.C,v $
594 // Revision 1.38  2020/02/11 16:56:41  abbott
595 // Summary: Corrected last update (see redmine 969)
596 //
597 // Revision 1.37  2020/02/11 16:12:18  abbott
598 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969
599 //
600 // Revision 1.36  2019/10/15 11:54:08  abbott
601 // Summary: Changed 0 into nullptr (where appropriate)
602 //
603 // Revision 1.35  2019/03/04 10:32:03  abbott
604 // Summary: Changed auto_ptr into unqiue_ptr
605 //
606 // Revision 1.34  2018/05/17 15:38:11  bigatti
607 // -- renamed VectorOperations --> VectorOps
608 //
609 // Revision 1.33  2018/04/20 16:15:31  bigatti
610 // -- minor
611 //
612 // Revision 1.32  2017/12/01 17:29:21  bigatti
613 // // -- updated Copyright line
614 // // -- removed doxygen initial comment
615 // // -- some commented out debugging info
616 //
617 // Revision 1.31  2017/04/18 15:52:27  abbott
618 // Summary: Corrected an ifdef directive
619 //
620 // Revision 1.30  2017/04/18 12:50:06  abbott
621 // Summary: Corrected ifdef use of CoCoA_THREADSAFE_HACK and CoCoA_DEBUG
622 //
623 // Revision 1.29  2016/11/03 12:25:25  abbott
624 // Summary: Changed IsRadical (for PPMonoidElem) into IsSqFree
625 //
626 // Revision 1.28  2015/12/01 13:11:01  abbott
627 // Summary: Changed mem fn PPOrderingCtor::myCtor into operator(); also for ModuleOrderingCtor; see issue 829
628 //
629 // Revision 1.27  2015/11/30 21:53:55  abbott
630 // Summary: Major update to matrices for orderings (not yet complete, some tests fail)
631 //
632 // Revision 1.26  2015/06/30 12:55:00  abbott
633 // Summary: Added new fn myIndetsIn
634 // Author: JAA
635 //
636 // Revision 1.25  2015/04/16 16:36:33  abbott
637 // Summary: Cleaned impls of myPowerOverflowCheck
638 // Author: JAA
639 //
640 // Revision 1.24  2015/04/13 14:42:08  abbott
641 // Summary: Added myPowerOverflowCheck (1st version)
642 // Author: JAA
643 //
644 // Revision 1.23  2014/07/03 15:36:35  abbott
645 // Summary: Cleaned up impl of PPMonoids: moved myIndetSymbols & myNumIndets to base class
646 // Author: JAA
647 //
648 // Revision 1.22  2014/05/14 15:57:15  bigatti
649 // -- added "using" for clang with superpedantic flag
650 //
651 // Revision 1.21  2014/01/30 17:28:42  abbott
652 // Summary: Added new fn IsPPMonoidOv
653 // Author: JAA
654 //
655 // Revision 1.20  2014/01/28 16:46:21  abbott
656 // Made code threadsafe; also some cleaning (buffer expv no longer needed).
657 //
658 // Revision 1.19  2012/01/26 16:50:55  bigatti
659 // -- changed back_inserter into insert
660 //
661 // Revision 1.18  2011/08/14 15:52:17  abbott
662 // Changed ZZ into BigInt (phase 1: just the library sources).
663 //
664 // Revision 1.17  2011/05/03 09:56:16  abbott
665 // Introduced static data member "ourMaxExp" to avoid compiler complaints
666 // (it does improve readability too).
667 //
668 // Revision 1.16  2011/03/22 22:46:01  abbott
669 // Corrected wrong static_cast in a CoCoA_ASSERT.
670 //
671 // Revision 1.15  2011/03/10 17:28:28  bigatti
672 // -- changed unsigned long into long in some CoCoA_ASSERT
673 // -- removed assert in myCmpWDegPartial (done in OrdvArith)
674 //
675 // Revision 1.14  2011/03/10 16:39:34  abbott
676 // Replaced (very many) size_t by long in function interfaces (for rings,
677 // PPMonoids and modules).  Also replaced most size_t inside fn defns.
678 //
679 // Revision 1.13  2010/11/30 11:18:11  bigatti
680 // -- renamed IndetName --> IndetSymbol
681 //
682 // Revision 1.12  2010/11/05 16:21:08  bigatti
683 // -- added ZZExponents
684 //
685 // Revision 1.11  2010/10/06 14:10:24  abbott
686 // Added increments to the ref count in ring and PPMonoid ctors to make
687 // them exception safe.
688 //
689 // Revision 1.10  2010/02/03 16:13:52  abbott
690 // Added new single word tags for specifying the ordering in PPMonoid
691 // pseudo-ctors.
692 //
693 // Revision 1.9  2010/02/02 16:44:31  abbott
694 // Added radical & IsRadical (via mem fns myRadical & myIsRadical)
695 // for PPMonoidElems.
696 //
697 // Revision 1.8  2009/09/22 14:01:33  bigatti
698 // -- added myCmpWDegPartial (ugly name, I know....)
699 // -- cleaned up and realigned code in PPMonoid*.C files
700 //
701 // Revision 1.7  2007/12/05 11:06:24  bigatti
702 // -- changed "size_t StdDeg/myStdDeg(f)" into "long"  (and related functions)
703 // -- changed "log/myLog(f, i)" into "MaxExponent/myMaxExponent(f, i)"
704 // -- fixed bug in "IsOne(ideal)" in SparsePolyRing.C
705 //
706 // Revision 1.6  2007/12/04 14:27:06  bigatti
707 // -- changed "log(pp, i)" into "exponent(pp, i)"
708 //
709 // Revision 1.5  2007/10/30 17:14:07  abbott
710 // Changed licence from GPL-2 only to GPL-3 or later.
711 // New version for such an important change.
712 //
713 // Revision 1.4  2007/05/31 14:54:31  bigatti
714 // -- now using AreDistinct and AreArityConsistent for sanity check on
715 //    indet names
716 //
717 // Revision 1.2  2007/05/03 10:35:23  abbott
718 // Added new PPMonoidEvZZ with (virtually) unlimited exponents.
719 // Modified test-PPMonoid1.C accordingly.
720 // Added warning in doc about silent/unchecked exponent overflow in other
721 // PPMonoids.
722 //
723 // Revision 1.1.1.1  2007/03/09 15:16:11  abbott
724 // Imported files
725 //
726 // Revision 1.11  2007/03/08 18:22:29  cocoa
727 // Just whitespace cleaning.
728 //
729 // Revision 1.10  2007/03/08 17:43:11  cocoa
730 // Swapped order of args to the NewPPMonoid pseudo ctors.
731 //
732 // Revision 1.9  2007/03/08 11:07:12  cocoa
733 // Made pseudo ctors for polynomial rings more uniform.  This allowed me to
734 // remove an include of CoCoA/symbol.H  from the RingDistrM*.H files, but then
735 // I had to put the include in several .C files.
736 //
737 // Revision 1.8  2006/12/06 17:35:58  cocoa
738 // -- style: RawPtr args are now called "raw.."
739 //
740 // Revision 1.7  2006/11/24 17:04:32  cocoa
741 // -- reorganized includes of header files
742 //
743 // Revision 1.6  2006/11/23 17:39:26  cocoa
744 // -- added #include
745 //
746 // Revision 1.5  2006/11/16 11:27:20  cocoa
747 // -- reinserted myRefCountZero(): sometimes really necessary, in general safe
748 //
749 // Revision 1.4  2006/11/14 17:29:20  cocoa
750 // -- commented out myRefCountZero() (not necessary???)
751 //
752 // Revision 1.3  2006/10/06 14:04:14  cocoa
753 // Corrected position of #ifndef in header files.
754 // Separated CoCoA_ASSERT into assert.H from config.H;
755 // many minor consequential changes (have to #include assert.H).
756 // A little tidying of #include directives (esp. in Max's code).
757 //
758 // Revision 1.2  2006/08/07 21:23:25  cocoa
759 // Removed almost all publicly visible references to SmallExponent_t;
760 // changed to long in all PPMonoid functions and SparsePolyRing functions.
761 // DivMask remains to sorted out.
762 //
763 // Revision 1.1.1.1  2006/05/30 11:39:37  cocoa
764 // Imported files
765 //
766 // Revision 1.6  2006/03/15 18:09:31  cocoa
767 // Changed names of member functions which print out their object
768 // into myOutputSelf -- hope this will appease the Intel C++ compiler.
769 //
770 // Revision 1.5  2006/03/14 17:21:18  cocoa
771 // Moved concrete PPMonoid impls entirely into their respective .C files.
772 // Now the corresponding .H files are very compact.
773 //
774 // Revision 1.4  2006/03/12 21:28:33  cocoa
775 // Major check in after many changes
776 //
777 // Revision 1.3  2006/02/20 22:41:20  cocoa
778 // All forms of the log function for power products now return SmallExponent_t
779 // (instead of int).  exponents now resizes the vector rather than requiring
780 // the user to pass in the correct size.
781 //
782 // Revision 1.2  2006/01/17 10:23:08  cocoa
783 // Updated DivMask; many consequential changes.
784 // A few other minor fixes.
785 //
786 // Revision 1.1.1.1  2005/10/17 10:46:54  cocoa
787 // Imported files
788 //
789 // Revision 1.7  2005/10/11 16:37:30  cocoa
790 // Added new small prime finite field class (see RingFpDouble).
791 //
792 // Cleaned makefiles and configuration script.
793 //
794 // Tidied PPMonoid code (to eliminate compiler warnings).
795 //
796 // Fixed bug in RingFloat::myIsInteger.
797 //
798 // Revision 1.6  2005/08/08 16:36:32  cocoa
799 // Just checking in before going on holiday.
800 // Don't really recall what changes have been made.
801 // Added IsIndet function for RingElem, PPMonoidElem,
802 // and a member function of OrdvArith.
803 // Improved the way failed assertions are handled.
804 //
805 // Revision 1.5  2005/07/19 15:30:20  cocoa
806 // A first attempt at iterators over sparse polynomials.
807 // Main additions are to SparsePolyRing, DistrMPoly*.
808 // Some consequential changes to PPMonoid*.
809 //
810 // Revision 1.4  2005/07/08 15:09:28  cocoa
811 // Added new symbol class (to represent names of indets).
812 // Integrated the new class into concrete polynomial rings
813 // and PPMonoid -- many consequential changes.
814 // Change ctors for the "inline" sparse poly rings: they no
815 // longer expect a PPMonoid, but build their own instead
816 // (has to be a PPMonoidOv).
817 //
818 // Revision 1.3  2005/07/01 16:08:15  cocoa
819 // Friday check-in.  Major change to structure under PolyRing:
820 // now SparsePolyRing and DUPolyRing are separated (in preparation
821 // for implementing iterators).
822 //
823 // A number of other relatively minor changes had to be chased through
824 // (e.g. IndetPower).
825 //
826 // Revision 1.2  2005/06/23 15:42:41  cocoa
827 // Fixed typo in GNU fdl -- all doc/*.txt files affected.
828 // Minor corrections to PPMonoid (discovered while writing doc).
829 //
830 // Revision 1.1  2005/06/22 14:47:56  cocoa
831 // PPMonoids and PPMonoidElems updated to mirror the structure
832 // used for rings and RingElems.  Many consequential changes.
833 //
834