1 //   Copyright (c)  2005-2008,2014  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 #include "CoCoA/OrdvArith.H"
19 
20 #include "CoCoA/BigIntOps.H"
21 #include "CoCoA/CanonicalHom.H"
22 #include "CoCoA/DenseMatrix.H"
23 #include "CoCoA/MatrixForOrdering.H"
24 #include "CoCoA/MatrixOps.H"
25 #include "CoCoA/PPOrdering.H"
26 #include "CoCoA/PREPROCESSOR_DEFNS.H"
27 #include "CoCoA/QuotientRing.H"
28 #include "CoCoA/RingFp.H"
29 #include "CoCoA/RingHom.H"
30 #include "CoCoA/RingQQ.H"
31 #include "CoCoA/RingZZ.H"
32 #include "CoCoA/assert.H"
33 #include "CoCoA/config.H"
34 #include "CoCoA/convert.H"
35 #include "CoCoA/degree.H"
36 #include "CoCoA/error.H"
37 #include "CoCoA/matrix.H"
38 
39 
40 #include <iostream>
41 using std::ostream;
42 using std::endl;
43 //#include <vector>
44 using std::vector;
45 #include <limits>
46 using std::numeric_limits;
47 #include <algorithm>
48 using std::find;
49 using std::copy;
50 //using std::swap;
51 
52 
53 namespace CoCoA
54 {
55 
base(long NumIndets,long GradingDim,long NumOrdvEntries)56   OrdvArith::base::base(long NumIndets, long GradingDim, long NumOrdvEntries):
57     IntrusiveReferenceCount(),
58     myNumIndets(NumIndets),
59     myGradingDim(GradingDim),
60     myOrdvBuffer(NumOrdvEntries),
61     myExpvBuffer(NumIndets)
62   {
63     CoCoA_ASSERT(NumIndets > 0);
64     CoCoA_ASSERT(NumIndets < 1000000); // complain about ridiculously large number of indets
65     CoCoA_ASSERT(GradingDim <= NumIndets);
66     CoCoA_ASSERT(NumOrdvEntries >= NumIndets);
67     myBitsPerOrdvEntry = numeric_limits<SmallExponent_t>::digits;
68     myPackingDensity = numeric_limits<OrdvElem>::digits / myBitsPerOrdvEntry;
69     CoCoA_ASSERT(myPackingDensity >= 1);
70     // Recompute myBitsPerOrdvEntry; this may increase the value (safely, of course)...
71     myBitsPerOrdvEntry = numeric_limits<OrdvElem>::digits / myPackingDensity;
72     CoCoA_ASSERT(myPackingDensity == 1 || myBitsPerOrdvEntry < numeric_limits<OrdvElem>::digits);
73     if (myPackingDensity == 1) // special case because shift op not defined if shift >= wordsize
74       myOrdvMask = numeric_limits<OrdvElem>::max();
75     else
76       myOrdvMask = (static_cast<OrdvElem>(1) << myBitsPerOrdvEntry) - 1;
77     CoCoA_ASSERT(myOrdvMask != 0);
78     // Reset myOrdvWords to the correct value...
79     myOrdvWords = 1 + (NumOrdvEntries-1)/myPackingDensity;
80     myOrdvWordsForCmp = 1 + (myNumIndets-1)/myPackingDensity;
81 
82     myRefCountZero();
83   }
84 
85 
~base()86   OrdvArith::base::~base()
87   {}
88 
89 
90 
myAssignZero(OrdvElem * ordv)91   void OrdvArith::base::myAssignZero(OrdvElem* ordv) const
92   {
93     for (long i=0; i < myOrdvWords; ++i)
94       ordv[i] = 0;
95   }
96 
97 
myAssign(OrdvElem * dest,const OrdvElem * src)98   void OrdvArith::base::myAssign(OrdvElem* dest, const OrdvElem* src) const
99   {
100 //    std::copy(&src[0], &src[myOrdvWords], &dest[0]); // seems slightly slower
101     for (long i=0; i < myOrdvWords; ++i)
102       dest[i] = src[i];
103   }
104 
105 
mySwap(OrdvElem * ordv1,OrdvElem * ordv2)106   void OrdvArith::base::mySwap(OrdvElem* ordv1, OrdvElem* ordv2) const
107   {
108 //    if (ordv1 == ordv2) return; // worth checking this special case???
109     for (long i=0; i < myOrdvWords; ++i)
110       std::swap(ordv1[i], ordv2[i]);
111   }
112 
113 
myMulIndetPower(OrdvElem * ordv,long var,long exp)114   void OrdvArith::base::myMulIndetPower(OrdvElem* ordv, long var, long exp) const
115   {
116     CoCoA_ASSERT(exp >= 0);
117     CoCoA_ASSERT(0 <= var && var < myNumIndets);
118     vector<long> PowerExpv(myNumIndets);  // should be member of OrdvArith::base?  Use myExpvBuffer???
119     PowerExpv[var] = exp;
120     vector<OrdvElem> PowerOrdv(myOrdvWords);  // should be member of OrdvArith::base?  Use myOrdvBuffer????
121     myAssignFromExpv(&PowerOrdv[0], PowerExpv);
122     myMul(ordv, ordv, &PowerOrdv[0]);
123   }
124 
125 
myPower(OrdvElem * ordv,const OrdvElem * ordv1,long LongExp)126   void OrdvArith::base::myPower(OrdvElem* ordv, const OrdvElem* ordv1, long LongExp) const
127   {
128     CoCoA_ASSERT(LongExp >= 0);
129 #ifdef CoCoA_DEBUG
130     myPowerOverflowCheck(ordv1, LongExp);
131 #endif
132     const OrdvElem exp = static_cast<OrdvElem>(LongExp);
133     if (exp > myOrdvMask)
134       CoCoA_THROW_ERROR(ERR::ExpTooBig, "OrdvArith::myPower");
135     for (long i=0; i < myOrdvWords; ++i)
136       ordv[i] = exp*ordv1[i];
137   }
138 
139 
myPowerOverflowCheck(const OrdvElem * ordv,long LongExp)140   void OrdvArith::base::myPowerOverflowCheck(const OrdvElem* ordv, long LongExp) const
141   {
142     if (LongExp == 0 || LongExp == 1) return;
143     CoCoA_ASSERT(LongExp >= 0);
144     if (static_cast<unsigned long>(LongExp) > myOrdvMask)
145       CoCoA_THROW_ERROR(ERR::ExpTooBig, "OrdvArith::myPower");
146     const OrdvElem exp = static_cast<OrdvElem>(LongExp);
147     // ??? Is it worth uncommenting these two shortcuts???
148     // if (pow == 0) { myAssignZero(ordv); return; }
149     // if (pow == 1) { myAssign(ordv, ordv1); return; }
150 #ifdef CoCoA_THREADSAFE_HACK
151     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
152 #endif
153     myDecompress(myOrdvBuffer, ordv, myNumIndets);
154     for (long i=0; i < myNumIndets; ++i)
155     {
156       // Check for ordv element overflow.
157       if (myOrdvBuffer[i] > 0 && myOrdvMask/myOrdvBuffer[i] < exp)
158         CoCoA_THROW_ERROR(ERR::ExpTooBig, "OrdvArith::myPower");
159     }
160   }
161 
162 
myStdDeg(const OrdvElem * ordv)163   long OrdvArith::base::myStdDeg(const OrdvElem* ordv) const
164   {
165 #ifdef CoCoA_THREADSAFE_HACK
166     vector<long> myExpvBuffer(myNumIndets); // NB hides data member!
167 #endif
168     myComputeExpv(myExpvBuffer, ordv);
169     long d=0;
170     for (long i=0; i < myNumIndets; ++i)
171       d += myExpvBuffer[i];  // ignore possible overflow
172     return d;
173   }
174 
175 
myWDeg(degree & d,const OrdvElem * ordv)176   void OrdvArith::base::myWDeg(degree& d, const OrdvElem* ordv) const
177   {
178     CoCoA_ASSERT(GradingDim(d) == myGradingDim);
179 #ifdef CoCoA_THREADSAFE_HACK
180     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
181 #endif
182     myDecompress(myOrdvBuffer, ordv, myGradingDim);
183     for (long i=0; i < myGradingDim; ++i)
184       SetComponent(d, i, myOrdvBuffer[i]);
185   }
186 
187 
myCmpWDegPartial(const OrdvElem * ordv1,const OrdvElem * ordv2,long PartialGrDim)188   int OrdvArith::base::myCmpWDegPartial(const OrdvElem* ordv1, const OrdvElem* ordv2, long PartialGrDim) const  // assumes GrDim >= 0
189   {
190     CoCoA_ASSERT(0 <= PartialGrDim && PartialGrDim <= myGradingDim);
191     const long last = PartialGrDim/myPackingDensity;
192     for (long i=0; i < last; ++i)
193       if (ordv1[i] != ordv2[i]) return (ordv1[i] > ordv2[i])?1:-1;
194     const long ShiftCount = (last+1)*myPackingDensity - PartialGrDim;
195     if (ShiftCount == myPackingDensity) return 0;
196     CoCoA_ASSERT(myPackingDensity > 1 && myBitsPerOrdvEntry < numeric_limits<OrdvElem>::digits);
197     // Reach here only if myPackingDensity > 1, so myBitsPerOrdvEntry < wordsize
198     const OrdvElem last1 = ordv1[last] >> (ShiftCount*myBitsPerOrdvEntry);
199     const OrdvElem last2 = ordv2[last] >> (ShiftCount*myBitsPerOrdvEntry);
200     if (last1 == last2) return 0;
201     if (last1 > last2) return 1;
202     return -1;
203   }
204 
205 
myIsZero(const OrdvElem * ordv)206   bool OrdvArith::base::myIsZero(const OrdvElem* ordv) const
207   {
208     for (long i=0; i < myOrdvWordsForCmp; ++i)
209       if (ordv[i] != 0) return false;
210     return true;
211   }
212 
213 
214   // Simple rather than efficient.
myIsIndet(long & index,const OrdvElem * ordv)215   bool OrdvArith::base::myIsIndet(long& index, const OrdvElem* ordv) const
216   {
217 #ifdef CoCoA_THREADSAFE_HACK
218     vector<long> myExpvBuffer(myNumIndets); // NB hides data member!
219 #endif
220     myComputeExpv(myExpvBuffer, ordv);
221 
222     long j = myNumIndets;
223     for (long i = 0; i < myNumIndets; ++i)
224     {
225       if (myExpvBuffer[i] == 0) continue;
226       if (j != myNumIndets || myExpvBuffer[i] != 1) return false;
227       j = i;
228     }
229     if (j == myNumIndets) return false;
230     index = j;
231     return true;
232   }
233 
234 
myOrdvGetNth(const OrdvElem * ordv,long n)235   OrdvArith::OrdvElem OrdvArith::base::myOrdvGetNth(const OrdvElem* ordv, long n) const
236   {
237     CoCoA_ASSERT(n < myOrdvWords*myPackingDensity);
238     const long posn = n/myPackingDensity;
239     const long n_shifts = myPackingDensity-1 - (n%myPackingDensity);
240     const OrdvElem tmp = ordv[posn] >> (n_shifts * myBitsPerOrdvEntry);  // NB shift amount is less than word width!
241     return (tmp & myOrdvMask);
242   }
243 
244 
myCompress(OrdvElem * ordv,const vector<OrdvElem> & buffer)245   void OrdvArith::base::myCompress(OrdvElem* ordv, const vector<OrdvElem>& buffer) const
246   {
247     if (myPackingDensity == 1)
248     {
249       std::copy(buffer.begin(), buffer.end(), ordv);
250       return;
251     }
252     long posn = 0;
253     for (long i=0; i < myOrdvWords; ++i)
254     {
255       OrdvElem word = 0; // this value is totally irrelevant, it gets shifted into "hyperspace"
256       for (long j=0; j < myPackingDensity; ++j)
257       {
258         word <<= myBitsPerOrdvEntry; // ok because myBitsPerOrdvEntry < wordsize!!!
259 	if (posn < myNumIndets) word += buffer[posn];
260 	++posn;
261       }
262       ordv[i] = word;
263     }
264   }
265 
266 
myDecompress(vector<OrdvElem> & buffer,const OrdvElem * ordv,long NumCompts)267   void OrdvArith::base::myDecompress(vector<OrdvElem>& buffer, const OrdvElem* ordv, long NumCompts) const
268   {
269     if (myPackingDensity == 1)
270     {
271       std::copy(&ordv[0], &ordv[NumCompts], buffer.begin());
272       return;
273     }
274     long BasePosn = 0;
275     for (long i=0; i < myOrdvWords; ++i)
276     {
277       OrdvElem word = ordv[i];
278       for (long j=myPackingDensity; j-- > 0;)
279       {
280 	if (BasePosn + j < NumCompts)
281           buffer[BasePosn + j] = (word & myOrdvMask);
282         word >>= myBitsPerOrdvEntry;  // ok because myBitsPerOrdvEntry < wordsize!!!
283       }
284       BasePosn += myPackingDensity;
285     }
286   }
287 
288 
289 
290   //---------------------------------------------------------------------------
291   // LexImpl
292 
LexImpl(long NumIndets)293   OrdvArith::LexImpl::LexImpl(long NumIndets):
294     base(NumIndets, 0, NumIndets)
295   {}
296 
297 
myAssignFromExpv(OrdvElem * ordv,const vector<long> & expv)298   void OrdvArith::LexImpl::myAssignFromExpv(OrdvElem* ordv, const vector<long>& expv) const
299   {
300 #ifdef CoCoA_THREADSAFE_HACK
301     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
302 #endif
303     for (long i=0; i < myNumIndets; ++i)
304       myOrdvBuffer[i] = expv[i];
305     myCompress(ordv, myOrdvBuffer);
306   }
307 
308 
myComputeExpv(vector<long> & expv,const OrdvElem * ordv)309   void OrdvArith::LexImpl::myComputeExpv(vector<long>& expv, const OrdvElem* ordv) const
310   {
311 #ifdef CoCoA_THREADSAFE_HACK
312     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
313 #endif
314     myDecompress(myOrdvBuffer, ordv, myNumIndets);
315     for (long i=0; i < myNumIndets; ++i)
316       expv[i] = NumericCast<long>(myOrdvBuffer[i]);
317   }
318 
319 
myExponent(const OrdvElem * ordv,long var)320   long OrdvArith::LexImpl::myExponent(const OrdvElem* ordv, long var) const
321   {
322     return NumericCast<long>(myOrdvGetNth(ordv, var));
323   }
324 
325 
myOutputSelf(ostream & out)326   void OrdvArith::LexImpl::myOutputSelf(ostream& out) const
327   {
328     if (!out) return;  // short-cut for bad ostreams
329     out << "OrdvArith::LexImpl(" << myNumIndets << ")";
330   }
331 
332 
333 
334   //---------------------------------------------------------------------------
335   // StdDegLexImpl
336 
StdDegLexImpl(long NumIndets)337   OrdvArith::StdDegLexImpl::StdDegLexImpl(long NumIndets):
338     base(NumIndets, 1, NumIndets)
339   {}
340 
341 
myAssignFromExpv(OrdvElem * ordv,const vector<long> & expv)342   void OrdvArith::StdDegLexImpl::myAssignFromExpv(OrdvElem* ordv, const vector<long>& expv) const
343   {
344     OrdvElem deg = expv[0];
345     for (long i=1; i < myNumIndets; ++i)
346     {
347       CoCoA_ASSERT("Exponent overflow" && deg <= myOrdvMask-expv[i]);
348       deg += expv[i];
349     }
350 #ifdef CoCoA_THREADSAFE_HACK
351     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
352 #endif
353     myOrdvBuffer[0] = deg;
354     for (long i=1; i < myNumIndets; ++i)
355       myOrdvBuffer[i] = expv[i-1];
356 
357     myCompress(ordv, myOrdvBuffer);
358   }
359 
360 
myComputeExpv(vector<long> & expv,const OrdvElem * ordv)361   void OrdvArith::StdDegLexImpl::myComputeExpv(vector<long>& expv, const OrdvElem* ordv) const
362   {
363 #ifdef CoCoA_THREADSAFE_HACK
364     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
365 #endif
366     myDecompress(myOrdvBuffer, ordv, myNumIndets);
367     OrdvElem expN = myOrdvBuffer[0];
368     for (long i=1; i < myNumIndets; ++i)
369     {
370       const OrdvElem& ordvi = myOrdvBuffer[i];
371       expN -= ordvi;
372       expv[i-1] = ordvi;
373     }
374     expv[myNumIndets-1] = expN;
375   }
376 
377 
myStdDeg(const OrdvElem * ordv)378   long OrdvArith::StdDegLexImpl::myStdDeg(const OrdvElem* ordv) const
379   {
380 #ifdef CoCoA_THREADSAFE_HACK
381     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
382 #endif
383     myDecompress(myOrdvBuffer, ordv, 1);
384     return myOrdvBuffer[0];
385   }
386 
387 
myExponent(const OrdvElem * ordv,long var)388   long OrdvArith::StdDegLexImpl::myExponent(const OrdvElem* ordv, long var) const
389   {
390     if (var < myNumIndets-1) return NumericCast<long>(myOrdvGetNth(ordv, var+1));
391 #ifdef CoCoA_THREADSAFE_HACK
392     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
393 #endif
394     myDecompress(myOrdvBuffer, ordv, myNumIndets);
395     OrdvElem ans = myOrdvBuffer[0];
396     for (long i=1; i < myNumIndets; ++i)
397       ans -= myOrdvBuffer[i];  // NB this cannot underflow if degree has not overflowed
398     return NumericCast<long>(ans);
399   }
400 
401 
myOutputSelf(ostream & out)402   void OrdvArith::StdDegLexImpl::myOutputSelf(ostream& out) const
403   {
404     if (!out) return;  // short-cut for bad ostreams
405     out << "OrdvArith::StdDegLexImpl(" << myNumIndets << ")";
406   }
407 
408 
409 
410   //---------------------------------------------------------------------------
411   // StdDegRevLexImpl
412 
StdDegRevLexImpl(long NumIndets)413   OrdvArith::StdDegRevLexImpl::StdDegRevLexImpl(long NumIndets):
414     base(NumIndets, 1, NumIndets)
415   {}
416 
417 
myAssignFromExpv(OrdvElem * ordv,const vector<long> & expv)418   void OrdvArith::StdDegRevLexImpl::myAssignFromExpv(OrdvElem* ordv, const vector<long>& expv) const
419   {
420     OrdvElem deg = expv[0];
421     for (long i=1; i < myNumIndets; ++i)
422     {
423       CoCoA_ASSERT("Negative exponent" && expv[i] >= 0);
424       CoCoA_ASSERT("Exponent overflow" && static_cast<unsigned long>(expv[i]) <= myOrdvMask-deg);
425       deg += expv[i];
426     }
427 #ifdef CoCoA_THREADSAFE_HACK
428     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
429 #endif
430     myOrdvBuffer[0] = deg;
431     for (long i=1; i < myNumIndets; ++i)
432       myOrdvBuffer[i] = deg - expv[myNumIndets - i];
433 
434     myCompress(ordv, myOrdvBuffer);
435   }
436 
437 
myComputeExpv(vector<long> & expv,const OrdvElem * ordv)438   void OrdvArith::StdDegRevLexImpl::myComputeExpv(vector<long>& expv, const OrdvElem* ordv) const
439   {
440 #ifdef CoCoA_THREADSAFE_HACK
441     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
442 #endif
443     myDecompress(myOrdvBuffer, ordv, myNumIndets);
444     const OrdvElem deg = myOrdvBuffer[0];
445     OrdvElem exp0 = (2-myNumIndets)*deg; // may HARMLESSLY become "negative" or "overflow"
446     for (long i=1; i < myNumIndets; ++i)
447     {
448       const OrdvElem ordvi = myOrdvBuffer[i];
449       exp0 += ordvi;
450       expv[myNumIndets-i] = deg - ordvi;
451     }
452     expv[0] = exp0;
453   }
454 
455 
myStdDeg(const OrdvElem * ordv)456   long OrdvArith::StdDegRevLexImpl::myStdDeg(const OrdvElem* ordv) const
457   {
458 #ifdef CoCoA_THREADSAFE_HACK
459     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
460 #endif
461     myDecompress(myOrdvBuffer, ordv, 1);
462     return myOrdvBuffer[0];
463   }
464 
465 
myExponent(const OrdvElem * ordv,long var)466   long OrdvArith::StdDegRevLexImpl::myExponent(const OrdvElem* ordv, long var) const
467   {
468     if (var != 0) return NumericCast<long>(myOrdvGetNth(ordv, 0) - myOrdvGetNth(ordv, myNumIndets-var));
469 
470 #ifdef CoCoA_THREADSAFE_HACK
471     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
472 #endif
473     myDecompress(myOrdvBuffer, ordv, myNumIndets);
474     OrdvElem ans = (2-myNumIndets)*myOrdvBuffer[0]; // may HARMLESSLY become "negative" or overflow
475     for (long i=1; i < myNumIndets; ++i)
476       ans += myOrdvBuffer[i];
477     return NumericCast<long>(ans);
478   }
479 
480 
myOutputSelf(ostream & out)481   void OrdvArith::StdDegRevLexImpl::myOutputSelf(ostream& out) const
482   {
483     if (!out) return;  // short-cut for bad ostreams
484     out << "OrdvArith::StdDegRevLexImpl(" << myNumIndets << ")";
485   }
486 
487 
488 
489   //---------------------------------------------------------------------------
490   // StdDegRevLexImpl2
491 
StdDegRevLexImpl2(long NumIndets)492   OrdvArith::StdDegRevLexImpl2::StdDegRevLexImpl2(long NumIndets):
493     base(NumIndets, 1, NumIndets)
494   {}
495 
496 
myAssignFromExpv(OrdvElem * ordv,const vector<long> & expv)497   void OrdvArith::StdDegRevLexImpl2::myAssignFromExpv(OrdvElem* ordv, const vector<long>& expv) const
498   {
499     OrdvElem PartialSum = 0;
500     long j = myNumIndets-1;
501 #ifdef CoCoA_THREADSAFE_HACK
502     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
503 #endif
504     for (long i=0; i < myNumIndets; ++i, --j)
505     {
506       CoCoA_ASSERT("Exponent overflow" && NumericCast<OrdvElem>(expv[i]) <= myOrdvMask-PartialSum);
507       PartialSum += expv[i];
508       myOrdvBuffer[j] = PartialSum;
509     }
510 
511     myCompress(ordv, myOrdvBuffer);
512   }
513 
514 
myComputeExpv(vector<long> & expv,const OrdvElem * ordv)515   void OrdvArith::StdDegRevLexImpl2::myComputeExpv(vector<long>& expv, const OrdvElem* ordv) const
516   {
517 #ifdef CoCoA_THREADSAFE_HACK
518     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
519 #endif
520     myDecompress(myOrdvBuffer, ordv, myNumIndets);
521     expv[0] = myOrdvBuffer[myNumIndets-1];
522     long i = myNumIndets-1;
523     for (long j=1; j < myNumIndets; ++j, --i)
524       expv[i] = myOrdvBuffer[j-1] - myOrdvBuffer[j];
525   }
526 
527 
myStdDeg(const OrdvElem * ordv)528   long OrdvArith::StdDegRevLexImpl2::myStdDeg(const OrdvElem* ordv) const
529   {
530 #ifdef CoCoA_THREADSAFE_HACK
531     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
532 #endif
533     myDecompress(myOrdvBuffer, ordv, 1);
534     return myOrdvBuffer[0];
535   }
536 
537 
myExponent(const OrdvElem * ordv,long var)538   long OrdvArith::StdDegRevLexImpl2::myExponent(const OrdvElem* ordv, long var) const
539   {
540     if (var == 0) return NumericCast<long>(myOrdvGetNth(ordv, myNumIndets-1));
541     return NumericCast<long>(myOrdvGetNth(ordv, myNumIndets-var-1) - myOrdvGetNth(ordv, myNumIndets-var));
542   }
543 
544 
myOutputSelf(ostream & out)545   void OrdvArith::StdDegRevLexImpl2::myOutputSelf(ostream& out) const
546   {
547     if (!out) return;  // short-cut for bad ostreams
548     out << "OrdvArith::StdDegRevLexImpl2(" << myNumIndets << ")";
549   }
550 
551 
552 
553   //---------------------------------------------------------------------------
554   // MatrixOrderingImpl
555 
MatrixOrderingImpl(long NumIndets,long GradingDim,const ConstMatrixView &)556   OrdvArith::MatrixOrderingImpl::MatrixOrderingImpl(long NumIndets, long GradingDim, const ConstMatrixView& /*OrderMatrix*/):
557     base(NumIndets, GradingDim, NumIndets)
558   {
559     CoCoA_THROW_ERROR(ERR::NYI, "MatrixOrderingImpl");
560 //     CoCoA_ASSERT(myGradingDim < NumRows(OrderMatrix));
561 //     CoCoA_ASSERT(NumRows(OrderMatrix) == NumIndets);
562 //     CoCoA_ASSERT(NumCols(OrderMatrix) == NumIndets);
563 //       // Check that the matrix entries are non-negative
564 //     for (long i=0; i < myNumIndets; ++i)
565 //       for (long j=0; j < myNumIndets; ++j)
566 //         CoCoA_ASSERT(myOrderMatrix[i][j] >= 0);
567    }
568 
569 
myAssignFromExpv(OrdvElem * ordv,const vector<long> & expv)570   void OrdvArith::MatrixOrderingImpl::myAssignFromExpv(OrdvElem* ordv, const vector<long>& expv) const
571   {
572 #ifdef CoCoA_THREADSAFE_HACK
573     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
574 #endif
575     for (long i=0; i < myNumIndets; ++i)
576     {
577       myOrdvBuffer[i] = 0;
578       for (long j=0; j < myNumIndets; ++j)
579         myOrdvBuffer[i] += myOrderMatrix[i][j]*expv[j];
580     }
581 
582     myCompress(ordv, myOrdvBuffer);
583   }
584 
585 
myComputeExpv(vector<long> & expv,const OrdvElem * ordv)586   void OrdvArith::MatrixOrderingImpl::myComputeExpv(vector<long>& expv, const OrdvElem* ordv) const
587   {
588 #ifdef CoCoA_THREADSAFE_HACK
589     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
590 #endif
591     myDecompress(myOrdvBuffer, ordv, myNumIndets);
592     for (long i=0; i < myNumIndets; ++i)
593     {
594       long deg = 0;
595       for (long j=0; j < myNumIndets; ++j)
596         deg += myAdjointOrderMatrix[i][j] * myOrdvBuffer[j];
597       expv[i] = deg/myOrderMatrixDet;
598     }
599   }
600 
601 
myExponent(const OrdvElem * ordv,long var)602   long OrdvArith::MatrixOrderingImpl::myExponent(const OrdvElem* ordv, long var) const
603   {
604 #ifdef CoCoA_THREADSAFE_HACK
605     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
606 #endif
607     myDecompress(myOrdvBuffer, ordv, myNumIndets);
608     OrdvElem ans = 0;
609     for (long j=0; j < myNumIndets; ++j)
610       ans += myAdjointOrderMatrix[var][j] * myOrdvBuffer[j];
611     ans /= myOrderMatrixDet;
612     return NumericCast<long>(ans);
613   }
614 
615 
616 
myOutputSelf(ostream & out)617   void OrdvArith::MatrixOrderingImpl::myOutputSelf(ostream& out) const
618   {
619     if (!out) return;  // short-cut for bad ostreams
620 
621     out << "OrdArith::MatrixOrdering(GradingDim=" << myGradingDim << ", ";
622 //     out << "PPOrdering(GRADING=matrix([";
623 //     for (long i=0; i < myGradingDim; ++i)
624 //     {
625 //       if (i > 0) out << ", ";
626 //       out << "[";
627 //       for (long j=0; j < myNumIndets; ++j)
628 //       {
629 //         if (j > 0) out << ", ";
630 //         out << myOrderMatrix[i][j];
631 //       }
632 //       out << "]";
633 //     }
634 //     out << "]), ";
635     out << "matrix([";
636     for (long i=0; i < myNumIndets; ++i) //??? start from myGradingDim???
637     {
638       if (i > 0) out << ", ";
639       out << "[";
640       for (long j=0; j < myNumIndets; ++j)
641       {
642         if (j > 0) out << ", ";
643         out << myOrderMatrix[i][j];
644       }
645       out << "]";
646     }
647     out << "]))";
648   }
649 
650 
651 
652 
653   //--------------------  MatrixOrderingMod32749Impl --------------------
654 
MatrixOrderingMod32749Impl(long NumIndets,long GradingDim,const ConstMatrixView & OrderMatrix)655   OrdvArith::MatrixOrderingMod32749Impl::MatrixOrderingMod32749Impl(long NumIndets, long GradingDim, const ConstMatrixView& OrderMatrix):
656     base(NumIndets, GradingDim, NumIndets)
657   {
658     //    std::cout << "------ctor-MatrixOrderingMod32749Impl-called" << std::endl;
659     CoCoA_ASSERT(NumRows(OrderMatrix) == NumIndets);
660     CoCoA_ASSERT(NumCols(OrderMatrix) == NumIndets);
661     CoCoA_ASSERT(IsZZ(RingOf(OrderMatrix))||IsQQ(RingOf(OrderMatrix)));
662     if (!IsTermOrdering(OrderMatrix))
663       CoCoA_THROW_ERROR(ERR::NotTermOrdering, "OrdvArith::MatrixOrderingMod32749Impl::MatrixOrderingMod32749Impl");
664 
665     const QuotientRing Fp = NewRingFp(32749,GlobalSettings::NonNegResidues);
666     matrix M(NewDenseMat(Fp, NumIndets, NumIndets));
667     const RingHom phi = CanonicalHom(RingOf(OrderMatrix), Fp);
668 
669     for (long i=0; i < GradingDim; ++i)
670       for (long j=0; j < NumCols(OrderMatrix); ++j)
671         if (sign(OrderMatrix(i,j)) < 0)  CoCoA_THROW_ERROR(ERR::NYI, "MatrixOrderingMod32749Impl: temporarily forcing weights to be non-negative");
672     matrix PosOrdMat = MakeTermOrd(OrderMatrix);
673     for (long i=0; i < myNumIndets; ++i)
674       for (long j=0; j < myNumIndets; ++j)
675       {
676         if (PosOrdMat(i,j)>= 32749) CoCoA_THROW_ERROR(ERR::ArgTooBig, "OrdvArith::MatrixOrderingMod32749Impl ctor");
677         SetEntry(M, i, j, phi(PosOrdMat(i, j)));
678       }
679     matrix InvM = inverse(M);
680 
681     BigInt tmp;
682     myOrderMatrix.resize(myNumIndets, vector<int>(myNumIndets));
683     myInverseOrderMatrix.resize(myNumIndets, vector<int>(myNumIndets));
684     for (long i=0; i < myNumIndets; ++i)
685       for (long j=0; j < myNumIndets; ++j)
686       {
687         myOrderMatrix[i][j] = ConvertTo<long>(PosOrdMat(i,j));
688         myInverseOrderMatrix[i][j] = ConvertTo<long>(InvM(i,j));
689       }
690 
691 #ifdef CoCoA_DEBUG
692     // Verify that myOrderMatrix is all non-negative
693     for (long i=0; i < NumRows(M); ++i)
694       for (long j=0; j < NumCols(M); ++j)
695         CoCoA_ASSERT(myOrderMatrix[i][j] >= 0);
696     // Verify that myOrderMatrix*myInverseOrderMatrix is the identity
697     for (long i=0; i < myNumIndets; ++i)
698     {
699       for (long j=0; j < myNumIndets; ++j)
700       {
701         int prod_ij = 0;
702         for (long k=0; k < myNumIndets; ++k)
703           prod_ij += (myOrderMatrix[i][k] * myInverseOrderMatrix[k][j])%32749;
704         if (i == j) CoCoA_ASSERT("BAD INVERSE" && prod_ij%32749 == 1);
705         else        CoCoA_ASSERT("BAD INVERSE" && prod_ij%32749 == 0);
706       }
707     }
708 #endif
709     myRefCountZero();
710   }
711 
712 
myAssignFromExpv(OrdvElem * ordv,const vector<long> & expv)713   void OrdvArith::MatrixOrderingMod32749Impl::myAssignFromExpv(OrdvElem* ordv, const vector<long>& expv) const
714   {
715 #ifdef CoCoA_THREADSAFE_HACK
716     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
717 #endif
718     for (long i=0; i < myNumIndets; ++i)
719     {
720       myOrdvBuffer[i] = 0;
721       for (long j=0; j < myNumIndets; ++j)
722         myOrdvBuffer[i] += myOrderMatrix[i][j]*expv[j];
723     }
724 
725     myCompress(ordv, myOrdvBuffer);
726   }
727 
728 
myComputeExpv(vector<long> & expv,const OrdvElem * ordv)729   void OrdvArith::MatrixOrderingMod32749Impl::myComputeExpv(vector<long>& expv, const OrdvElem* ordv) const
730   {
731 #ifdef CoCoA_THREADSAFE_HACK
732     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
733 #endif
734     myDecompress(myOrdvBuffer, ordv, myNumIndets);
735     for (long i=0; i < myNumIndets; ++i)
736     {
737       unsigned long deg = 0;
738       for (long j=0; j < myNumIndets; ++j)
739       {
740         deg += (myInverseOrderMatrix[i][j] * myOrdvBuffer[j]);
741         if (deg>46336*32749) deg -= 46336*32749;
742       }
743       expv[i] = deg%32749;
744     }
745   }
746 
747 
myExponent(const OrdvElem * ordv,long var)748   long OrdvArith::MatrixOrderingMod32749Impl::myExponent(const OrdvElem* ordv, long var) const
749   {
750 #ifdef CoCoA_THREADSAFE_HACK
751     vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member!
752 #endif
753     myDecompress(myOrdvBuffer, ordv, myNumIndets);
754     OrdvElem ans = 0;
755     for (long j=0; j < myNumIndets; ++j)
756     {
757       ans += (myInverseOrderMatrix[var][j] * myOrdvBuffer[j]);
758       if (ans > 46336*32749) ans -= 46336*32749;
759     }
760     return ans%32749; // no need to use NumericCast here, overflow can never occur
761   }
762 
763 
myOutputSelf(ostream & out)764   void OrdvArith::MatrixOrderingMod32749Impl::myOutputSelf(ostream& out) const
765   {
766     if (!out) return;  // short-cut for bad ostreams
767 
768     out << "OrdvArith::MatrixOrdering(GradingDim=" << myGradingDim << ", ";
769 //     out << "PPOrdering(GRADING=matrix([";
770 //     for (long i=0; i < myGradingDim; ++i)
771 //     {
772 //       if (i > 0) out << ", ";
773 //       out << "[";
774 //       for (long j=0; j < myNumIndets; ++j)
775 //       {
776 //         if (j > 0) out << ", ";
777 //         out << myOrderMatrix[i][j];
778 //       }
779 //       out << "]";
780 //     }
781 //     out << "]), ";
782     out << "matrix([";
783     for (long i=0; i < myNumIndets; ++i)
784     {
785       if (i > 0) out << ", ";
786       out << "[";
787       for (long j=0; j < myNumIndets; ++j)
788       {
789         if (j > 0) out << ", ";
790         out << myOrderMatrix[i][j];
791       }
792       out << "]";
793     }
794     out << "]))";
795   }
796 
797 
798 //   void OrdvArith::MatrixOrderingMod32749Impl::mySetMatrix(const matrix& M)
799 //   {
800 //     CoCoA_ASSERT(NumRows(M) == myNumIndets);
801 //     CoCoA_ASSERT(NumCols(M) == myNumIndets);
802 //     BigInt tmp;
803 
804 //     for (long i=0; i < myNumIndets; ++i)
805 //       for (long j=0; j < myNumIndets; ++j)
806 //       {
807 //         if (!IsInteger(tmp, M(i, j)))
808 //           CoCoA_THROW_ERROR("entry of MatrixOrdering is not integer","MatrixOrderingMod32749Impl");
809 //         if (!convert(myInverseOrderMatrix[i][j], tmp))
810 //           CoCoA_THROW_ERROR("entry of MatrixOrdering is not integer","MatrixOrderingMod32749Impl");
811 //       }
812 //   }
813 
814 
815 //   void OrdvArith::MatrixOrderingMod32749Impl::mySetInverseMatrixTmp(const matrix& /*M*/)
816 //   { /*???*/  }
817 
818 
819 
820   //---------------------------------------------------------------------------
821 
NewOrdvArith(const PPOrdering & PPO)822   OrdvArith::reference NewOrdvArith(const PPOrdering& PPO)
823   {
824     //    std::cout << "--------NewOrdvArith-called" << std::endl;
825     if (IsLex(PPO))
826       return OrdvArith::reference(new OrdvArith::LexImpl(NumIndets(PPO)));
827     if (IsStdDegLex(PPO))
828       return OrdvArith::reference(new OrdvArith::StdDegLexImpl(NumIndets(PPO)));
829     if (IsStdDegRevLex(PPO))
830       return OrdvArith::reference(new OrdvArith::StdDegRevLexImpl(NumIndets(PPO)));
831 
832     // If we get here, we have a matrix ordering.
833 
834     const long n = NumIndets(PPO);
835     const long g = GradingDim(PPO);
836 
837     ConstMatrixView M(OrdMat(PPO));
838 
839     CoCoA_ASSERT(NumRows(M) == n);
840     CoCoA_ASSERT(NumCols(M) == n);
841     CoCoA_ASSERT(g <= n);
842 
843     return OrdvArith::reference(new OrdvArith::MatrixOrderingMod32749Impl(n, g, M));
844 
845     // (1) Get matrix M out of the ordering.
846     // (2) Make an equivalent matrix M2 which is strictly positive
847     // (3) Build a MatrixOrderingImpl object with M2, but also need
848     //     the transformation matrix to be able to calculate degrees!!
849   }
850 
851 
852   std::ostream& operator<<(std::ostream& out, const OrdvArith::reference& OA)
853   {
854     if (!out) return out;  // short-cut for bad ostreams
855     OA->myOutputSelf(out);
856     return out;
857   }
858 
859 
860 } // end of namespace CoCoA
861 
862 
863 // RCS header/log
864 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/OrdvArith.C,v 1.51 2020/06/17 15:49:24 abbott Exp $
865 // $Log: OrdvArith.C,v $
866 // Revision 1.51  2020/06/17 15:49:24  abbott
867 // Summary: Changed CoCoA_ERROR into CoCoA_THROW_ERROR
868 //
869 // Revision 1.50  2020/02/11 16:56:41  abbott
870 // Summary: Corrected last update (see redmine 969)
871 //
872 // Revision 1.49  2020/02/11 16:12:18  abbott
873 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969
874 //
875 // Revision 1.48  2018/05/18 12:15:04  bigatti
876 // -- renamed IntOperations --> BigIntOps
877 //
878 // Revision 1.47  2018/05/17 15:37:47  bigatti
879 // -- renamed MatrixOperations --> MatrixOps
880 //
881 // Revision 1.46  2017/05/17 15:57:34  bigatti
882 // -- added check for ArgTooBig in MatrixOrderingMod32749Impl ctor
883 //
884 // Revision 1.45  2017/04/18 12:50:06  abbott
885 // Summary: Corrected ifdef use of CoCoA_THREADSAFE_HACK and CoCoA_DEBUG
886 //
887 // Revision 1.44  2016/11/11 14:15:32  abbott
888 // Summary: Added short-cut to operator<< when ostream is in bad state
889 //
890 // Revision 1.43  2015/12/08 14:05:11  abbott
891 // Summary: Renamed NewMatCompleteOrd to MakeTermOrd
892 //
893 // Revision 1.42  2015/12/01 17:34:30  abbott
894 // Summary: Added call to NewMatCompleteOrd to ctor for MatOrdMod32749
895 //
896 // Revision 1.41  2015/12/01 15:58:22  abbott
897 // Summary: Removed call to NewPositiveMat; moved a sanity check
898 //
899 // Revision 1.40  2015/11/30 21:53:55  abbott
900 // Summary: Major update to matrices for orderings (not yet complete, some tests fail)
901 //
902 // Revision 1.39  2015/04/13 14:42:07  abbott
903 // Summary: Added myPowerOverflowCheck (1st version)
904 // Author: JAA
905 //
906 // Revision 1.38  2014/07/31 13:10:46  bigatti
907 // -- GetMatrix(PPO) --> OrdMat(PPO)
908 // -- added OrdMat and GradingMat to PPOrdering, PPMonoid, SparsePolyRing
909 //
910 // Revision 1.37  2014/07/30 14:07:26  abbott
911 // Summary: Changed BaseRing into RingOf
912 // Author: JAA
913 //
914 // Revision 1.36  2014/04/30 16:10:00  abbott
915 // Summary: Removed pointless include
916 // Author: JAA
917 //
918 // Revision 1.35  2014/04/11 15:44:27  abbott
919 // Summary: Renamed MatrixArith to MatrixOperations (in includes)
920 // Author: JAA
921 //
922 // Revision 1.34  2014/01/29 13:06:08  abbott
923 // Summary: Removed irrelevant #include directive
924 // Author: JAA
925 //
926 // Revision 1.33  2014/01/28 16:53:36  abbott
927 // Significant change: code is now threadsafe.
928 // Uses CPP flag CoCoA_THREADSAFE_HACK to select between single-threaded & multi-threaded
929 // code; single-threaded uses a "global" buffer.
930 //
931 // Revision 1.32  2013/05/27 13:09:35  abbott
932 // Added include directive for config.H.
933 //
934 // Revision 1.31  2013/04/24 09:15:08  abbott
935 // Added an assertion.
936 //
937 // Revision 1.30  2013/03/27 11:37:04  abbott
938 // Added new (faster, cleaner) impl for StdDegRevLex.  Still no doc though.
939 //
940 // Revision 1.29  2013/03/26 15:45:37  abbott
941 // NOT YET COMPLETE -- just checking in so that CVS compiles!!!
942 //
943 // Revision 1.28  2013/03/15 10:56:39  abbott
944 // Changed OrdvElem into unsigned long.
945 // Corrected evil/subtle bug in CmpWDegPartial.
946 //
947 // Revision 1.27  2013/02/26 21:40:43  abbott
948 // Fixed evil subtle bug: shift operator<< and operator>> are UNDEFINED if
949 // shift amount is greater than or equal to wordsize.  NASTY!!!
950 // Added overflow check in power function.
951 // Some minor cleaning.
952 //
953 // Revision 1.26  2012/05/28 09:18:21  abbott
954 // Created IntOperations which gathers together all operations on
955 // integers (both big and small).  Many consequential changes.
956 //
957 // Revision 1.25  2012/04/02 17:06:00  bigatti
958 // -- allowing QQ for BaseRing of oder matrices
959 //
960 // Revision 1.24  2012/03/30 17:29:01  bigatti
961 // -- accepting matrices over QQ
962 //
963 // Revision 1.23  2012/02/10 10:28:08  bigatti
964 // -- changed RingZ.H, RingQ.H --> RingZZ.H, RingQQ.H
965 //
966 // Revision 1.22  2012/02/08 16:12:37  bigatti
967 // -- changed: Z,Q -> ZZ,QQ
968 //
969 // Revision 1.21  2011/08/14 15:52:17  abbott
970 // Changed ZZ into BigInt (phase 1: just the library sources).
971 //
972 // Revision 1.20  2011/05/19 14:41:09  abbott
973 // Matrix impl now explicitly requests non-neg residues when creating RingFp.
974 //
975 // Revision 1.19  2011/03/16 15:30:09  abbott
976 // Removed two "unsigned" (exponent args).
977 //
978 // Revision 1.18  2011/03/16 13:22:15  abbott
979 // Added comments (about GrDim) for myCmpWDegPartial.
980 //
981 // Revision 1.17  2011/03/10 17:25:51  bigatti
982 // -- added CoCoA_ASSERT in myCmpWDegPartial
983 //
984 // Revision 1.16  2011/03/10 16:39:34  abbott
985 // Replaced (very many) size_t by long in function interfaces (for rings,
986 // PPMonoids and modules).  Also replaced most size_t inside fn defns.
987 //
988 // Revision 1.15  2009/12/23 18:53:52  abbott
989 // Major change to conversion functions:
990 //   convert(..) is now a procedure instead of a function
991 //   IsConvertible(..) replaces the former convert(..) function
992 //   Added new NumericCast conversion function (placeholder for BOOST feature)
993 //   Consequent changes in code which uses these features.
994 //
995 // Revision 1.14  2009/09/22 14:01:33  bigatti
996 // -- added myCmpWDegPartial (ugly name, I know....)
997 // -- cleaned up and realigned code in PPMonoid*.C files
998 //
999 // Revision 1.13  2009/07/24 14:21:42  abbott
1000 // Added an include directive (became necessary after cleaning up other files).
1001 //
1002 // Revision 1.12  2009/03/16 07:28:21  bigatti
1003 // -- fixed a CoCoA_ASSERT on GradingDim
1004 //
1005 // Revision 1.11  2008/05/30 12:44:14  abbott
1006 // Moved "ordering matrices" into their ownn special file.
1007 //
1008 // Revision 1.10  2008/04/21 11:23:11  abbott
1009 // Separated functions dealing with matrices and PPOrderings into a new file.
1010 // Added matrix norms, and completed adjoint.
1011 //
1012 // Revision 1.9  2008/04/18 15:35:57  abbott
1013 // (long overdue) Major revision to matrices
1014 //
1015 // Revision 1.8  2008/04/08 15:26:42  abbott
1016 // Major revision to matrix implementation: added matrix views.
1017 // Lots of changes.
1018 //
1019 // Revision 1.7  2008/03/26 16:52:04  abbott
1020 // Added exponent overflow checks (also for ordvs) when CoCoA_DEBUG is active.
1021 //
1022 // Revision 1.6  2007/12/05 11:06:24  bigatti
1023 // -- changed "size_t StdDeg/myStdDeg(f)" into "long"  (and related functions)
1024 // -- changed "log/myLog(f, i)" into "MaxExponent/myMaxExponent(f, i)"
1025 // -- fixed bug in "IsOne(ideal)" in SparsePolyRing.C
1026 //
1027 // Revision 1.5  2007/12/04 14:27:07  bigatti
1028 // -- changed "log(pp, i)" into "exponent(pp, i)"
1029 //
1030 // Revision 1.4  2007/10/30 17:14:07  abbott
1031 // Changed licence from GPL-2 only to GPL-3 or later.
1032 // New version for such an important change.
1033 //
1034 // Revision 1.3  2007/09/25 16:32:30  abbott
1035 // Several minor changes to silence gcc-4.3:
1036 //    more #includes,
1037 //    and fixed a template problemm in RegisterServerOps.C
1038 //
1039 // Revision 1.2  2007/03/23 18:38:42  abbott
1040 // Separated the "convert" functions (and CheckedCast) into their own files.
1041 // Many consequential changes.  Also corrected conversion to doubles.
1042 //
1043 // Revision 1.1.1.1  2007/03/09 15:16:11  abbott
1044 // Imported files
1045 //
1046 // Revision 1.15  2007/03/08 18:22:29  cocoa
1047 // Just whitespace cleaning.
1048 //
1049 // Revision 1.14  2007/03/07 13:44:15  bigatti
1050 // -- minor cleanup
1051 //
1052 // Revision 1.13  2007/03/02 10:47:53  cocoa
1053 // First stage of RingZ modifications -- tests do not compile currently, Anna will fix this.
1054 //
1055 // Revision 1.12  2007/02/10 18:44:03  cocoa
1056 // Added "const" twice to each test and example.
1057 // Eliminated dependency on io.H in several files.
1058 // Improved BuildInfo, and added an example about how to use it.
1059 // Some other minor cleaning.
1060 //
1061 // Revision 1.11  2006/11/27 14:26:44  cocoa
1062 // -- reorganised #include files
1063 //
1064 // Revision 1.10  2006/11/27 13:06:23  cocoa
1065 // Anna and Michael made me check without writing a proper message.
1066 //
1067 // Revision 1.9  2006/11/24 17:12:05  cocoa
1068 // -- reorganized includes of header files
1069 //
1070 // Revision 1.8  2006/11/23 17:33:10  cocoa
1071 // -- changed: OrdvArith::base is now a class (instead of typedef)
1072 //
1073 // Revision 1.7  2006/11/16 11:27:20  cocoa
1074 // -- reinserted myRefCountZero(): sometimes really necessary, in general safe
1075 //
1076 // Revision 1.6  2006/11/14 17:21:44  cocoa
1077 // -- commented out myRefCountZero() (not necessary?)
1078 //
1079 // Revision 1.5  2006/10/16 23:18:59  cocoa
1080 // Corrected use of std::swap and various special swap functions.
1081 // Improved myApply memfn for homs of RingDistrMPolyInlPP.
1082 //
1083 // Revision 1.4  2006/10/06 14:04:15  cocoa
1084 // Corrected position of #ifndef in header files.
1085 // Separated CoCoA_ASSERT into assert.H from config.H;
1086 // many minor consequential changes (have to #include assert.H).
1087 // A little tidying of #include directives (esp. in Max's code).
1088 //
1089 // Revision 1.3  2006/08/07 21:23:25  cocoa
1090 // Removed almost all publicly visible references to SmallExponent_t;
1091 // changed to long in all PPMonoid functions and SparsePolyRing functions.
1092 // DivMask remains to sorted out.
1093 //
1094 // Revision 1.2  2006/06/21 17:07:10  cocoa
1095 // Fixed IsIndet bug -- why are there three almost identical copies of code?
1096 //
1097 // Revision 1.1.1.1  2006/05/30 11:39:37  cocoa
1098 // Imported files
1099 //
1100 // Revision 1.9  2006/05/02 14:40:19  cocoa
1101 // -- Changed "not" into "!" becuase of M$Windoze (by M.Abshoff)
1102 //
1103 // Revision 1.8  2006/04/05 17:26:04  cocoa
1104 // -- added code to deal with ordering matrix with negative entries
1105 //
1106 // Revision 1.7  2006/03/15 18:09:31  cocoa
1107 // Changed names of member functions which print out their object
1108 // into myOutputSelf -- hope this will appease the Intel C++ compiler.
1109 //
1110 // Revision 1.6  2006/03/12 21:28:34  cocoa
1111 // Major check in after many changes
1112 //
1113 // Revision 1.5  2006/03/07 09:55:10  cocoa
1114 // -- changed: OrdvArith::MatrixOrderingMod32749Impl gives NYI error if
1115 //    matrix has negative entries
1116 //
1117 // Revision 1.4  2006/02/20 22:41:20  cocoa
1118 // All forms of the log function for power products now return SmallExponent_t
1119 // (instead of int).  exponents now resizes the vector rather than requiring
1120 // the user to pass in the correct size.
1121 //
1122 // Revision 1.3  2006/02/15 19:46:41  cocoa
1123 // Corrected check of positivity of input ordering matrix
1124 // (in matrix ordering mod 32749).
1125 //
1126 // Revision 1.2  2005/12/31 12:22:17  cocoa
1127 // Several minor tweaks to silence the Microsoft compiler:
1128 //  - added some missing #includes and using directives
1129 //  - moved some function defns into the right namespace
1130 //  - etc.
1131 //
1132 // Revision 1.1.1.1  2005/10/17 10:46:54  cocoa
1133 // Imported files
1134 //
1135 // Revision 1.6  2005/10/14 15:25:07  cocoa
1136 // Major tidying and cleaning to small prime finite fields.
1137 // Several consequential changes.  Improved their documentation.
1138 //
1139 // Added Makefile and script to include/CoCoA/ directory to
1140 // keep library.H up to date.
1141 //
1142 // Revision 1.5  2005/08/08 16:36:32  cocoa
1143 // Just checking in before going on holiday.
1144 // Don't really recall what changes have been made.
1145 // Added IsIndet function for RingElem, PPMonoidElem,
1146 // and a member function of OrdvArith.
1147 // Improved the way failed assertions are handled.
1148 //
1149 // Revision 1.4  2005/07/01 16:08:15  cocoa
1150 // Friday check-in.  Major change to structure under PolyRing:
1151 // now SparsePolyRing and DUPolyRing are separated (in preparation
1152 // for implementing iterators).
1153 //
1154 // A number of other relatively minor changes had to be chased through
1155 // (e.g. IndetPower).
1156 //
1157 // Revision 1.3  2005/06/23 15:42:41  cocoa
1158 // Fixed typo in GNU fdl -- all doc/*.txt files affected.
1159 // Minor corrections to PPMonoid (discovered while writing doc).
1160 //
1161 // Revision 1.2  2005/06/22 14:47:56  cocoa
1162 // PPMonoids and PPMonoidElems updated to mirror the structure
1163 // used for rings and RingElems.  Many consequential changes.
1164 //
1165 // Revision 1.1.1.1  2005/05/03 15:47:31  cocoa
1166 // Imported files
1167 //
1168 // Revision 1.7  2005/04/20 15:40:48  cocoa
1169 // Major change: modified the standard way errors are to be signalled
1170 // (now via a macro which records filename and line number).  Updated
1171 // documentation in error.txt accordingly.
1172 //
1173 // Improved the documentation in matrix.txt (still more work to be done).
1174 //
1175 // Revision 1.6  2005/04/19 14:06:04  cocoa
1176 // Added GPL and GFDL licence stuff.
1177 //
1178 // Revision 1.5  2005/03/11 18:39:36  cocoa
1179 // -- fixed: myCmpDeg
1180 //
1181 // Revision 1.4  2005/03/02 18:46:41  cocoa
1182 // Added new types ConstRefMatrix, and RefMatrix following along
1183 // the lines of ConstRefRingElem and RefRingElem.  The semantics
1184 // should be a bit clearer now.
1185 //
1186 // Revision 1.3  2005/02/15 18:19:11  cocoa
1187 // -- fixed base::myCmpDeg (if (ShiftCount==0) return 0;)
1188 //
1189 // Revision 1.2  2005/02/11 14:15:20  cocoa
1190 // New style ring elements and references to ring elements;
1191 // I hope I have finally got it right!
1192 //
1193 // Revision 1.1.1.1  2005/01/27 15:12:13  cocoa
1194 // Imported files
1195 //
1196 // Revision 1.7  2004/11/29 16:22:35  cocoa
1197 // -- added function for computing adjoint and inverse for DenseMatrix
1198 //    (so adjoint/inverse matrix is computed by OrdvArith and is no
1199 //    longer needed by PPOrdering)
1200 //
1201 // Revision 1.6  2004/11/11 13:38:27  cocoa
1202 // -- change: cout --> GlobalLogput()
1203 //
1204 // Revision 1.5  2004/11/05 16:37:27  cocoa
1205 // -- change: inverse matrix computed modulo 32749 using RingHom
1206 //
1207 // Revision 1.4  2004/11/03 17:50:31  cocoa
1208 // -- added  mySetMatrix and mySetInverseMatrixTmp  for MatrixOrderingMod32749Impl
1209 //
1210 // Revision 1.3  2004/11/02 15:05:30  cocoa
1211 // -- new: base::myGetExpvBuffer()
1212 // -- new: base::myComputeExpvBuffer
1213 // -- fixed: reference count in destructor
1214 // -- new field: myExpvBuffer
1215 // -- changed: class base is now protected
1216 //
1217 // Revision 1.2  2004/10/29 15:29:30  cocoa
1218 // -- added MatrixOrderingMod32749Impl (not tested)
1219 //
1220 // Revision 1.1  2004/10/21 17:16:37  cocoa
1221 // Fairly major change: new OrdvArith namspace with various members,
1222 //   new global typedef  SmallExponent_t (defined in config.H).
1223 //
1224