1 //   Copyright (c)  2005,2007,2010  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 PPMonoidEvOvImpl
20 
21 #include "CoCoA/PPMonoidEvOv.H"
22 
23 #include "CoCoA/BigIntOps.H"
24 #include "CoCoA/DivMask.H"
25 #include "CoCoA/MemPool.H"
26 #include "CoCoA/OrdvArith.H"
27 #include "CoCoA/PPMonoid.H"
28 #include "CoCoA/PPOrdering.H"
29 #include "CoCoA/assert.H"
30 #include "CoCoA/convert.H"
31 #include "CoCoA/degree.H"
32 #include "CoCoA/error.H"
33 #include "CoCoA/matrix.H"
34 #include "CoCoA/symbol.H"
35 
36 #include <algorithm>
37 using std::min;
38 using std::max;
39 //using std::swap;
40 #include <cstring>
41 using std::memcpy;
42 #include <iostream>
43 using std::ostream;
44 #include<limits>
45 using std::numeric_limits;
46 #include <memory>
47 using std::unique_ptr;
48 #include <vector>
49 using std::vector;
50 
51 
52 namespace CoCoA
53 {
54 
55   /*-- class PPMonoidEvOvImpl ---------------------------------------*/
56   /**
57 
58   \brief Implementation of power product monoid for fast generic use
59 
60   PPMonoidEvOv implements a power product monoid for generic use as
61   it stores exp vector and order vector.
62   Compared with PPMonoidSafe, PPMonoidEvOv is:
63   - slower for gcd/lcm because it has to update the order vector;
64   - faster for comparisons expecially with matrix defined orderings.
65 
66   So this type is good for you if
67   (1) you do not perform many gcd/lcm
68   (2) you need efficiency in ordering test
69 
70   */
71   /*-----------------------------------------------------------------*/
72 
73   class PPMonoidEvOvImpl: public PPMonoidBase
74   {
75     typedef PPMonoidElemRawPtr RawPtr;           // just to save typing
76     typedef PPMonoidElemConstRawPtr ConstRawPtr; // just to save typing
77     typedef OrdvArith::OrdvElem OrdvElem;        // just to save typing
78 
79     static const unsigned long ourMaxExp;        // defined below; value is just numeric_limits<SmallExponent_t>::max()
80 
81   public:
82     PPMonoidEvOvImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord);
83     ~PPMonoidEvOvImpl();
84   private: // disable copy ctor and assignment
85     explicit PPMonoidEvOvImpl(const PPMonoidEvOvImpl& copy);  // NEVER DEFINED -- copy ctor disabled
86     PPMonoidEvOvImpl& operator=(const PPMonoidEvOvImpl& rhs); // NEVER DEFINED -- assignment disabled
87 
88   public:
89     void contents() const; // FOR DEBUGGING ONLY
90 
91     const std::vector<PPMonoidElem>& myIndets() const;                  ///< std::vector whose n-th entry is n-th indet as PPMonoidElem
92 
93     // The functions below are operations on power products owned by PPMonoidEvOvImpl
94     const PPMonoidElem& myOne() const;
95     using PPMonoidBase::myNew;    // disable warnings of overloading
96     PPMonoidElemRawPtr myNew() const;                                   ///< ctor from nothing
97     PPMonoidElemRawPtr myNew(PPMonoidElemConstRawPtr rawpp) const;      ///< ctor by assuming ownership
98     PPMonoidElemRawPtr myNew(const std::vector<long>& expv) const;      ///< ctor from exp vector
99 //NYI    PPMonoidElemRawPtr myNew(const std::vector<BigInt>& EXPV) const;///< ctor from exp vector
100     void myDelete(RawPtr rawpp) const;                                  ///< dtor, frees pp
101     void mySwap(RawPtr rawpp1, RawPtr rawpp2) const;                    ///< swap(pp1, pp2);
102     void myAssignOne(RawPtr rawpp) const;                               ///< pp = 1
103     void myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const;              ///< p = pp1
104     void myAssign(RawPtr rawpp, const std::vector<long>& expv) const;   ///< pp = expv (assign from exp vector)
105 
106     void myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = pp1*pp2
107     using PPMonoidBase::myMulIndetPower;    // disable warnings of overloading
108     void myMulIndetPower(RawPtr rawpp, long indet, long exp) const;           ///< pp *= indet^exp, assumes exp >= 0
109     void myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = pp1/pp2
110     void myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1/gcd(pp1,pp2)
111     void myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = gcd(pp1,pp2)
112     void myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< pp = lcm(pp1,pp2)
113     void myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const;                   ///< pp = radical(pp1)
114     void myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long exp) const;   ///< pp = pp1^exp, assumes exp >= 0
115     void myPowerOverflowCheck(ConstRawPtr rawpp1, long exp) const;            ///< throw if pp1^exp would overflow, assumes exp >= 0
116 
117     bool myIsOne(ConstRawPtr rawpp) const;                              ///< is pp = 1?
118     bool myIsIndet(long& index, ConstRawPtr rawpp) const;               ///< true iff pp is an indet
119     bool myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;     ///< are pp1 & pp2 coprime?
120     bool myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;       ///< is pp1 equal to pp2?
121     bool myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;   ///< does pp2 divide pp1?
122     bool myIsSqFree(ConstRawPtr rawpp) const;                           ///< is pp equal to its radical?
123 
124     int myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;            ///< -1,0,1 as pp1 < = > pp2
125     long myStdDeg(ConstRawPtr rawpp) const;                             ///< standard degree of pp
126     void myWDeg(degree& d, ConstRawPtr rawpp) const;                    ///< d = grading(pp)
127     int myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const;        ///< <0, =0, >0 as wdeg(pp1) < = > wdeg(pp2)
128     int myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long) const; ///< as myCmpWDeg wrt the first weights
129     long myExponent(ConstRawPtr rawpp, long indet) const;             ///< exponent of indet in pp
130     void myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const;  ///< EXP = exponent of indet in pp
131     void myExponents(std::vector<long>& expv, ConstRawPtr rawpp) const;      ///< expv[i] = exponent(pp,i)
132     void myBigExponents(std::vector<BigInt>& v, ConstRawPtr rawpp) const;  ///< get exponents, SHOULD BE myExponents ???
133     void myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const;   ///< v[i] = true if i-th indet has exponent != 0
134     void myOutputSelf(std::ostream& out) const;                      ///< out << PPM
135     // INHERITED DEFINITION of virtual  void myOutput(std::ostream& out, ConstRawPtr rawpp) const;
136     void myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const;   ///< print pp in debugging format???
137 
138 
139   private: // auxiliary functions
140     SmallExponent_t* myExpv(RawPtr) const;
141     const SmallExponent_t* myExpv(ConstRawPtr) const;
142     OrdvElem* myOrdv(RawPtr) const;
143     const OrdvElem* myOrdv(ConstRawPtr) const;
144 
145     void myComputeDivMask(DivMask& dm, const DivMaskRule& DivMaskImpl, ConstRawPtr rawpp) const; ///< used by PPWithMask
146     void myComputeOrdv(RawPtr) const;
147     bool myCheckExponents(const std::vector<long>& expv) const;
148 
149   private: // data members
150     ///@name Class members
151     //@{
152     OrdvArith::reference myOrdvArith;  //??? should be const
153     const long myOrdvSize;        ///< used only in myExpv
154     const long myEntrySize;       ///< size in bytes
155     mutable MemPool myMemMgr;     // IMPORTANT: this must come *before* myIndetVector and myOnePtr.
156 //???    vector<SmallExponent_t> myDelta;
157     vector<PPMonoidElem> myIndetVector; ///< the indets as PPMonoidElems
158     unique_ptr<PPMonoidElem> myOnePtr;
159     //@}
160   };
161 
162 
163   // static variable
164   const unsigned long PPMonoidEvOvImpl::ourMaxExp = numeric_limits<SmallExponent_t>::max();
165 
166 
167   // File local inline functions
168 
myExpv(RawPtr rawpp)169   inline SmallExponent_t* PPMonoidEvOvImpl::myExpv(RawPtr rawpp) const
170   {
171     return reinterpret_cast<SmallExponent_t*>(static_cast<char*>(rawpp.myRawPtr()) + myOrdvSize);
172   }
173 
174 
myExpv(ConstRawPtr rawpp)175   inline const SmallExponent_t* PPMonoidEvOvImpl::myExpv(ConstRawPtr rawpp) const
176   {
177     return reinterpret_cast<const SmallExponent_t*>(static_cast<const char*>(rawpp.myRawPtr()) + myOrdvSize);
178   }
179 
180 
myOrdv(RawPtr rawpp)181   inline PPMonoidEvOvImpl::OrdvElem* PPMonoidEvOvImpl::myOrdv(RawPtr rawpp) const
182   {
183     return static_cast<OrdvElem*>(rawpp.myRawPtr());
184 
185   }
186 
myOrdv(ConstRawPtr rawpp)187   inline const PPMonoidEvOvImpl::OrdvElem* PPMonoidEvOvImpl::myOrdv(ConstRawPtr rawpp) const
188   {
189     return static_cast<const OrdvElem*>(rawpp.myRawPtr());
190   }
191 
192 
myCheckExponents(const std::vector<long> & expv)193   bool PPMonoidEvOvImpl::myCheckExponents(const std::vector<long>& expv) const
194   {
195     // Check expv.size == myNumIndets.
196     // Check exps are non-neg and not too big.
197     if (len(expv) != myNumIndets) return false;
198     for (long i=0; i < myNumIndets; ++i)
199       if (expv[i] < 0 || static_cast<unsigned long>(expv[i]) > numeric_limits<SmallExponent_t>::max()) return false;
200     return true;
201   }
202 
203 
204   //----   Constructors & destructor   ----//
205 
PPMonoidEvOvImpl(const std::vector<symbol> & IndetNames,const PPOrdering & ord)206   PPMonoidEvOvImpl::PPMonoidEvOvImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord):
207       PPMonoidBase(ord, IndetNames),
208       myOrdvArith(NewOrdvArith(ord)),
209       myOrdvSize(sizeof(OrdvElem)*OrdvWords(myOrdvArith)),
210       myEntrySize(myOrdvSize + sizeof(SmallExponent_t)*myNumIndets),
211       myMemMgr(myEntrySize, "PPMonoidEvOvImpl.myMemMgr"),
212       myIndetVector()
213   {
214     // std::cout << "------PPMonoidEvOvImpl:NewOrdvArith-called" << std::endl;
215     myRefCountInc();  // this is needed for exception cleanliness, in case one of the lines below throws
216     myOnePtr.reset(new PPMonoidElem(PPMonoid(this)));
217     {
218       // IMPORTANT: this block destroys pp *before* the call to myRefCountZero.
219       PPMonoidElem pp(PPMonoid(this));
220       vector<long> expv(myNumIndets);
221       for (long i=0; i < myNumIndets; ++i)
222       {
223         expv[i] = 1;
224         myAssign(raw(pp), expv);
225         myIndetVector.push_back(pp);
226         expv[i] = 0;
227       }
228     }
229     myRefCountZero();
230   }
231 
232 
~PPMonoidEvOvImpl()233   PPMonoidEvOvImpl::~PPMonoidEvOvImpl()
234   {}
235 
236 /////////////////////////////////////////////////////////////////////////////
237 
238 
myComputeOrdv(RawPtr rawpp)239   inline void PPMonoidEvOvImpl::myComputeOrdv(RawPtr rawpp) const
240   {
241     const SmallExponent_t* const expv = myExpv(rawpp);
242     vector<long> ExpvCopy(myNumIndets);
243     for (long i=0; i < myNumIndets; ++i)
244       ExpvCopy[i] = NumericCast<long>(expv[i]);
245     myOrdvArith->myAssignFromExpv(myOrdv(rawpp), ExpvCopy);
246   }
247 
248 
myIndets()249   const std::vector<PPMonoidElem>& PPMonoidEvOvImpl::myIndets() const
250   {
251     return myIndetVector;
252   }
253 
254 
myOne()255   const PPMonoidElem& PPMonoidEvOvImpl::myOne() const
256   {
257     return *myOnePtr;
258   }
259 
260 
myNew()261   PPMonoidElemRawPtr PPMonoidEvOvImpl::myNew() const
262   {
263     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
264     myAssignOne(rawpp); // cannot throw
265     return rawpp;
266   }
267 
myNew(PPMonoidElemConstRawPtr rawcopypp)268   PPMonoidElemRawPtr PPMonoidEvOvImpl::myNew(PPMonoidElemConstRawPtr rawcopypp) const
269   {
270     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
271     myAssign(rawpp, rawcopypp); // cannot throw
272     return rawpp;
273   }
274 
275 
myNew(const std::vector<long> & expv)276   PPMonoidElemRawPtr PPMonoidEvOvImpl::myNew(const std::vector<long>& expv) const
277   {
278     CoCoA_ASSERT(myCheckExponents(expv));
279     PPMonoidElemRawPtr rawpp(myMemMgr.alloc());
280     myAssign(rawpp, expv); // cannot throw
281     return rawpp;
282   }
283 
284 
myAssignOne(RawPtr rawpp)285   void PPMonoidEvOvImpl::myAssignOne(RawPtr rawpp) const
286   {
287     SmallExponent_t* const expv = myExpv(rawpp);
288     for (long i = 0; i < myNumIndets; ++i)
289       expv[i] = 0;
290     myOrdvArith->myAssignZero(myOrdv(rawpp));
291   }
292 
293 
myAssign(RawPtr rawpp,ConstRawPtr rawpp1)294   void PPMonoidEvOvImpl::myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const
295   {
296     if (rawpp == rawpp1) return;
297 //     // This code assumes that myEntrySize is an exact multiple of sizeof(int).
298 //     int* const expv = static_cast<int*>(rawpp.myRawPtr());
299 //     const int* const expv1 = static_cast<const int*>(rawpp1.myRawPtr());
300 //     const long NumWords = myEntrySize/sizeof(int);
301 //     std::copy(expv1, expv1+NumWords, expv);  // does this work???
302 
303     memcpy(myOrdv(rawpp), myOrdv(rawpp1), myEntrySize);
304 
305 // This would be a cleaner (but slower) way of achieving the same result...
306 //     SmallExponent_t* const exp = myExpv(rawpp);
307 //     const SmallExponent_t* const exp_src = myExpv(src);
308 //     for (long i=0 ; i<myNumIndets ; ++i )  exp[i] = exp_src[i];
309 //     myOrdvArith->myAssign(myOrdv(rawpp), myOrdv(src));
310   }
311 
myAssign(RawPtr rawpp,const vector<long> & expv)312   void PPMonoidEvOvImpl::myAssign(RawPtr rawpp, const vector<long>& expv) const
313   {
314     CoCoA_ASSERT(myCheckExponents(expv));
315 
316     SmallExponent_t* const expv2 = myExpv(rawpp);
317     for (long i = 0; i < myNumIndets; ++i)
318       expv2[i] = NumericCast<SmallExponent_t>(expv[i]);
319 
320     myOrdvArith->myAssignFromExpv(myOrdv(rawpp), expv);
321   }
322 
323 
myDelete(RawPtr rawpp)324   void PPMonoidEvOvImpl::myDelete(RawPtr rawpp) const
325   {
326     myMemMgr.free(rawpp.myRawPtr());
327   }
328 
329 
mySwap(RawPtr rawpp1,RawPtr rawpp2)330   void PPMonoidEvOvImpl::mySwap(RawPtr rawpp1, RawPtr rawpp2) const
331   {
332     if (rawpp1 == rawpp2) return;
333     // This code assumes that myEntrySize is an exact multiple of sizeof(int)
334     int* v1 = static_cast<int*>(rawpp1.myRawPtr());
335     int* v2 = static_cast<int*>(rawpp2.myRawPtr());
336     const long NumWords = myEntrySize/sizeof(int);
337     for (long i=0; i < NumWords; ++i)
338       std::swap(v1[i], v2[i]);
339   }
340 
341 
myMul(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)342   void PPMonoidEvOvImpl::myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
343   {
344     // No worries about aliasing.
345     SmallExponent_t* const expv = myExpv(rawpp);
346     const SmallExponent_t* const expv1 = myExpv(rawpp1);
347     const SmallExponent_t* const expv2 = myExpv(rawpp2);
348     for (long i=0; i < myNumIndets; ++i)
349     {
350       CoCoA_ASSERT("Exponent Overflow" && expv1[i] <= std::numeric_limits<SmallExponent_t>::max()-expv2[i]);
351       expv[i] = expv1[i] + expv2[i];
352     }
353     myOrdvArith->myMul(myOrdv(rawpp), myOrdv(rawpp1), myOrdv(rawpp2));
354   }
355 
356 
myMulIndetPower(RawPtr rawpp,long indet,long exp)357   void PPMonoidEvOvImpl::myMulIndetPower(RawPtr rawpp, long indet, long exp) const  // assumes exp >= 0
358   {
359     CoCoA_ASSERT(exp >= 0);
360     CoCoA_ASSERT(0 <= indet && indet < myNumIndets);
361     SmallExponent_t* const expv = myExpv(rawpp);
362     // If CoCoA_DEBUG active, check for exponent overflow...
363     CoCoA_ASSERT("Exponent Overflow" && ourMaxExp - expv[indet] >= static_cast<unsigned long>(exp));
364     expv[indet] += static_cast<SmallExponent_t>(exp);  // cast to keep M$ compiler quiet
365     myOrdvArith->myMulIndetPower(myOrdv(rawpp), indet, exp);
366   }
367 
368 
myDiv(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)369   void PPMonoidEvOvImpl::myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
370   {
371     // No worries about aliasing.
372     SmallExponent_t* const expv = myExpv(rawpp);
373     const SmallExponent_t* const expv1 = myExpv(rawpp1);
374     const SmallExponent_t* const expv2 = myExpv(rawpp2);
375     for (long i=0; i < myNumIndets; ++i)
376     {
377       CoCoA_ASSERT("Exponent Underflow" && expv1[i] >= expv2[i]);
378       expv[i] = expv1[i] - expv2[i];
379     }
380     myOrdvArith->myDiv(myOrdv(rawpp), myOrdv(rawpp1), myOrdv(rawpp2));
381   }
382 
383 
myColon(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)384   void PPMonoidEvOvImpl::myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
385   {
386     // No worries about aliasing.
387     SmallExponent_t* const expv = myExpv(rawpp);
388     const SmallExponent_t* const expv1 = myExpv(rawpp1);
389     const SmallExponent_t* const expv2 = myExpv(rawpp2);
390 
391     for (long i = 0; i < myNumIndets; ++i)
392     {
393       if (expv1[i] > expv2[i])
394         expv[i] = expv1[i] - expv2[i];
395       else
396         expv[i] = 0;
397     }
398     myComputeOrdv(rawpp);
399   }
400 
401 
myGcd(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)402   void PPMonoidEvOvImpl::myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
403   {
404     // No worries about aliasing.
405     SmallExponent_t* const expv = myExpv(rawpp);
406     const SmallExponent_t* const expv1 = myExpv(rawpp1);
407     const SmallExponent_t* const expv2 = myExpv(rawpp2);
408 
409     for (long i = 0; i < myNumIndets; ++i)
410       expv[i] = min(expv1[i], expv2[i]);
411 
412     myComputeOrdv(rawpp);
413   }
414 
415 
myLcm(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)416   void PPMonoidEvOvImpl::myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
417   {
418     // No worries about aliasing.
419     SmallExponent_t* const expv = myExpv(rawpp);
420     const SmallExponent_t* const expv1 = myExpv(rawpp1);
421     const SmallExponent_t* const expv2 = myExpv(rawpp2);
422 
423     for (long i = 0; i < myNumIndets; ++i)
424       expv[i] = max(expv1[i], expv2[i]);
425 
426     myComputeOrdv(rawpp);
427   }
428 
429 
myRadical(RawPtr rawpp,ConstRawPtr rawpp1)430   void PPMonoidEvOvImpl::myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const
431   {
432     SmallExponent_t* const expv = myExpv(rawpp);
433     const SmallExponent_t* const expv1 = myExpv(rawpp1);
434 
435     for (long i = 0; i < myNumIndets; ++i)
436       expv[i] = (expv1[i] > 0);
437 
438     myComputeOrdv(rawpp);
439   }
440 
441 
myPowerSmallExp(RawPtr rawpp,ConstRawPtr rawpp1,long LongExp)442   void PPMonoidEvOvImpl::myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long LongExp) const  // assumes exp >= 0
443   {
444     CoCoA_ASSERT(LongExp >= 0);
445 #ifdef CoCoA_DEBUG
446     myPowerOverflowCheck(rawpp1, LongExp);
447 #endif
448     if (static_cast<unsigned long>(LongExp) > ourMaxExp)
449       CoCoA_THROW_ERROR(ERR::ExpTooBig, "PPMonoidEvOvImpl::myPowerSmallExp");
450     const SmallExponent_t exp = static_cast<SmallExponent_t>(LongExp);
451 
452     SmallExponent_t* const expv = myExpv(rawpp);
453     const SmallExponent_t* const expv1 = myExpv(rawpp1);
454     for (long i = 0; i < myNumIndets; ++i)
455       expv[i] = exp * expv1[i];
456     myOrdvArith->myPower(myOrdv(rawpp), myOrdv(rawpp1), exp);
457   }
458 
459 
myPowerOverflowCheck(ConstRawPtr rawpp,long LongExp)460   void PPMonoidEvOvImpl::myPowerOverflowCheck(ConstRawPtr rawpp, long LongExp) const
461   {
462     if (LongExp == 0 || LongExp == 1) return;
463     CoCoA_ASSERT(LongExp >= 0);
464     const char* const FnName = "PPMonoidEvOvImpl::myPowerOverflowCheck";
465     if (static_cast<unsigned long>(LongExp) > ourMaxExp)
466       CoCoA_THROW_ERROR(ERR::ExpTooBig, FnName);
467     const SmallExponent_t exp = static_cast<SmallExponent_t>(LongExp);
468     const SmallExponent_t limit = ourMaxExp/exp;
469 
470     const SmallExponent_t* const expv = myExpv(rawpp);
471     for (long i = 0; i < myNumIndets; ++i)
472     {
473       if (expv[i] > limit)
474         CoCoA_THROW_ERROR(ERR::ExpTooBig, FnName);
475     }
476     // Check separately for overflow in ordv
477     myOrdvArith->myPowerOverflowCheck(myOrdv(rawpp), exp);
478   }
479 
480 
myIsOne(ConstRawPtr rawpp)481   bool PPMonoidEvOvImpl::myIsOne(ConstRawPtr rawpp) const
482   {
483     const SmallExponent_t* const expv = myExpv(rawpp);
484 
485     for (long i = 0; i < myNumIndets; ++i)
486       if (expv[i] != 0) return false;
487 
488     return true;
489   }
490 
491 
myIsIndet(long & index,ConstRawPtr rawpp)492   bool PPMonoidEvOvImpl::myIsIndet(long& index, ConstRawPtr rawpp) const
493   {
494     const SmallExponent_t* const expv = myExpv(rawpp);
495     long j = myNumIndets;
496     for (long i = 0; i < myNumIndets; ++i)
497     {
498       if (expv[i] == 0) continue;
499       if (j != myNumIndets || expv[i] != 1) return false;
500       j = i;
501     }
502     if (j == myNumIndets) return false;
503     index = j;
504     return true;
505   }
506 
507 
myIsCoprime(ConstRawPtr rawpp1,ConstRawPtr rawpp2)508   bool PPMonoidEvOvImpl::myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
509   {
510     const SmallExponent_t* const expv1 = myExpv(rawpp1);
511     const SmallExponent_t* const expv2 = myExpv(rawpp2);
512 
513     for (long i = 0; i < myNumIndets; ++i)
514       if (expv1[i] != 0 && expv2[i] != 0) return false;
515 
516     return true;
517   }
518 
519 
myIsEqual(ConstRawPtr rawpp1,ConstRawPtr rawpp2)520   bool PPMonoidEvOvImpl::myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
521   {
522     return myOrdvArith->myCmp(myOrdv(rawpp1), myOrdv(rawpp2)) == 0;
523   }
524 
525 
myIsDivisible(ConstRawPtr rawpp1,ConstRawPtr rawpp2)526   bool PPMonoidEvOvImpl::myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
527   {
528     const SmallExponent_t* const expv1 = myExpv(rawpp1);
529     const SmallExponent_t* const expv2 = myExpv(rawpp2);
530 
531     for (long i = 0; i < myNumIndets; ++i)
532       if (expv1[i] < expv2[i]) return false;
533 
534     return true;
535   }
536 
537 
myIsSqFree(ConstRawPtr rawpp)538   bool PPMonoidEvOvImpl::myIsSqFree(ConstRawPtr rawpp) const
539   {
540     const SmallExponent_t* const expv = myExpv(rawpp);
541 
542     for (long i = 0; i < myNumIndets; ++i)
543       if (expv[i] > 1) return false;
544 
545     return true;
546   }
547 
548 
myCmp(ConstRawPtr rawpp1,ConstRawPtr rawpp2)549   int PPMonoidEvOvImpl::myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
550   {
551     return myOrdvArith->myCmp(myOrdv(rawpp1), myOrdv(rawpp2));
552   }
553 
554 
555 // // should potentially skip the first few packed ordv entries???
556 // int PPMonoidEvOvImpl::myHomogCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
557 // {
558 //   return myOrdvArith->myCmp(myOrdv(rawpp1), myOrdv(rawpp2));
559 // }
560 
561 
myStdDeg(ConstRawPtr rawpp)562   long PPMonoidEvOvImpl::myStdDeg(ConstRawPtr rawpp) const
563   {
564     const SmallExponent_t* const expv = myExpv(rawpp);
565     long d=0;
566     for (long i=0; i < myNumIndets; ++i)
567       d += expv[i];
568     return d;
569   }
570 
571 
myWDeg(degree & d,ConstRawPtr rawpp)572   void PPMonoidEvOvImpl::myWDeg(degree& d, ConstRawPtr rawpp) const
573   {
574     myOrdvArith->myWDeg(d, myOrdv(rawpp));
575   }
576 
577 
myCmpWDeg(ConstRawPtr rawpp1,ConstRawPtr rawpp2)578   int PPMonoidEvOvImpl::myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const
579   {
580     return myOrdvArith->myCmpWDeg(myOrdv(rawpp1), myOrdv(rawpp2));
581   }
582 
583 
myCmpWDegPartial(ConstRawPtr rawpp1,ConstRawPtr rawpp2,long i)584   int PPMonoidEvOvImpl::myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long i) const
585   {
586     return myOrdvArith->myCmpWDegPartial(myOrdv(rawpp1), myOrdv(rawpp2), i);
587   }
588 
589 
myExponent(ConstRawPtr rawpp,long indet)590   long PPMonoidEvOvImpl::myExponent(ConstRawPtr rawpp, long indet) const
591   {
592     CoCoA_ASSERT(0 <= indet && indet < myNumIndets);
593     return NumericCast<long>(myExpv(rawpp)[indet]);
594   }
595 
myBigExponent(BigInt & EXP,ConstRawPtr rawpp,long indet)596   void PPMonoidEvOvImpl::myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const
597   {
598     CoCoA_ASSERT(0 <= indet && indet < myNumIndets);
599     EXP = myExpv(rawpp)[indet];
600   }
601 
602 
myExponents(std::vector<long> & expv,ConstRawPtr rawpp)603   void PPMonoidEvOvImpl::myExponents(std::vector<long>& expv, ConstRawPtr rawpp) const
604   {
605     CoCoA_ASSERT(len(expv) == myNumIndets);
606     const SmallExponent_t* const v = myExpv(rawpp);
607     for (long i=0; i < myNumIndets; ++i)
608       expv[i] = NumericCast<long>(v[i]);
609   }
610 
611 
myBigExponents(std::vector<BigInt> & expv,ConstRawPtr rawpp)612   void PPMonoidEvOvImpl::myBigExponents(std::vector<BigInt>& expv, ConstRawPtr rawpp) const
613   {
614     CoCoA_ASSERT(len(expv) == myNumIndets);
615     const SmallExponent_t* const v = myExpv(rawpp);
616     for (long i=0; i < myNumIndets; ++i)  expv[i] = v[i];
617   }
618 
619 
myIndetsIn(std::vector<bool> & v,ConstRawPtr rawpp)620   void PPMonoidEvOvImpl::myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const
621   {
622     CoCoA_ASSERT(len(v) == myNumIndets);
623     const SmallExponent_t* const expv = myExpv(rawpp);
624     for (long i=0; i < myNumIndets; ++i)
625       if (expv[i] != 0) v[i] = true;
626   }
627 
628 
myComputeDivMask(DivMask & dm,const DivMaskRule & DivMaskImpl,ConstRawPtr rawpp)629   void PPMonoidEvOvImpl::myComputeDivMask(DivMask& dm, const DivMaskRule& DivMaskImpl, ConstRawPtr rawpp) const
630   {
631     DivMaskImpl->myAssignFromExpv(dm, myExpv(rawpp), myNumIndets);
632   }
633 
634 
myOutputSelf(std::ostream & out)635   void PPMonoidEvOvImpl::myOutputSelf(std::ostream& out) const
636   {
637     if (!out) return;  // short-cut for bad ostreams
638     out << "PPMonoidEvOv(" << myNumIndets << ", " << myOrd << ")";
639   }
640 
641 
myDebugPrint(std::ostream & out,ConstRawPtr rawpp)642   void PPMonoidEvOvImpl::myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const
643   {
644     if (!out) return;  // short-cut for bad ostreams
645 
646     out << "DEBUG PP: myNumIndets=" << myNumIndets << ", exps=[";
647     for (long i=0; i < myNumIndets; ++i)
648       out << myExponent(rawpp, i) << " ";
649     out << "]" << std::endl;
650   }
651 
652 
NewPPMonoidEvOv(const std::vector<symbol> & IndetNames,const PPOrdering & ord)653   PPMonoid NewPPMonoidEvOv(const std::vector<symbol>& IndetNames, const PPOrdering& ord)
654   {
655     // Sanity check on the indet names given.
656     const long nvars = NumIndets(ord);
657 
658     if (len(IndetNames) != nvars)
659       CoCoA_THROW_ERROR(ERR::BadNumIndets, "NewPPMonoidEvOv(IndetNames,ord)");
660     if (!AreDistinct(IndetNames))
661       CoCoA_THROW_ERROR(ERR::BadIndetNames, "NewPPMonoidEvOv(IndetNames,ord)");
662     if (!AreArityConsistent(IndetNames))
663       CoCoA_THROW_ERROR(ERR::BadIndetNames, "NewPPMonoidEvOv(IndetNames,ord)");
664 
665     // Inefficient quadratic loop -- speed is probably not important.
666     for (long i=0; i < nvars; ++i)
667       for (long j=i+1; j < nvars; ++j)
668         if (IndetNames[i] == IndetNames[j])
669           CoCoA_THROW_ERROR(ERR::BadIndetNames, "NewPPMonoidEvOv(IndetNames,ord)");
670 
671     return PPMonoid(new PPMonoidEvOvImpl(IndetNames, ord));
672   }
673 
NewPPMonoidEvOv(const std::vector<symbol> & IndetNames,const PPOrderingCtor & OrdCtor)674   PPMonoid NewPPMonoidEvOv(const std::vector<symbol>& IndetNames, const PPOrderingCtor& OrdCtor)
675   {
676     return NewPPMonoidEvOv(IndetNames, OrdCtor(len(IndetNames)));
677   }
678 
679 
680 } // end of namespace CoCoA
681 
682 
683 // RCS header/log in the next few lines
684 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/PPMonoidEvOv.C,v 1.41 2020/06/17 15:49:25 abbott Exp $
685 // $Log: PPMonoidEvOv.C,v $
686 // Revision 1.41  2020/06/17 15:49:25  abbott
687 // Summary: Changed CoCoA_ERROR into CoCoA_THROW_ERROR
688 //
689 // Revision 1.40  2020/02/11 16:56:41  abbott
690 // Summary: Corrected last update (see redmine 969)
691 //
692 // Revision 1.39  2020/02/11 16:12:18  abbott
693 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969
694 //
695 // Revision 1.38  2019/03/04 10:31:45  abbott
696 // Summary: Changed auto_ptr into unqiue_ptr
697 //
698 // Revision 1.37  2018/05/18 12:15:04  bigatti
699 // -- renamed IntOperations --> BigIntOps
700 //
701 // Revision 1.36  2017/12/01 17:29:21  bigatti
702 // // -- updated Copyright line
703 // // -- removed doxygen initial comment
704 // // -- some commented out debugging info
705 //
706 // Revision 1.35  2017/04/18 12:50:06  abbott
707 // Summary: Corrected ifdef use of CoCoA_THREADSAFE_HACK and CoCoA_DEBUG
708 //
709 // Revision 1.34  2016/11/03 12:25:25  abbott
710 // Summary: Changed IsRadical (for PPMonoidElem) into IsSqFree
711 //
712 // Revision 1.33  2015/12/01 13:11:01  abbott
713 // Summary: Changed mem fn PPOrderingCtor::myCtor into operator(); also for ModuleOrderingCtor; see issue 829
714 //
715 // Revision 1.32  2015/06/30 12:54:35  abbott
716 // Summary: Added new fn myIndetsIn
717 // Author: JAA
718 //
719 // Revision 1.31  2015/04/16 20:20:22  abbott
720 // Summary: Fixed incorrectly edited code
721 // Author: JAA
722 //
723 // Revision 1.30  2015/04/16 16:36:33  abbott
724 // Summary: Cleaned impls of myPowerOverflowCheck
725 // Author: JAA
726 //
727 // Revision 1.29  2015/04/13 14:42:08  abbott
728 // Summary: Added myPowerOverflowCheck (1st version)
729 // Author: JAA
730 //
731 // Revision 1.28  2014/07/03 15:36:35  abbott
732 // Summary: Cleaned up impl of PPMonoids: moved myIndetSymbols & myNumIndets to base class
733 // Author: JAA
734 //
735 // Revision 1.27  2014/05/14 15:57:15  bigatti
736 // -- added "using" for clang with superpedantic flag
737 //
738 // Revision 1.26  2013/03/15 11:00:50  abbott
739 // Added check for exponent overflow when powering a PP.
740 // Merged PPMonoidEv and PPMonoidEvZZ implementations into a single file.
741 // Implemented new interface for pseudo-ctors for PPMonoidEv which uses a "flag"
742 // to say whether exponents are big or not.
743 //
744 // Revision 1.25  2012/05/28 09:18:21  abbott
745 // Created IntOperations which gathers together all operations on
746 // integers (both big and small).  Many consequential changes.
747 //
748 // Revision 1.24  2012/01/26 16:50:55  bigatti
749 // -- changed back_inserter into insert
750 //
751 // Revision 1.23  2011/08/14 15:52:17  abbott
752 // Changed ZZ into BigInt (phase 1: just the library sources).
753 //
754 // Revision 1.22  2011/05/03 12:13:12  abbott
755 // Added static const data member ourMaxExp.
756 // Code is more readable, and compiler doesn't grumble any more.
757 //
758 // Revision 1.21  2011/03/22 22:38:15  abbott
759 // Fixed some wrong static_casts inside some CoCoA_ASSERTs.
760 //
761 // Revision 1.20  2011/03/10 17:27:11  bigatti
762 // -- changed unsigned long into long in some CoCoA_ASSERT
763 // -- removed assert in myCmpWDegPartial (done in OrdvArith)
764 //
765 // Revision 1.19  2011/03/10 16:39:34  abbott
766 // Replaced (very many) size_t by long in function interfaces (for rings,
767 // PPMonoids and modules).  Also replaced most size_t inside fn defns.
768 //
769 // Revision 1.18  2010/12/17 16:09:51  abbott
770 // Corrected used of myIndetSymbols in some assertions.
771 //
772 // Revision 1.17  2010/11/30 11:18:11  bigatti
773 // -- renamed IndetName --> IndetSymbol
774 //
775 // Revision 1.16  2010/11/05 16:21:08  bigatti
776 // -- added ZZExponents
777 //
778 // Revision 1.15  2010/10/06 14:10:24  abbott
779 // Added increments to the ref count in ring and PPMonoid ctors to make
780 // them exception safe.
781 //
782 // Revision 1.14  2010/02/03 16:13:52  abbott
783 // Added new single word tags for specifying the ordering in PPMonoid
784 // pseudo-ctors.
785 //
786 // Revision 1.13  2010/02/02 16:44:31  abbott
787 // Added radical & IsRadical (via mem fns myRadical & myIsRadical)
788 // for PPMonoidElems.
789 //
790 // Revision 1.12  2009/12/23 18:53:52  abbott
791 // Major change to conversion functions:
792 //   convert(..) is now a procedure instead of a function
793 //   IsConvertible(..) replaces the former convert(..) function
794 //   Added new NumericCast conversion function (placeholder for BOOST feature)
795 //   Consequent changes in code which uses these features.
796 //
797 // Revision 1.11  2009/09/22 14:01:33  bigatti
798 // -- added myCmpWDegPartial (ugly name, I know....)
799 // -- cleaned up and realigned code in PPMonoid*.C files
800 //
801 // Revision 1.10  2008/03/26 16:52:04  abbott
802 // Added exponent overflow checks (also for ordvs) when CoCoA_DEBUG is active.
803 //
804 // Revision 1.9  2007/12/05 11:06:24  bigatti
805 // -- changed "size_t StdDeg/myStdDeg(f)" into "long"  (and related functions)
806 // -- changed "log/myLog(f, i)" into "MaxExponent/myMaxExponent(f, i)"
807 // -- fixed bug in "IsOne(ideal)" in SparsePolyRing.C
808 //
809 // Revision 1.8  2007/12/04 14:27:06  bigatti
810 // -- changed "log(pp, i)" into "exponent(pp, i)"
811 //
812 // Revision 1.7  2007/10/30 17:14:07  abbott
813 // Changed licence from GPL-2 only to GPL-3 or later.
814 // New version for such an important change.
815 //
816 // Revision 1.6  2007/09/25 16:32:30  abbott
817 // Several minor changes to silence gcc-4.3:
818 //    more #includes,
819 //    and fixed a template problemm in RegisterServerOps.C
820 //
821 // Revision 1.5  2007/05/31 14:54:31  bigatti
822 // -- now using AreDistinct and AreArityConsistent for sanity check on
823 //    indet names
824 //
825 // Revision 1.3  2007/05/03 10:35:23  abbott
826 // Added new PPMonoidEvZZ with (virtually) unlimited exponents.
827 // Modified test-PPMonoid1.C accordingly.
828 // Added warning in doc about silent/unchecked exponent overflow in other
829 // PPMonoids.
830 //
831 // Revision 1.2  2007/03/23 18:38:42  abbott
832 // Separated the "convert" functions (and CheckedCast) into their own files.
833 // Many consequential changes.  Also corrected conversion to doubles.
834 //
835 // Revision 1.1.1.1  2007/03/09 15:16:11  abbott
836 // Imported files
837 //
838 // Revision 1.14  2007/03/08 18:22:29  cocoa
839 // Just whitespace cleaning.
840 //
841 // Revision 1.13  2007/03/08 17:43:11  cocoa
842 // Swapped order of args to the NewPPMonoid pseudo ctors.
843 //
844 // Revision 1.12  2007/03/08 11:07:12  cocoa
845 // Made pseudo ctors for polynomial rings more uniform.  This allowed me to
846 // remove an include of CoCoA/symbol.H  from the RingDistrM*.H files, but then
847 // I had to put the include in several .C files.
848 //
849 // Revision 1.11  2006/12/06 17:35:58  cocoa
850 // -- style: RawPtr args are now called "raw.."
851 //
852 // Revision 1.10  2006/11/27 13:06:23  cocoa
853 // Anna and Michael made me check without writing a proper message.
854 //
855 // Revision 1.9  2006/11/24 17:04:32  cocoa
856 // -- reorganized includes of header files
857 //
858 // Revision 1.8  2006/11/23 17:39:11  cocoa
859 // -- added #include
860 //
861 // Revision 1.7  2006/11/16 11:27:20  cocoa
862 // -- reinserted myRefCountZero(): sometimes really necessary, in general safe
863 //
864 // Revision 1.6  2006/11/14 17:29:20  cocoa
865 // -- commented out myRefCountZero() (not necessary???)
866 //
867 // Revision 1.5  2006/10/16 23:18:59  cocoa
868 // Corrected use of std::swap and various special swap functions.
869 // Improved myApply memfn for homs of RingDistrMPolyInlPP.
870 //
871 // Revision 1.4  2006/10/06 14:04:14  cocoa
872 // Corrected position of #ifndef in header files.
873 // Separated CoCoA_ASSERT into assert.H from config.H;
874 // many minor consequential changes (have to #include assert.H).
875 // A little tidying of #include directives (esp. in Max's code).
876 //
877 // Revision 1.3  2006/08/07 21:23:25  cocoa
878 // Removed almost all publicly visible references to SmallExponent_t;
879 // changed to long in all PPMonoid functions and SparsePolyRing functions.
880 // DivMask remains to sorted out.
881 //
882 // Revision 1.2  2006/06/21 17:07:10  cocoa
883 // Fixed IsIndet bug -- why are there three almost identical copies of code?
884 //
885 // Revision 1.1.1.1  2006/05/30 11:39:37  cocoa
886 // Imported files
887 //
888 // Revision 1.6  2006/03/15 18:09:31  cocoa
889 // Changed names of member functions which print out their object
890 // into myOutputSelf -- hope this will appease the Intel C++ compiler.
891 //
892 // Revision 1.5  2006/03/14 17:21:18  cocoa
893 // Moved concrete PPMonoid impls entirely into their respective .C files.
894 // Now the corresponding .H files are very compact.
895 //
896 // Revision 1.4  2006/03/12 21:28:33  cocoa
897 // Major check in after many changes
898 //
899 // Revision 1.3  2006/02/20 22:41:20  cocoa
900 // All forms of the log function for power products now return SmallExponent_t
901 // (instead of int).  exponents now resizes the vector rather than requiring
902 // the user to pass in the correct size.
903 //
904 // Revision 1.2  2006/01/17 10:23:08  cocoa
905 // Updated DivMask; many consequential changes.
906 // A few other minor fixes.
907 //
908 // Revision 1.1.1.1  2005/10/17 10:46:54  cocoa
909 // Imported files
910 //
911 // Revision 1.8  2005/10/11 16:37:30  cocoa
912 // Added new small prime finite field class (see RingFpDouble).
913 //
914 // Cleaned makefiles and configuration script.
915 //
916 // Tidied PPMonoid code (to eliminate compiler warnings).
917 //
918 // Fixed bug in RingFloat::myIsInteger.
919 //
920 // Revision 1.7  2005/08/08 16:36:32  cocoa
921 // Just checking in before going on holiday.
922 // Don't really recall what changes have been made.
923 // Added IsIndet function for RingElem, PPMonoidElem,
924 // and a member function of OrdvArith.
925 // Improved the way failed assertions are handled.
926 //
927 // Revision 1.6  2005/07/19 15:30:20  cocoa
928 // A first attempt at iterators over sparse polynomials.
929 // Main additions are to SparsePolyRing, DistrMPoly*.
930 // Some consequential changes to PPMonoid*.
931 //
932 // Revision 1.5  2005/07/08 15:09:28  cocoa
933 // Added new symbol class (to represent names of indets).
934 // Integrated the new class into concrete polynomial rings
935 // and PPMonoid -- many consequential changes.
936 // Change ctors for the "inline" sparse poly rings: they no
937 // longer expect a PPMonoid, but build their own instead
938 // (has to be a PPMonoidOv).
939 //
940 // Revision 1.4  2005/07/01 16:08:15  cocoa
941 // Friday check-in.  Major change to structure under PolyRing:
942 // now SparsePolyRing and DUPolyRing are separated (in preparation
943 // for implementing iterators).
944 //
945 // A number of other relatively minor changes had to be chased through
946 // (e.g. IndetPower).
947 //
948 // Revision 1.3  2005/06/23 15:42:41  cocoa
949 // Fixed typo in GNU fdl -- all doc/*.txt files affected.
950 // Minor corrections to PPMonoid (discovered while writing doc).
951 //
952 // Revision 1.2  2005/06/22 14:47:56  cocoa
953 // PPMonoids and PPMonoidElems updated to mirror the structure
954 // used for rings and RingElems.  Many consequential changes.
955 //
956 // Revision 1.1.1.1  2005/05/03 15:47:31  cocoa
957 // Imported files
958 //
959 // Revision 1.4  2005/04/29 15:42:02  cocoa
960 // Improved documentation for GMPAllocator.
961 // Added example program for GMPAllocator.
962 // Added example program for simple ops on polynomials.
963 // Added two new ctors for (principal) ideals (from long, and from ZZ).
964 // Added (crude) printing for PPMonoids.
965 // Updated library.H (#included GMPAllocator.H).
966 //
967 // Revision 1.3  2005/04/20 15:40:48  cocoa
968 // Major change: modified the standard way errors are to be signalled
969 // (now via a macro which records filename and line number).  Updated
970 // documentation in error.txt accordingly.
971 //
972 // Improved the documentation in matrix.txt (still more work to be done).
973 //
974 // Revision 1.2  2005/04/19 14:06:04  cocoa
975 // Added GPL and GFDL licence stuff.
976 //
977 // Revision 1.1.1.1  2005/01/27 15:12:13  cocoa
978 // Imported files
979 //
980 // Revision 1.4  2004/11/25 16:14:21  cocoa
981 // (1) Fixed definition of specialization of std::swap template function
982 //     so that it compiles with gcc 3.4.3
983 // (2) Implemented monomial function for polynomial rings.
984 // (3) Added one(PPM) and PPM->myOne() functions.
985 //
986 // Revision 1.3  2004/11/11 13:41:48  cocoa
987 // -- change: cout --> GlobalLogput()
988 //
989 // Revision 1.2  2004/11/02 14:56:33  cocoa
990 // -- changed *Print* into *Output* (myPrint --> myOutput)
991 // -- changed *Var* into *Indet* (myPrintVarName --> myOutputIndetName)
992 // -- removed suffix "IgnoreDivMask"
993 // -- added myComputeDivMask
994 // -- improved storing of IndetNames
995 // -- changed ExpvElem into SmallExponent_t
996 //
997 // Revision 1.1  2004/10/29 15:31:25  cocoa
998 // -- new PPMonoid for compatibility with OrdvArith (without DivMask)
999 //
1000