1 //   Copyright (c)  2005-2011,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/RingZZ.H"
19 
20 #include "CoCoA/BigIntOps.H"
21 #include "CoCoA/BigRat.H"
22 #include "CoCoA/GlobalManager.H"
23 #include "CoCoA/MemPool.H"
24 #include "CoCoA/NumTheory-prime.H"
25 #include "CoCoA/OpenMath.H"
26 #include "CoCoA/RingHom.H"
27 #include "CoCoA/assert.H"
28 #include "CoCoA/convert.H"
29 #include "CoCoA/error.H"
30 #include "CoCoA/ideal.H"
31 #include "CoCoA/utils.H"
32 
33 #include <iostream>
34 using std::ostream;
35 #include <limits>
36 using std::numeric_limits;
37 #include <vector>
38 using std::vector; // for RingZZImpl::output and RingZZImpl::IdealImpl
39 
40 
41 namespace CoCoA
42 {
43 
44   // This is the concrete class which does all the work.
45   class RingZZImpl: public RingBase
46   {
47   private:
48     typedef mpz_t value_t; // mpz_t is the actual type of the values in a RingZZImpl
49      static value_t& import(RingElemRawPtr rawx);
50     static const value_t& import(RingElemConstRawPtr rawx);
51   private: // data members
52     mutable MemPool myMemMgr;           // MemPool must come BEFORE myZeroPtr and myOnePtr
53     std::unique_ptr<RingElem> myZeroPtr;  ///< Every ring stores its own zero.
54     std::unique_ptr<RingElem> myOnePtr;   ///< Every ring stores its own one.
55 
56   private:
57     RingZZImpl();                        ///< Called only by NewRingZZ
58     RingZZImpl(const RingZZImpl&);           // NEVER DEFINED -- copy ctor disabled
59     RingZZImpl operator=(const RingZZImpl&); // NEVER DEFINED -- assignment disabled
60     ~RingZZImpl();
61     friend ring MakeUniqueInstanceOfRingZZ(); // the only function allowed to call the constructor
62     friend bool RingZZStillInUse(const ring& ZZ);
63 
64     static const mpz_t& AsMPZ(ConstRefRingElem r); // handy in a few member fns
65   public:
66     virtual const ring& myBaseRing() const;
67     virtual void myCharacteristic(BigInt& p) const;
68     virtual bool IamCommutative() const;
69     virtual bool3 IamIntegralDomain3(bool) const;
70     virtual bool IamOrderedDomain() const;
71     virtual bool IamField() const;
72     virtual bool IamFiniteField() const;
73     virtual bool IamExact() const;
74     virtual ConstRefRingElem myZero() const;
75     virtual ConstRefRingElem myOne() const;
76     using RingBase::myNew;    // disable warnings of overloading
77     using RingBase::myAssign; // disable warnings of overloading
78     virtual RingElemRawPtr myNew() const;
79     virtual RingElemRawPtr myNew(const MachineInt& n) const;
80     virtual RingElemRawPtr myNew(const BigInt& N) const;
81     virtual RingElemRawPtr myNew(ConstRawPtr rawcopy) const;
82     virtual void myDelete(RawPtr rawx) const;                      // destroys x (incl all resources)
83     virtual void mySwap(RawPtr rawx, RawPtr rawy) const;                        // swap(x, y)
84     virtual void myAssign(RawPtr rawlhs, ConstRawPtr rawx) const;               // lhs = x
85     virtual void myAssign(RawPtr rawlhs, const MachineInt& n) const;        // lhs = n
86     virtual void myAssign(RawPtr rawlhs, const BigInt& N) const;                // lhs = N
87     virtual void myAssignZero(RawPtr rawlhs) const;                             // lhs = 0
88     virtual void myRecvTwinFloat(RawPtr rawlhs, ConstRawPtr rawx) const;
89     virtual void myNegate(RawPtr rawlhs, ConstRawPtr rawx) const;               // lhs = -x
90     virtual void myAdd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const;        // lhs = x+y
91     virtual void mySub(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const;        // lhs = x-y
92     virtual void myMul(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const;        // lhs = x*y
93     virtual void myDiv(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const;        // lhs = x/y
94     virtual bool myIsDivisible(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const;// lhs = x/y, if divisible
95     virtual bool myIsInvertible(ConstRawPtr rawx) const;                                // true iff x is invertible
96     virtual bool myIsIrred(ConstRawPtr rawx) const;                                  ///< true iff x is irreducible (if defined)
97     virtual void myGcd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const;        // lhs = gcd(x,y) if TrueGCDDomain;
98     virtual void myExgcd(RawPtr rawlhs, RawPtr rawxcofac, RawPtr rawycofac, ConstRawPtr rawx, ConstRawPtr rawy) const;            // lhs = gcd(x,y) = xcofac*x + ycofac*y  if TrueGCDDomain;
99     //    virtual void myNormalizeFrac: use default defn
100     virtual void myPowerSmallExp(RawPtr rawlhs, ConstRawPtr rawx, long n) const; // lhs = x^n, n>1, x not -1,0,1
101     virtual void myOutput(std::ostream& out, ConstRawPtr rawx) const;             // out << x
102     virtual bool myIsPrintAtom(ConstRawPtr rawx) const;
103     virtual bool myIsPrintedWithMinus(ConstRawPtr rawx) const;
myOutputSelf(std::ostream & out)104     virtual void myOutputSelf(std::ostream& out) const       { out << "ZZ"; }
myOutputSelfShort(std::ostream & out)105     virtual void myOutputSelfShort(std::ostream& out) const  { out << "ZZ"; }
106     void myOutputSelfLong(ostream& out) const;
107     virtual void myOutputSelf(OpenMathOutput& OMOut) const;                       // OMOut << R
108     virtual void myOutput(OpenMathOutput& OMOut, ConstRawPtr rawx) const;         // OMOut << x
109     virtual bool myIsZero(ConstRawPtr rawx) const;                                // x == 0
110     virtual bool myIsOne(ConstRawPtr rawx) const;                                 // x == 1
111     virtual bool myIsMinusOne(ConstRawPtr rawx) const;                            // x == -1
112     virtual bool myIsInteger(BigInt& N, ConstRawPtr rawx) const;                  // true iff x is integer
113     virtual bool myIsRational(BigRat& Q, ConstRawPtr rawx) const;                     // true iff x is rational
114     virtual bool myIsDouble(double& d, ConstRawPtr rawx) const;                   // false iff x overflows
115     //    virtual bool myIsZeroAddMul: use default definition
116     virtual bool myIsEqual(ConstRawPtr rawx, ConstRawPtr rawy) const;             // x == y
117     virtual int myCmp(ConstRawPtr rawx, ConstRawPtr rawy) const;                  // result is <0, =0, >0 according as x<y, x=y, x>y
118     virtual int myCmpAbs(ConstRawPtr rawx, ConstRawPtr rawy) const;               // equiv to myCmp(abs(x),abs(y))
119     virtual int mySign(ConstRawPtr rawx) const;                                   // -1,0,+1 according as x <0,=0,>0
120     virtual BigInt myFloor(ConstRawPtr rawx) const;                               // identity fn
121     virtual BigInt myCeil(ConstRawPtr rawx) const;                                // identity fn
122     virtual BigInt myNearestInt(ConstRawPtr rawx) const;                          // identity fn
123 
mySymbolValue(const symbol &)124     virtual RingElem mySymbolValue(const symbol& /*sym*/) const {CoCoA_THROW_ERROR("This ring has no symbols", "RingZZImpl::mySymbolValue"); return myZero();}
125     virtual ideal myIdealCtor(const std::vector<RingElem>& gens) const;
126 
127     virtual RingHom myCompose(const RingHom& phi, const RingHom& theta) const; // phi(theta(...))
128 
129     virtual bool myImageLiesInSubfield(const RingHom& phi) const;
130 
131     // Function special to RingZZBase
132     virtual RingHom myZZEmbeddingHomCtor(const ring& codomain) const;
133 
134   private: // homomorphism class
135     class HomImpl: public RingHomBase
136     {
137     public:
138       HomImpl(const ring& ZZ, const ring& codomain);
139       void myApply(RawPtr rawimage, ConstRawPtr rawarg) const;
IamPartial()140       virtual bool IamPartial() const { return false; }
141     };
142 
143   private: // ideal class
144 
145     class IdealImpl: public IdealBase
146     {
147     public:
148       IdealImpl(const ring& ZZ, const std::vector<RingElem>& gens);
149       // Default copy ctor works fine.
150       // Assignment disabled (see below)
151       virtual ~IdealImpl();
152     private: // disable assignment
153       IdealImpl& operator=(const IdealImpl&); // NEVER DEFINED -- assignment disabled
154     public:
155       virtual IdealImpl* myClone() const;
156 //???    virtual void swap(ideal& other);
157 
158       virtual const ring& myRing() const;
159       virtual bool IamZero() const;
160       virtual bool IamOne() const;
161       virtual bool IhaveElem(RingElemConstRawPtr rawx) const;
162       virtual void myReduceMod(RingElemRawPtr rawx) const;
163       virtual void myAdd(const ideal&);
164       virtual void myMul(const ideal&);
165       virtual void myIntersect(const ideal&);
166       virtual void myColon(const ideal&);
167       virtual bool myDivMod(RingElemRawPtr rawlhs, RingElemConstRawPtr rawnum, RingElemConstRawPtr rawden) const; // true iff quotient exists & is unique, sets lhs = num/den modulo I iff result is true
168 
169       virtual const std::vector<RingElem>& myGens() const; // gens as specified by user
170       virtual const std::vector<RingElem>& myTidyGens(const CpuTimeLimit&) const; // tidier set of gens
171 
172     protected:
173       virtual void myTestIsMaximal() const;
174       virtual void myTestIsPrimary() const;
175       virtual void myTestIsPrime() const;
176       virtual void myTestIsRadical() const;
177 
178     private: // data members
179       const ring myR;
180       std::vector<RingElem> myGensValue;
181       std::vector<RingElem> myTidyGensValue;
182       static const IdealImpl* GetPtr(const ideal& I);
183     };
184   };
185 
186 
187 
import(RingElemRawPtr rawx)188   inline RingZZImpl::value_t& RingZZImpl::import(RingElemRawPtr rawx)
189   {
190     return *static_cast<value_t*>(rawx.myRawPtr());
191   }
192 
import(RingElemConstRawPtr rawx)193   inline const RingZZImpl::value_t& RingZZImpl::import(RingElemConstRawPtr rawx)
194   {
195     return *static_cast<const value_t*>(rawx.myRawPtr());
196   }
197 
198 
AsMPZ(ConstRefRingElem x)199   inline const mpz_t& RingZZImpl::AsMPZ(ConstRefRingElem x)
200   {
201     CoCoA_ASSERT(IsZZ(owner(x)));
202     return RingZZImpl::import(raw(x));
203   }
204 
205 
206 
RingZZImpl()207   RingZZImpl::RingZZImpl():
208       myMemMgr(sizeof(value_t), "RingZZImpl.myMemMgr"),
209       myZeroPtr(),
210       myOnePtr()
211   {
212     myRefCountInc();  // this is needed for exception cleanliness, in case one of the lines below throws
213     myZeroPtr.reset(new RingElem(ring(this)));
214     myOnePtr.reset(new RingElem(ring(this), 1));
215     myRefCountZero();
216   }
217 
218 
~RingZZImpl()219   RingZZImpl::~RingZZImpl()
220   {}
221 
222 
myBaseRing()223   const ring& RingZZImpl::myBaseRing() const
224   {
225     CoCoA_THROW_ERROR(ERR::BadArg, "BaseRing");
226     return RingZZ();
227   }
228 
229 
myCharacteristic(BigInt & p)230   void RingZZImpl::myCharacteristic(BigInt& p) const
231   {
232     p = 0;
233   }
234 
235 
IamCommutative()236   bool RingZZImpl::IamCommutative() const
237   {
238     return true;
239   }
240 
241 
IamIntegralDomain3(bool)242   bool3 RingZZImpl::IamIntegralDomain3(bool) const
243   {
244     return true3;
245   }
246 
247 
IamOrderedDomain()248   bool RingZZImpl::IamOrderedDomain() const
249   {
250     return true;
251   }
252 
253 
IamField()254   bool RingZZImpl::IamField() const
255   {
256     return false;
257   }
258 
259 
IamFiniteField()260   bool RingZZImpl::IamFiniteField() const
261   {
262     return false;
263   }
264 
265 
IamExact()266   bool RingZZImpl::IamExact() const
267   {
268     return true;
269   }
270 
271 
myZero()272   ConstRefRingElem RingZZImpl::myZero() const
273   {
274     return *myZeroPtr;
275   }
276 
277 
myOne()278   ConstRefRingElem RingZZImpl::myOne() const
279   {
280     return *myOnePtr;
281   }
282 
283 
myNew()284   RingElemRawPtr RingZZImpl::myNew() const
285   {
286     value_t* ans = static_cast<value_t*>(myMemMgr.alloc());
287     mpz_init(*ans);
288     return RingElemRawPtr(ans);
289   }
290 
291 
myNew(const MachineInt & n)292   RingElemRawPtr RingZZImpl::myNew(const MachineInt& n) const
293   {
294     value_t* ans = static_cast<value_t*>(myMemMgr.alloc());
295     if (IsNegative(n))
296       mpz_init_set_si(*ans, AsSignedLong(n));
297     else
298       mpz_init_set_ui(*ans, AsUnsignedLong(n));
299     return RingElemRawPtr(ans);
300   }
301 
302 
myNew(const BigInt & N)303   RingElemRawPtr RingZZImpl::myNew(const BigInt& N) const
304   {
305     value_t* ans = static_cast<value_t*>(myMemMgr.alloc());
306     mpz_init_set(*ans, mpzref(N));
307     return RingElemRawPtr(ans);
308   }
309 
310 
myNew(ConstRawPtr rawcopy)311   RingElemRawPtr RingZZImpl::myNew(ConstRawPtr rawcopy) const
312   {
313     value_t *ans = static_cast<value_t*>(myMemMgr.alloc());
314     mpz_init_set(*ans, import(rawcopy));
315     return RingElemRawPtr(ans);
316   }
317 
318 
myDelete(RawPtr rawx)319   void RingZZImpl::myDelete(RawPtr rawx) const
320   {
321     mpz_clear(import(rawx)); // EXPLICIT dtor call here
322     myMemMgr.free(rawx.myRawPtr());
323   }
324 
325 
mySwap(RawPtr rawx,RawPtr rawy)326   void RingZZImpl::mySwap(RawPtr rawx, RawPtr rawy) const
327   {
328     mpz_swap(import(rawx), import(rawy));
329   }
330 
331 
myAssign(RawPtr rawlhs,ConstRawPtr rawx)332   void RingZZImpl::myAssign(RawPtr rawlhs, ConstRawPtr rawx) const
333   {
334     mpz_set(import(rawlhs), import(rawx));
335   }
336 
337 
myAssign(RawPtr rawlhs,const MachineInt & n)338   void RingZZImpl::myAssign(RawPtr rawlhs, const MachineInt& n) const
339   {
340     if (IsNegative(n))
341       mpz_set_si(import(rawlhs), AsSignedLong(n));
342     else
343       mpz_set_ui(import(rawlhs), AsUnsignedLong(n));
344   }
345 
346 
myAssign(RawPtr rawlhs,const BigInt & N)347   void RingZZImpl::myAssign(RawPtr rawlhs, const BigInt& N) const
348   {
349     mpz_set(import(rawlhs), mpzref(N));
350   }
351 
352 
myAssignZero(RawPtr rawlhs)353   void RingZZImpl::myAssignZero(RawPtr rawlhs) const
354   {
355     mpz_set_ui(import(rawlhs), 0);
356   }
357 
358 
myRecvTwinFloat(RawPtr,ConstRawPtr)359   void RingZZImpl::myRecvTwinFloat(RawPtr /*rawlhs*/, ConstRawPtr /*rawx*/) const
360   {
361     CoCoA_THROW_ERROR(ERR::ShouldNeverGetHere, "RingZZImpl::myRecvTwinFloat");
362   }
363 
myNegate(RawPtr rawlhs,ConstRawPtr rawx)364   void RingZZImpl::myNegate(RawPtr rawlhs, ConstRawPtr rawx) const
365   {
366     mpz_neg(import(rawlhs), import(rawx));
367   }
368 
369 
myAdd(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)370   void RingZZImpl::myAdd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
371   {
372     mpz_add(import(rawlhs), import(rawx), import(rawy));
373   }
374 
375 
mySub(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)376   void RingZZImpl::mySub(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
377   {
378     mpz_sub(import(rawlhs), import(rawx), import(rawy));
379   }
380 
381 
myMul(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)382   void RingZZImpl::myMul(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
383   {
384     mpz_mul(import(rawlhs), import(rawx), import(rawy));
385   }
386 
387 
myDiv(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)388   void RingZZImpl::myDiv(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
389   {
390     CoCoA_ASSERT(!myIsZero(rawy));
391     mpz_divexact(import(rawlhs), import(rawx), import(rawy));
392   }
393 
394 
myIsDivisible(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)395   bool RingZZImpl::myIsDivisible(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
396   {
397     if (myIsZero(rawy)) return false;
398     BigInt remainder;
399     mpz_tdiv_qr(import(rawlhs), mpzref(remainder), import(rawx), import(rawy));
400     return IsZero(remainder);
401   }
402 
403 
myIsInvertible(ConstRawPtr rawx)404   bool RingZZImpl::myIsInvertible(ConstRawPtr rawx) const
405   {
406     return myIsOne(rawx) || myIsMinusOne(rawx);
407   }
408 
409 
myIsIrred(ConstRawPtr rawx)410   bool RingZZImpl::myIsIrred(ConstRawPtr rawx) const
411   {
412     CoCoA_ASSERT(!myIsZero(rawx));
413 //    if (myIsZero(rawx)) CoCoA_THROW_ERROR(ERR::ZeroRingElem, "IsIrred");
414     return IsPrime(abs(BigIntFromMPZ(import(rawx))));
415   }
416 
417 
myGcd(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)418   void RingZZImpl::myGcd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
419   {
420     mpz_gcd(import(rawlhs), import(rawx), import(rawy));
421   }
422 
423 
myExgcd(RawPtr rawlhs,RawPtr rawxcofac,RawPtr rawycofac,ConstRawPtr rawx,ConstRawPtr rawy)424   void RingZZImpl::myExgcd(RawPtr rawlhs, RawPtr rawxcofac, RawPtr rawycofac, ConstRawPtr rawx, ConstRawPtr rawy) const
425   {
426     mpz_gcdext(import(rawlhs), import(rawxcofac), import(rawycofac), import(rawx), import(rawy));
427   }
428 
429 
myPowerSmallExp(RawPtr rawlhs,ConstRawPtr rawx,long n)430   void RingZZImpl::myPowerSmallExp(RawPtr rawlhs, ConstRawPtr rawx, long n) const
431   {
432     // Assert that we have a genuinely non-trivial case.
433     CoCoA_ASSERT(n > 1);
434     CoCoA_ASSERT(!myIsZero(rawx) && !myIsOne(rawx) && !myIsMinusOne(rawx));
435     mpz_pow_ui(import(rawlhs), import(rawx), n);
436   }
437 
438 
myOutput(ostream & out,ConstRawPtr rawx)439   void RingZZImpl::myOutput(ostream& out, ConstRawPtr rawx) const
440   {
441     if (!out) return;  // short-cut for bad ostreams
442     vector<char> buffer(mpz_sizeinbase(import(rawx),10)+2);
443     mpz_get_str(&buffer[0], 10, import(rawx));
444     out << &buffer[0];
445   }
446 
447 
myIsPrintAtom(ConstRawPtr rawx)448   bool RingZZImpl::myIsPrintAtom(ConstRawPtr rawx) const
449   {
450     return mySign(rawx)>=0;
451   }
452 
453 
myFloor(ConstRawPtr rawx)454   BigInt RingZZImpl::myFloor(ConstRawPtr rawx) const
455   {
456     BigInt N;
457     myIsInteger(N, rawx);
458     return N;
459   }
460 
myCeil(ConstRawPtr rawx)461   BigInt RingZZImpl::myCeil(ConstRawPtr rawx) const
462   {
463     BigInt N;
464     myIsInteger(N, rawx);
465     return N;
466   }
467 
myNearestInt(ConstRawPtr rawx)468   BigInt RingZZImpl::myNearestInt(ConstRawPtr rawx) const
469   {
470     BigInt N;
471     myIsInteger(N, rawx);
472     return N;
473   }
474 
475 
myIsPrintedWithMinus(ConstRawPtr rawx)476   bool RingZZImpl::myIsPrintedWithMinus(ConstRawPtr rawx) const
477   {
478     return mySign(rawx)<0;
479   }
480 
481 
myOutputSelfLong(ostream & out)482   void RingZZImpl::myOutputSelfLong(ostream& out) const
483   {
484     if (!out) return;  // short-cut for bad ostreams
485     out << "RingWithID(" << myID << ", \"ZZ\")";
486   }
487 
488 
myOutputSelf(OpenMathOutput & OMOut)489   void RingZZImpl::myOutputSelf(OpenMathOutput& OMOut) const
490   {
491     OMOut << OpenMathSymbol("setname1", "Z");
492   }
493 
494 
myOutput(OpenMathOutput & OMOut,ConstRawPtr rawx)495   void RingZZImpl::myOutput(OpenMathOutput& OMOut, ConstRawPtr rawx) const
496   {
497     OMOut << BigIntFromMPZ(import(rawx));  // have to get value of x as a BigInt
498   }
499 
500 
myIsZero(ConstRawPtr rawx)501   bool RingZZImpl::myIsZero(ConstRawPtr rawx) const
502   {
503     return mpz_sgn(import(rawx)) == 0;
504   }
505 
506 
myIsOne(ConstRawPtr rawx)507   bool RingZZImpl::myIsOne(ConstRawPtr rawx) const
508   {
509     return mpz_cmp_ui(import(rawx), 1) == 0;
510   }
511 
512 
myIsMinusOne(ConstRawPtr rawx)513   bool RingZZImpl::myIsMinusOne(ConstRawPtr rawx) const
514   {
515     return mpz_cmp_si(import(rawx), -1) == 0;
516   }
517 
518 
myIsInteger(BigInt & N,ConstRawPtr rawx)519   bool RingZZImpl::myIsInteger(BigInt& N, ConstRawPtr rawx) const
520   {
521     mpz_set(mpzref(N), import(rawx));
522     return true;
523   }
524 
525 
myIsRational(BigRat & Q,ConstRawPtr rawx)526   bool RingZZImpl::myIsRational(BigRat& Q, ConstRawPtr rawx) const
527   {
528     mpq_set_z(mpqref(Q), import(rawx));
529     return true;
530   }
531 
myIsDouble(double & d,ConstRawPtr rawx)532   bool RingZZImpl::myIsDouble(double& d, ConstRawPtr rawx) const
533   {
534     long exp;
535     d = mpz_get_d_2exp(&exp, import(rawx)); // BUG, ignore possible overflow in exp
536     if (numeric_limits<double>::radix != 2) CoCoA_THROW_ERROR(ERR::NYI, "RingZZImpl::myIsDouble");
537     if (exp < numeric_limits<double>::min_exponent) { d=0; return true; }  // ???false also for underflow???
538     if (exp > numeric_limits<double>::max_exponent) return false;
539     d = ldexp(d,exp);
540     return true;
541   }
542 
543 
myIsEqual(ConstRawPtr rawx,ConstRawPtr rawy)544   bool RingZZImpl::myIsEqual(ConstRawPtr rawx, ConstRawPtr rawy) const
545   {
546     return mpz_cmp(import(rawx), import(rawy)) == 0;
547   }
548 
549 
myCmp(ConstRawPtr rawx,ConstRawPtr rawy)550   int RingZZImpl::myCmp(ConstRawPtr rawx, ConstRawPtr rawy) const
551   {
552     return sign(mpz_cmp(import(rawx), import(rawy)));
553   }
554 
555 
myCmpAbs(ConstRawPtr rawx,ConstRawPtr rawy)556   int RingZZImpl::myCmpAbs(ConstRawPtr rawx, ConstRawPtr rawy) const
557   {
558     return sign(mpz_cmpabs(import(rawx), import(rawy)));
559   }
560 
561 
mySign(ConstRawPtr rawx)562   int RingZZImpl::mySign(ConstRawPtr rawx) const
563   {
564     return mpz_sgn(import(rawx)); // Needs modification for GMP older than 4.1
565   }
566 
567 
myIdealCtor(const std::vector<RingElem> & gens)568   ideal RingZZImpl::myIdealCtor(const std::vector<RingElem>& gens) const
569   {
570     return ideal(new RingZZImpl::IdealImpl(ring(this), gens));
571   }
572 
573 
574   //---------------------------------------------------------------------------
575   // Functions to do with ring homomorphisms
576 
myZZEmbeddingHomCtor(const ring & codomain)577   RingHom RingZZImpl::myZZEmbeddingHomCtor(const ring& codomain) const
578   {
579     if (IsZZ(codomain)) return IdentityHom(ring(this));
580     return RingHom(new RingZZImpl::HomImpl(ring(this), codomain));
581   }
582 
583 
myCompose(const RingHom & phi,const RingHom &)584   RingHom RingZZImpl::myCompose(const RingHom& phi, const RingHom& /*theta*/) const
585   {
586     return myZZEmbeddingHomCtor(codomain(phi));
587   }
588 
589 
myImageLiesInSubfield(const RingHom & phi)590   bool RingZZImpl::myImageLiesInSubfield(const RingHom& phi) const
591   {
592     (void)(phi); // to avoid compiler warning about unused parameter
593     CoCoA_ASSERT(codomain(phi) == ring(this));
594     return false;
595   }
596 
597 
598   //---------------------------------------------------------------------------
599   // Homomorphisms
600 
HomImpl(const ring & ZZ,const ring & codomain)601   RingZZImpl::HomImpl::HomImpl(const ring& ZZ, const ring& codomain):
602       RingHomBase(ZZ, codomain)
603   {}
604 
605 
myApply(RawPtr rawimage,ConstRawPtr rawarg)606   void RingZZImpl::HomImpl::myApply(RawPtr rawimage, ConstRawPtr rawarg) const
607   {
608     // Unfortunately we have to copy the value of arg.
609     BigInt N;  // wasteful new/delete???
610     myDomain->myIsInteger(N, rawarg);  // must necessarily succeed
611     myCodomain->myAssign(rawimage, N);
612   }
613 
614 
615   //---------------------------------------------------------------------------
616   // Ideals
617 
GetPtr(const ideal & I)618   inline const RingZZImpl::IdealImpl* RingZZImpl::IdealImpl::GetPtr(const ideal& I)
619   {
620     return dynamic_cast<const RingZZImpl::IdealImpl*>(I.myIdealPtr());
621   }
622 
623 
IdealImpl(const ring & ZZ,const std::vector<RingElem> & gens)624   RingZZImpl::IdealImpl::IdealImpl(const ring& ZZ, const std::vector<RingElem>& gens):
625       myR(ZZ),
626       myGensValue(gens),
627       myTidyGensValue()
628   {
629     RingElem g(ZZ);
630     for (long i=0; i < len(gens); ++i) // break out if g=1???
631       g = gcd(g, gens[i]);
632     if (IsZero(g)) return;
633     myTidyGensValue.push_back(g);
634   }
635 
636 
~IdealImpl()637   RingZZImpl::IdealImpl::~IdealImpl()
638   {}
639 
640 
myClone()641   RingZZImpl::IdealImpl* RingZZImpl::IdealImpl::myClone() const
642   {
643     return new IdealImpl(*this);
644   }
645 
646 
647 //???  void RingZZImpl::IdealImpl::swap(CoCoA::ideal& J) {}
648 
649 
myRing()650   const ring& RingZZImpl::IdealImpl::myRing() const
651   {
652     return myR;
653   }
654 
655 
IamZero()656   bool RingZZImpl::IdealImpl::IamZero() const
657   {
658     return myTidyGensValue.empty();
659   }
660 
661 
IamOne()662   bool RingZZImpl::IdealImpl::IamOne() const
663   {
664     return !myTidyGensValue.empty() && IsOne(myTidyGensValue[0]);
665   }
666 
667 
myReduceMod(RawPtr rawx)668   void RingZZImpl::IdealImpl::myReduceMod(RawPtr rawx) const
669   {
670     if (IamZero()) return;
671     mpz_fdiv_r(import(rawx), import(rawx), AsMPZ(myTidyGensValue[0]));
672   }
673 
674 
IhaveElem(const RingElemConstRawPtr rawx)675   bool RingZZImpl::IdealImpl::IhaveElem(const RingElemConstRawPtr rawx) const
676   {
677     if (myR->myIsZero(rawx)) return true;
678     if (IamZero()) return false;
679     RingElem junk(myR);
680     return myR->myIsDivisible(raw(junk), rawx, raw(myTidyGensValue[0]));
681   }
682 
683 
myAdd(const ideal & J)684   void RingZZImpl::IdealImpl::myAdd(const ideal& J)
685   {
686     const IdealImpl* J1 = GetPtr(J);
687     myGensValue.insert(myGensValue.end(), gens(J).begin(), gens(J).end());
688     if (IsZero(J)) return;
689     if (IamZero())
690     {
691       myTidyGensValue.push_back(J1->myTidyGensValue[0]);
692       IamPrime3Flag = IamMaximal3Flag = J1->IamMaximal3Flag;
693       return;
694     }
695     myTidyGensValue[0] = gcd(myTidyGensValue[0], J1->myTidyGensValue[0]);
696     IamPrime3Flag = IamMaximal3Flag = uncertain3;
697   }
698 
699 
myMul(const ideal & J)700   void RingZZImpl::IdealImpl::myMul(const ideal& J)
701   {
702     if (IamZero()) return;
703     //    CoCoA_THROW_ERROR(ERR::NYI, "RingZZImpl::IdealImpl::mul");
704     if (IsZero(J)) { myGensValue.clear(); myTidyGensValue.clear(); IamPrime3Flag = true3; IamMaximal3Flag = false3; return; }
705     const IdealImpl* J1 = GetPtr(J);
706     myTidyGensValue[0] = myTidyGensValue[0]*J1->myTidyGensValue[0];
707     myGensValue = myTidyGensValue;
708     IamPrime3Flag = IamMaximal3Flag = uncertain3;
709   }
710 
711 
myIntersect(const ideal & J)712   void RingZZImpl::IdealImpl::myIntersect(const ideal& J)
713   {
714     if (IamZero() || IsOne(J)) return;
715     if (IsZero(J)) { myGensValue.clear(); myTidyGensValue.clear(); IamPrime3Flag = true3; IamMaximal3Flag = false3; return; }
716     const IdealImpl* J1 = GetPtr(J);
717     myTidyGensValue[0] = lcm(myTidyGensValue[0], J1->myTidyGensValue[0]);
718     myGensValue = myTidyGensValue;
719     IamPrime3Flag = IamMaximal3Flag = uncertain3;
720   }
721 
722 
myColon(const ideal & J)723   void RingZZImpl::IdealImpl::myColon(const ideal& J)
724   {
725     if (IsZero(J))
726     {
727       if (IamZero()) myTidyGensValue.push_back(one(myR));
728       else myTidyGensValue[0] = 1;
729       myGensValue = myTidyGensValue;
730       IamPrime3Flag = IamMaximal3Flag = false3;
731       return;
732     }
733     if (IamZero()) return;
734     const IdealImpl* J1 = GetPtr(J);
735     myTidyGensValue[0] = myTidyGensValue[0]/gcd(myTidyGensValue[0], J1->myTidyGensValue[0]);
736     myGensValue = myTidyGensValue;
737     IamPrime3Flag = IamMaximal3Flag = uncertain3;
738   }
739 
740 
myDivMod(RingElemRawPtr rawlhs,RingElemConstRawPtr rawnum,RingElemConstRawPtr rawden)741   bool RingZZImpl::IdealImpl::myDivMod(RingElemRawPtr rawlhs, RingElemConstRawPtr rawnum, RingElemConstRawPtr rawden) const
742   {
743     const ring& ZZ = myRing();
744     if (IamOne()) { ZZ->myAssignZero(rawlhs); return true; }
745     if (IamZero())
746     {
747       return ZZ->myIsDivisible(rawlhs, rawnum, rawden);
748     }
749 
750     const BigInt m = ConvertTo<BigInt>(myTidyGensValue[0]);
751     BigInt g, RecipDen, junk;
752     mpz_gcdext(mpzref(g), mpzref(RecipDen), mpzref(junk), import(rawden), mpzref(m));
753     if (!IsOne(g)) { return false; } // (gcd != 1) ==>  quot not uniquely defd in this ring
754 //2013-06-15    BigInt quo, rem;
755 //2013-06-15    mpz_fdiv_qr(mpzref(quo), mpzref(rem), import(rawnum), mpzref(g));
756 //2013-06-15    if (!IsZero(rem)) { ZZ->myAssignZero(rawlhs); return; }
757 //???    if (!CoCoA::IsZero(rem)) CoCoA_THROW_ERROR(ERR::DivByZero, "RingZZImpl::IdealImpl::inverse");
758 //2013-06-15    mpz_mul(import(rawlhs), mpzref(quo), mpzref(RecipDen));
759     mpz_mul(mpzref(junk), import(rawnum), mpzref(RecipDen));
760     mpz_mod(import(rawlhs), mpzref(junk), mpzref(m));
761     return true;
762   }
763 
764 
myGens()765   const std::vector<RingElem>& RingZZImpl::IdealImpl::myGens() const
766   {
767     return myGensValue;
768   }
769 
770 
myTidyGens(const CpuTimeLimit &)771   const std::vector<CoCoA::RingElem>& RingZZImpl::IdealImpl::myTidyGens(const CpuTimeLimit&) const
772   {
773     return myTidyGensValue;
774   }
775 
776 
myTestIsMaximal()777   void RingZZImpl::IdealImpl::myTestIsMaximal() const
778   {
779     myAssignMaximalFlag(!IamZero() && !IamOne() && mpz_probab_prime_p(AsMPZ(myTidyGensValue[0]), 25)); // trust to luck in randomized primality test
780   }
781 
782 
myTestIsPrimary()783   void RingZZImpl::IdealImpl::myTestIsPrimary() const
784   { CoCoA_THROW_ERROR(ERR::NYI, "myTestIsPrimary ZZ"); }
785 
786 
myTestIsPrime()787   void RingZZImpl::IdealImpl::myTestIsPrime() const
788   { myAssignPrimeFlag(IamZero() || IamMaximal()); }
789 
790 
myTestIsRadical()791   void RingZZImpl::IdealImpl::myTestIsRadical() const
792   { CoCoA_THROW_ERROR(ERR::NYI, "myTestIsRadical ZZ"); }
793 
794 
795   //---------------------------------------------------------------------------
796 
797   // This fn should be called only by ctor for CoCoA::GlobalManager (see GlobalManager.C)
MakeUniqueInstanceOfRingZZ()798   ring MakeUniqueInstanceOfRingZZ()
799   { return ring(new RingZZImpl()); }
800 
801 
RingZZ()802   const ring& RingZZ()
803   {
804     if (GlobalManager::ourGlobalDataPtr == nullptr)
805       CoCoA_THROW_ERROR(ERR::NoGlobalMgr, "RingZZ()");
806     return GlobalManager::ourGlobalDataPtr->myRingZZ();
807   }
808 
809 
IsZZ(const ring & R)810   bool IsZZ(const ring& R)
811   { return dynamic_cast<const RingZZImpl*>(R.myRawPtr()) != nullptr; }
812 
813 
ZZEmbeddingHom(const ring & codomain)814   RingHom ZZEmbeddingHom(const ring& codomain)
815   {
816     // Ugly down cast of raw ptr in RingZZ() to type RingZZImpl*.
817     const RingZZImpl* const ZZPtr = static_cast<const RingZZImpl*>(RingZZ().myRawPtr());
818     return ZZPtr->myZZEmbeddingHomCtor(codomain);
819   }
820 
ZZEmbeddingHom(const ring & ZZ,const ring & codomain)821   RingHom ZZEmbeddingHom(const ring& ZZ, const ring& codomain)
822   {
823     CoCoA_ASSERT(IsZZ(ZZ));
824     // Ugly down cast of raw ptr in RingZZ() to type RingZZImpl*.
825     const RingZZImpl* const ZZPtr = static_cast<const RingZZImpl*>(ZZ.myRawPtr());
826     return ZZPtr->myZZEmbeddingHomCtor(codomain);
827   }
828 
829 
830   // This fn is used only in the dtor for GlobalManager.
RingZZStillInUse(const ring & ZZ)831   bool RingZZStillInUse(const ring& ZZ)
832   {
833     const RingZZImpl* ZZptr = dynamic_cast<const RingZZImpl*>(ZZ.myRawPtr());
834 #ifdef CoCoA_DEBUG
835     if (ZZptr->myRefCount() > 3)
836       std::cerr << "ERROR!!!  RingZZ refcount = " << ZZptr->myRefCount() << " but should be 3." << std::endl;
837 #endif
838     return ZZptr->myRefCount() > 3; // copy in GlobalManager & as base ring of RingQQ & in RingQQ embedding hom
839   }
840 
841 
842 } // end of namespace CoCoA
843 
844 
845 // RCS header/log in the next few lines
846 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/RingZZ.C,v 1.36 2020/06/17 15:49:27 abbott Exp $
847 // $Log: RingZZ.C,v $
848 // Revision 1.36  2020/06/17 15:49:27  abbott
849 // Summary: Changed CoCoA_ERROR into CoCoA_THROW_ERROR
850 //
851 // Revision 1.35  2020/02/12 09:01:47  bigatti
852 // -- changed myTestIsMaximal etc to return void (and consequences)
853 //
854 // Revision 1.34  2020/02/11 16:56:42  abbott
855 // Summary: Corrected last update (see redmine 969)
856 //
857 // Revision 1.33  2020/02/11 16:12:19  abbott
858 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969
859 //
860 // Revision 1.32  2019/10/15 11:54:08  abbott
861 // Summary: Changed 0 into nullptr (where appropriate)
862 //
863 // Revision 1.31  2019/03/04 11:11:54  abbott
864 // Summary: Changed auto_ptr into unique_ptr
865 //
866 // Revision 1.30  2018/05/25 09:24:46  abbott
867 // Summary: Major redesign of CpuTimeLimit (many consequences)
868 //
869 // Revision 1.29  2018/05/18 12:22:30  bigatti
870 // -- renamed IntOperations --> BigIntOps
871 //
872 // Revision 1.28  2018/04/20 18:51:25  abbott
873 // Summary: Changed ctors for BigInt/BigRat from string or from MPZ/MPQ
874 //
875 // Revision 1.27  2018/03/29 09:36:40  bigatti
876 // -- added member functions myTestIsRadical, myTestIsPrimary and flags
877 //
878 // Revision 1.26  2018/03/20 11:38:07  bigatti
879 // -- changed iAm***Test --> myTestIs***;  and it returns bool
880 //
881 // Revision 1.25  2018/02/27 17:30:22  abbott
882 // Summary: Renamed NumTheory_prime to NumTheory-prime; changed includes
883 //
884 // Revision 1.24  2018/02/27 10:56:21  abbott
885 // Summary: Added include NumTheory_prime
886 //
887 // Revision 1.23  2017/11/08 14:05:24  abbott
888 // Summary: Corrected myIsIrred
889 //
890 // Revision 1.22  2017/09/06 11:56:30  abbott
891 // Summary: Changed ERR::SERIOUS into ERR::ShouldNeverGetHere
892 //
893 // Revision 1.21  2016/09/08 14:12:32  bigatti
894 // -- mySetMaximalFlag --> myAssignMaximalFlag
895 // -- mySetPrimeFlag --> myAssignPrimeFlag
896 // -- updated the related code
897 // -- (still "old design", but better aligned)
898 //
899 // Revision 1.20  2016/03/25 20:06:49  abbott
900 // Summary: Introduced new mem fns myCeil and myNearestInt; impls in ZZ, QQ, & TwinFloat. Renamed NearestInteger to NearestInt.
901 //
902 // Revision 1.19  2015/07/29 11:04:54  bigatti
903 // -- added space after comma in printing rings
904 //
905 // Revision 1.18  2014/07/30 14:09:43  abbott
906 // Summary: Changed myAmbientRing --> myRing
907 // Author: JAA
908 //
909 // Revision 1.17  2014/07/11 15:49:55  bigatti
910 // -- added  myOutputSelfLong
911 //
912 // Revision 1.16  2014/07/08 13:14:41  abbott
913 // Summary: Removed AsQuotientRing; added new defn of BaseRing
914 // Author: JAA
915 //
916 // Revision 1.15  2014/06/14 19:45:07  abbott
917 // Summary: Added new fn CmpAbs for RingElem (via memfn myCmpAbs)
918 // Author: JAA
919 //
920 // Revision 1.14  2014/05/14 15:57:15  bigatti
921 // -- added "using" for clang with superpedantic flag
922 //
923 // Revision 1.13  2014/04/02 10:57:46  abbott
924 // Summary: Revised design of IamIntegralDomain3
925 // Author: JAA
926 //
927 // Revision 1.12  2014/03/27 17:18:11  abbott
928 // Summary: Added new fn IsIntegralDomain3 (and mem fn IamIntegralDomain3)
929 // Author: JAA
930 //
931 // Revision 1.11  2014/03/27 16:41:57  bigatti
932 // -- added myMul
933 // -- fixed intersect
934 //
935 // Revision 1.10  2014/01/28 09:45:32  abbott
936 // Now uses ConvertTo instead of IsInteger.
937 //
938 // Revision 1.9  2013/06/28 17:03:51  abbott
939 // Modified semantics of IdealBase::myDivMod;
940 // it now returns a boolean.
941 // Several consequential changes.
942 //
943 // Revision 1.8  2013/06/17 08:55:45  abbott
944 // Improved RingZZImpl::IdealImpl::myDivMod (but there's a design issue!!)
945 //
946 // Revision 1.7  2013/02/21 14:14:41  abbott
947 // First attempt at implementing PartialRingHom -- some problems remain!!
948 //
949 // Revision 1.6  2012/05/30 16:04:55  bigatti
950 // -- applied "3" convention on bool3 functions and member fields
951 //
952 // Revision 1.5  2012/05/29 07:45:23  abbott
953 // Implemented simplification change to bool3:
954 //  changed names of the constants,
955 //  changed names of the testing fns.
956 //
957 // Revision 1.4  2012/05/28 09:18:20  abbott
958 // Created IntOperations which gathers together all operations on
959 // integers (both big and small).  Many consequential changes.
960 //
961 // Revision 1.3  2012/05/22 10:02:37  abbott
962 // Removed IsGCDDomain; substituted by IsTrueGCDDomain.
963 // Added IsFractionFieldOfGCDDomain.
964 //
965 // Revision 1.2  2012/04/27 15:03:16  abbott
966 // Added mem fn IamFiniteField;  corrected several Z into ZZ.
967 //
968 // Revision 1.1  2012/02/10 12:15:53  bigatti
969 // -- was RingZ.C
970 //
971 // Revision 1.28  2012/02/10 10:30:03  bigatti
972 // -- changed RingZ.H, RingQ.H --> RingZZ.H, RingQQ.H
973 //
974 // Revision 1.27  2012/02/08 13:43:50  bigatti
975 // -- changed Z --> ZZ
976 //
977 // Revision 1.26  2012/01/26 17:13:34  abbott
978 // Cleaned up impl of  RingZImpl::IdealImpl::myAdd
979 //
980 // Revision 1.25  2012/01/26 15:02:33  abbott
981 // Replaced call to copy(..., back_inserter...) by a call to range insert
982 // [see Scott Meyers "Effective STL" section 5, page 26]
983 //
984 // Revision 1.24  2011/11/09 14:29:37  bigatti
985 // -- renamed MachineInteger --> MachineInt
986 //
987 // Revision 1.23  2011/09/06 15:28:58  abbott
988 // Changed impl of  "myCmp" so that its return value is in {-1,0,+1}
989 //
990 // Revision 1.22  2011/08/24 10:29:55  bigatti
991 // -- renamed QQ --> BigRat
992 // -- sorted #include
993 //
994 // Revision 1.21  2011/08/14 15:52:16  abbott
995 // Changed ZZ into BigInt (phase 1: just the library sources).
996 //
997 // Revision 1.20  2011/06/23 16:04:46  abbott
998 // Added IamExact mem fn for rings.
999 // Added myRecvTwinFloat mem fn for rings.
1000 // Added first imple of RingHom from RingTwinFloat to other rings.
1001 //
1002 // Revision 1.19  2011/05/24 14:54:29  abbott
1003 // Consquential changes from removing several ctors for principal ideals.
1004 //
1005 // Revision 1.18  2011/05/19 14:46:47  abbott
1006 // Added defn of myIsDouble.
1007 //
1008 // Revision 1.17  2011/03/10 16:39:33  abbott
1009 // Replaced (very many) size_t by long in function interfaces (for rings,
1010 // PPMonoids and modules).  Also replaced most size_t inside fn defns.
1011 //
1012 // Revision 1.16  2010/10/27 20:58:45  abbott
1013 // Major reorganization of GlobalManager and GMPAllocator.
1014 //
1015 // Revision 1.15  2010/10/06 14:10:24  abbott
1016 // Added increments to the ref count in ring and PPMonoid ctors to make
1017 // them exception safe.
1018 //
1019 // Revision 1.14  2010/10/01 15:45:17  bigatti
1020 // -- added mySymbolValue
1021 //
1022 // Revision 1.13  2010/09/30 14:35:34  abbott
1023 // Added new pseudo-ctor for ZEmbeddingHom which requires the domain as first arg:
1024 // this form is essential for the ctor for RingQImpl!
1025 //
1026 // Added (hidden) new fn which checks whether RingZ has ref count greater than 3:
1027 // this fn tells us whether any object other than the GlobalManager and RingQ
1028 // refers to RingZ.  The fn is called only from the dtor of GlobalManager when
1029 // checking that no CoCoALib values still survive.
1030 //
1031 // Revision 1.12  2010/06/10 08:00:02  bigatti
1032 // -- fixed naming conventions
1033 //
1034 // Revision 1.11  2010/02/04 09:57:11  bigatti
1035 // -- added "mul" for ideals.  Implemented only for SparsePolyRing
1036 //
1037 // Revision 1.10  2009/10/29 18:41:42  abbott
1038 // Made a change to  RingZImpl::IdealImpl::myDivMod  but I don't recall why now
1039 // (the new version does avoid some wasteful copying).
1040 //
1041 // Revision 1.9  2009/10/26 15:42:55  bigatti
1042 // -- added CopyFromMPZ in ZZ ctor
1043 //
1044 // Revision 1.8  2009/07/02 16:32:11  abbott
1045 // Consequential changes stemming from new class QQ, and modified interface to the member
1046 // function RingBase::myIsRational.  Also some new conversion functions.
1047 //
1048 // Revision 1.7  2009/06/05 12:14:55  abbott
1049 // Major change:
1050 //   created new files NumTheory.H/C  which contain basic number theory operations
1051 //   removed several basic number theory operations from ZZ.H/C
1052 //   removed gcd from MachineInt.H/C
1053 //   changed names of some basic fns:
1054 //      IsPPrime -> IsProbPrime
1055 //      invmod -> InvMod    (changed signature too)
1056 //      powermod -> PowerMod  (changed signature too)
1057 //   added new fns
1058 //      NextProbPrime & PrevProbPrime
1059 //   consequent changes to other code and tests and examples
1060 //
1061 // Revision 1.6  2008/12/17 12:11:52  abbott
1062 // Changed type from long to MachineInt in operations which use a machine integer
1063 // in place of a RingElem.  The change is "superficial" but affects many files.
1064 //
1065 // Revision 1.5  2008/11/20 10:49:17  abbott
1066 // Added definition of myFloor member fn.
1067 //
1068 // Revision 1.4  2007/10/30 17:14:07  abbott
1069 // Changed licence from GPL-2 only to GPL-3 or later.
1070 // New version for such an important change.
1071 //
1072 // Revision 1.3  2007/05/22 22:45:14  abbott
1073 // Changed fn name IsUnit to IsInvertible.
1074 //
1075 // Revision 1.2  2007/03/28 10:06:13  abbott
1076 // Now gives error when you use RingZ() or RingQ() without creating GlobalManager.
1077 //
1078 // Revision 1.1.1.1  2007/03/09 15:16:11  abbott
1079 // Imported files
1080 //
1081 // Revision 1.12  2007/03/07 14:08:11  bigatti
1082 // -- minor: commented argument names for -Wextra
1083 //
1084 // Revision 1.11  2007/03/05 21:25:57  cocoa
1085 // Forgot to check these in a few minutes ago.
1086 //
1087 // Revision 1.10  2007/03/02 10:47:53  cocoa
1088 // First stage of RingZ modifications -- tests do not compile currently, Anna will fix this.
1089 //
1090 // Revision 1.9  2007/01/17 12:32:39  cocoa
1091 // Changed a few more "raw" variable names so that the code compiles fine
1092 // also when CoCoA_DEBUG is set.
1093 //
1094 // Revision 1.8  2007/01/15 16:04:48  cocoa
1095 // -- added prefix "raw" to RawPtr arguments names
1096 // -- changed rhs into rawx, n, or N
1097 //
1098 // Revision 1.7  2007/01/13 14:14:34  cocoa
1099 // Overhaul of RingHom code: it nows uses SmartPtrIRC, and printing is more logical.
1100 // Have not yet updated the documentation.
1101 //
1102 // Revision 1.6  2006/11/08 16:21:59  cocoa
1103 // Structural cleaning of RingHom; many consequential changes.
1104 //
1105 // Revision 1.5  2006/11/03 14:01:46  cocoa
1106 // -- changed: reference counting in ring, PPMonoids and OrdvArith now
1107 //    uses SmartPtrIRC
1108 //
1109 // Revision 1.4  2006/11/02 13:25:43  cocoa
1110 // Simplification of header files: the OpenMath classes have been renamed.
1111 // Many minor consequential changes.
1112 //
1113 // Revision 1.3  2006/10/06 14:04:14  cocoa
1114 // Corrected position of #ifndef in header files.
1115 // Separated CoCoA_ASSERT into assert.H from config.H;
1116 // many minor consequential changes (have to #include assert.H).
1117 // A little tidying of #include directives (esp. in Max's code).
1118 //
1119 // Revision 1.2  2006/10/06 10:15:52  cocoa
1120 // In response to Susan's bug: a fiasco when compiling with CoCoA_MEMPOOL_DEBUG
1121 // set wrongly.  Moved several implementation classes out of their header files
1122 // into the implementation files.  Several functions had to be uninlined.
1123 // Also corrected position of #include, etc.
1124 //
1125 // Revision 1.1.1.1  2006/05/30 11:39:37  cocoa
1126 // Imported files
1127 //
1128 // Revision 1.8  2006/05/29 16:22:37  cocoa
1129 // Third time lucky???
1130 // Added myIsInteger member function to all rings (NYI for RingFloat).
1131 //
1132 // Revision 1.7  2006/05/12 16:10:58  cocoa
1133 // Added OpenMathFwd.H, and tidied OpenMath.H.
1134 // Many consequential but trivial changes.
1135 //
1136 // Revision 1.6  2006/04/27 13:45:30  cocoa
1137 // Changed name of NewIdentityRingHom to NewIdentityHom.
1138 // Changed name of member functions which print out their own object
1139 // into myOutputSelf (to distinguish from "transitive" myOutput fns).
1140 //
1141 // Revision 1.5  2006/03/21 09:43:13  cocoa
1142 // Changed names of some member fns of ideals (dealing with setting and testing
1143 // the flags for primeness and maximality).  Hope icc will complain less now.
1144 //
1145 // Revision 1.4  2006/03/15 18:09:31  cocoa
1146 // Changed names of member functions which print out their object
1147 // into myOutputSelf -- hope this will appease the Intel C++ compiler.
1148 //
1149 // Revision 1.3  2006/03/14 15:01:49  cocoa
1150 // Improved the implementation of ring member fns for computing powers.
1151 // Should keep Intel C++ compiler quieter too.
1152 //
1153 // Revision 1.2  2006/03/12 21:28:33  cocoa
1154 // Major check in after many changes
1155 //
1156 // Revision 1.1.1.1  2005/10/17 10:46:54  cocoa
1157 // Imported files
1158 //
1159 // Revision 1.4  2005/09/30 15:03:39  cocoa
1160 // Minor cleaning and tidying.
1161 // DistrMPolyInlPP: use of summands now rather cleaner.
1162 //
1163 // Revision 1.3  2005/09/22 18:04:17  cocoa
1164 // It compiles; the tests run OK.  The examples compile.
1165 // No documentation -- the mindless eurocrats have rendered
1166 // me mindless too.
1167 //
1168 // Revision 1.2  2005/06/22 14:42:16  cocoa
1169 // Renamed MemPool data member to myMemMgr
1170 // (seems more sensible than myMemory).
1171 //
1172 // Revision 1.1.1.1  2005/05/03 15:47:31  cocoa
1173 // Imported files
1174 //
1175 // Revision 1.4  2005/04/20 15:40:48  cocoa
1176 // Major change: modified the standard way errors are to be signalled
1177 // (now via a macro which records filename and line number).  Updated
1178 // documentation in error.txt accordingly.
1179 //
1180 // Improved the documentation in matrix.txt (still more work to be done).
1181 //
1182 // Revision 1.3  2005/04/19 14:06:03  cocoa
1183 // Added GPL and GFDL licence stuff.
1184 //
1185 // Revision 1.2  2005/02/11 14:15:20  cocoa
1186 // New style ring elements and references to ring elements;
1187 // I hope I have finally got it right!
1188 //
1189 // Revision 1.1.1.1  2005/01/27 15:12:13  cocoa
1190 // Imported files
1191 //
1192 // Revision 1.16  2004/11/18 18:33:41  cocoa
1193 // Now every ring know its own "one" element (as well as "zero").
1194 // Several consequential changes.
1195 //
1196 // Revision 1.15  2004/11/11 11:56:09  cocoa
1197 // (1) Tidied makefiles, and introduced common.mki
1198 // (2) Improved several tests, and cleaned them so that they
1199 //     handle sanely any otherwise unhandled exceptions.
1200 //
1201 // Revision 1.14  2004/11/09 15:53:01  cocoa
1202 // -- fixed IamPrime  (now check also for equality to ideal(0))
1203 //
1204 // Revision 1.13  2004/11/04 18:47:42  cocoa
1205 // (1) Ring member functions which previously expected mpz_t args
1206 //     now expect ZZ args.  Numerous minor consequential changes.
1207 // (2) Renamed function which gives access to the mpz_t value inside
1208 //     a ZZ object: previously was raw(...), now is mpzref(...).
1209 //     Plenty of calls had to be altered.
1210 //
1211 // Revision 1.12  2004/07/27 16:03:39  cocoa
1212 // Added IsCommutative test and IamCommutative member function
1213 // to all rings.  Tidied geobuckets a little.
1214 //
1215 // Revision 1.11  2004/05/24 15:52:13  cocoa
1216 // Major update:
1217 //   new error mechanism
1218 //   many fixes
1219 //   RingHoms almost work now
1220 //   RingFloat much improved
1221 //
1222 // Revision 1.10  2004/04/08 15:33:34  cocoa
1223 // Added function IsInteger, and the related RingBase::myIsInteger
1224 // virtual function, plus all necessary implementations.
1225 //
1226 // Revision 1.9  2004/03/20 17:46:10  cocoa
1227 // Check in prior to departure to RWCA
1228 //
1229 // Revision 1.8  2004/02/03 16:16:20  cocoa
1230 // Removed pointless IamGCDDomain functions from several concrete rings.
1231 // Added IamOrderedDomain functions where appropriate.
1232 // Tidied ctors for the small finite fields.
1233 //
1234 // Revision 1.7  2004/01/30 14:07:10  cocoa
1235 // Tidied RingRawValue union: now it contains just two fields,
1236 // and has no need of forward declarations of types used internally
1237 // by the concrete rings -- it uses explicitly a void* instead.
1238 //
1239 // I have tidied the "import" functions used by most concrete rings.
1240 //
1241 // I have moved the choice of representation type for RingFp and RingFpLog
1242 // into a typedef in config.H -- this is to recognise that different
1243 // choices may work best on different platforms.
1244 //
1245 // Revision 1.6  2004/01/28 15:49:06  cocoa
1246 // RingZ now explicitly uses mpz_t to represent its values
1247 // (previously it used ZZ objects, with unhappy ownership questions).
1248 //
1249 // Revision 1.5  2003/11/14 13:06:05  cocoa
1250 // -- New function "myIsPrintAtom" for printing polynomials and fractions
1251 //
1252 // Revision 1.4  2003/10/17 10:51:06  cocoa
1253 // Major cleaning, and new naming convention.
1254 //
1255 // Revision 1.3  2003/10/09 14:55:19  cocoa
1256 // - minor debugging after merge
1257 //
1258 // Revision 1.2  2003/10/09 12:16:38  cocoa
1259 // New coding convention for rings.
1260 //
1261 // Revision 1.14  2003/06/23 16:41:19  abbott
1262 // Prior to public release:
1263 //   changed class name to follow coding conventions
1264 //   updated characteristic following RingBase
1265 //   added IsIntegralDomain following RingBase
1266 //
1267 // Revision 1.13  2003/05/14 17:15:42  abbott
1268 // Several consequential changes stemming from revisions to ring.H;
1269 // most notably added support for homomorphisms and ideals.
1270 //
1271 // Revision 1.12  2002/11/15 11:26:06  abbott
1272 // Updated following the renaming in ring.H.
1273 // Commented out the exception unsafe IsZeroAddMul, and opted to
1274 // use the default definition supplied by AbstractRing.
1275 // Fixed a memory leak in IsDivisible, and made it exception safe.
1276 //
1277 // Revision 1.11  2002/07/05 15:21:45  abbott
1278 // Revised ctor and dtor since zero is now an auto_ptr.
1279 // Added definition of member function IsDivisible.
1280 // Member function div now calls mpz_divexact.
1281 //
1282 // Revision 1.10  2002/06/22 17:10:57  abbott
1283 // Changed name of "equal" member function to "IsEqual" (as per new ring.H).
1284 //
1285 // Revision 1.9  2002/06/03 13:36:10  abbott
1286 // Added function definitions required to satisfy the OrderedRing interface.
1287 //
1288 // Revision 1.8  2002/05/30 13:50:29  abbott
1289 // Added IsGCDDomain, IsField, and zero functions as required by the new ring.H.
1290 //
1291 // Revision 1.7  2002/03/21 15:13:42  bigatti
1292 // - added: IsZeroAddMul
1293 // - corrected: pool name
1294 //
1295 // Revision 1.6  2002/02/15 11:57:16  bigatti
1296 // - added: gcd
1297 // - corrected: equal
1298 //
1299 // Revision 1.5  2001/12/07 18:22:30  abbott
1300 // Changed names in accordance with the new coding conventions.
1301 //
1302 // Revision 1.4  2001/11/23 20:59:09  abbott
1303 // Added assignment from a long.
1304 //
1305 // Revision 1.3  2001/11/19 20:10:03  abbott
1306 // Added using commands for the identifiers required from the standard
1307 // library (required by g++ version 3.0.2, and more properly correct).
1308 //
1309 // Revision 1.2  2001/11/06 16:44:41  abbott
1310 // Two main changes:
1311 //   *  alignment with the use of a union for a ring::raw_elem
1312 //      (instead of the previous void*);
1313 //
1314 //   *  the elements of a ring_Z are now pointers to mpz_t
1315 //      (instead of pointer to objects of class ZZ)
1316 //
1317 // Revision 1.1  2001/10/31 20:37:15  abbott
1318 // Initial revision
1319 //
1320