1 //   Copyright (c)  2001-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 
19 #include "CoCoA/RingFp.H"
20 
21 #include "CoCoA/BigIntOps.H"
22 #include "CoCoA/BigRat.H"
23 #include "CoCoA/FieldIdeal.H"
24 #include "CoCoA/GlobalManager.H"
25 #include "CoCoA/MemPool.H"
26 #include "CoCoA/OpenMath.H"
27 #include "CoCoA/QuotientRing.H"
28 #include "CoCoA/RingHom.H"
29 #include "CoCoA/RingZZ.H"
30 #include "CoCoA/SmallFpImpl.H"
31 #include "CoCoA/assert.H"
32 #include "CoCoA/convert.H"
33 #include "CoCoA/error.H"
34 #include "CoCoA/ideal.H"
35 
36 #include <algorithm>
37 //using std::swap;         // only in mySwap
38 #include <iostream>
39 using std::ostream;        // only in myOutput
40 // #include <limits>  ---  included in MachineInt.H (included via BigRat.H)
41 using std::numeric_limits; // only in ctor
42 // #include <memory>  ---  included in MemPool.H
43 using std::unique_ptr;
44 // #include <vector>  ---  included in ideal.H
45 using std::vector;
46 
47 
48 namespace CoCoA
49 {
50 
51   class RingFpImpl: public QuotientRingBase
52   {
53   private: // data members
54     typedef SmallFpImpl::value value_t;
55     const long myModulus;
56     const SmallFpImpl myImpl;
57     mutable MemPool myMemMgr;       // MemPool must come *BEFORE* myZeroPtr and myOnePtr
58     unique_ptr<RingElem> myZeroPtr;  ///< Every ring stores its own zero.
59     unique_ptr<RingElem> myOnePtr;   ///< Every ring stores its own one.
60 
61   private: // auxiliary functions
62     static long PrincipalGen(const ideal& I); // used for arg checking in ctor
63     static value_t& import(RingElemRawPtr rawx);
64     static const value_t& import(RingElemConstRawPtr rawx);
65 
66   private: // ctor and pseudo-ctors
67     explicit RingFpImpl(const ideal& I, GlobalSettings::ResidueSetting ResidueChoice =  DefaultResidueSetting()); // called only by NewRingFp
68     ~RingFpImpl();
69     friend QuotientRing NewRingFp(const MachineInt& p, GlobalSettings::ResidueSetting ResidueChoice);
70     friend QuotientRing NewRingFp(const BigInt& P);
71     friend QuotientRing NewRingFp(const ideal& I);
72   private:
73     RingFpImpl(const RingFpImpl&);            ///< NEVER DEFINED -- disallow copy construction
74     RingFpImpl& operator=(const RingFpImpl&); ///< NEVER DEFINED -- disallow assignment
75   public:
76 
77     // functions required by every ring
78     virtual void myCharacteristic(BigInt& p) const;
79     virtual long myLogCardinality() const;
80     virtual bool IamCommutative() const;
81     virtual bool3 IamIntegralDomain3(bool) const;
82     virtual bool IamField() const;
83     virtual bool IamFiniteField() const;
84     virtual bool IamExact() const;
85     virtual ConstRefRingElem myZero() const;
86     virtual ConstRefRingElem myOne() const;
87     using RingBase::myNew;    // disable warnings of overloading
88     using RingBase::myAssign; // disable warnings of overloading
89     virtual RingElemRawPtr myNew() const;
90     virtual RingElemRawPtr myNew(const MachineInt& n) const;
91     virtual RingElemRawPtr myNew(const BigInt& N) const;
92     virtual RingElemRawPtr myNew(ConstRawPtr rawt) const;
93     virtual void myDelete(RawPtr rawx) const;                                      // destroys x (incl all resources)
94     virtual void mySwap(RawPtr rawx, RawPtr rawy) const;                           // swap(x, y)
95     virtual void myAssign(RawPtr rawlhs, ConstRawPtr rawx) const;                  // lhs = x
96     virtual void myAssign(RawPtr rawlhs, const MachineInt& n) const;               // lhs = n
97     virtual void myAssign(RawPtr rawlhs, const BigInt& N) const;                   // lhs = N
98     virtual void myAssignZero(RawPtr rawlhs) const;                                // lhs = 0
99     virtual void myRecvTwinFloat(RawPtr rawlhs, ConstRawPtr rawx) const;
100     virtual void myNegate(RawPtr rawlhs, ConstRawPtr rawx) const;                  // lhs = -x
101     virtual void myAdd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const;   // lhs = x+y
102     virtual void mySub(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const;   // lhs = x-y
103     virtual void myMul(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const;   // lhs = x*y
104     virtual void myDiv(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const;   // lhs = x/y
105     virtual bool myIsDivisible(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const;// lhs = x/y, if divisible
106     virtual bool myIsInvertible(ConstRawPtr rawx) const;                           // true iff x is invertible
107     virtual void myGcd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const;   // lhs = gcd(x,y) in a field
108     virtual void myPowerSmallExp(RawPtr rawlhs, ConstRawPtr rawx, long n) const;   // lhs = x^n, n>1, x not -1,0,1
109     virtual void myPowerBigExp(RawPtr rawlhs, ConstRawPtr rawx, const BigInt& N) const; // lhs = x^N, N big, x not -1,0,1
110     virtual void myOutput(std::ostream& out, ConstRawPtr rawx) const;              // out << x
111     virtual bool myIsPrintAtom(ConstRawPtr rawx) const;
112     virtual bool myIsPrintedWithMinus(ConstRawPtr rawx) const;
113     virtual void myOutputSelfShort(std::ostream& out) const;                            // out << R
114     virtual void myOutputSelf(std::ostream& out) const;                            // out << R
115     virtual void myOutputSelf(OpenMathOutput& OMOut) const;                        // OMOut << R
116     virtual void myOutput(OpenMathOutput& OMOut, ConstRawPtr rawx) const;          // OMOut << x
117     virtual bool myIsZero(ConstRawPtr rawx) const;                                 // x == 0
118     virtual bool myIsOne(ConstRawPtr rawx) const;                                  // x == 1
119     virtual bool myIsMinusOne(ConstRawPtr rawx) const;                             // x == -1
120     virtual bool myIsInteger(BigInt& N, ConstRawPtr rawx) const;                   // always true
121     virtual bool myIsRational(BigRat& Q, ConstRawPtr rawx) const;                  // true iff x is rational
122     virtual bool myIsDouble(double& d, ConstRawPtr rawx) const;                    // false iff x overflows
123     virtual bool myIsZeroAddMul(RawPtr rawlhs, ConstRawPtr rawy, ConstRawPtr rawz) const;// lhs += y*z, result says whether lhs == 0.
124     virtual bool myIsZeroAddMul(RawPtr rawlhs, RawPtr /*rawtmp*/, ConstRawPtr rawy, ConstRawPtr rawz) const;// lhs += y*z, result says whether lhs == 0.
125     virtual bool myIsEqual(ConstRawPtr rawx, ConstRawPtr rawy) const;              // x == y
126 
127     virtual ideal myIdealCtor(const std::vector<RingElem>& gens) const;
128 
129     virtual RingHom myCompose(const RingHom& phi, const RingHom& theta) const; // phi(theta(...))
130 
131     virtual bool myImageLiesInSubfield(const RingHom& phi) const;
132 
133     // functions required for a QuotientRing
134     virtual RingElem myCanonicalRepr(ConstRawPtr rawx) const; // result is element of myReprRing
135     virtual void myReduction(RawPtr rawimage, ConstRawPtr rawarg) const;
136     virtual RingHom myInducedHomCtor(const RingHom& InducingHom) const;
137 
138     // Special fns for RingFp only
139     const SmallFpImpl& myModularArith() const;
140   private:
141     class InducedHomImpl: public RingHomBase
142     {
143     public:
144       InducedHomImpl(const QuotientRing& domain, const RingHom& InducingHom);
145       virtual void myApply(RingElemRawPtr rawimage, RingElemConstRawPtr rawarg) const;
IamPartial()146       virtual bool IamPartial() const { return false; }
147     };
148 
149   };
150 
151 
152 
import(RingElemRawPtr rawx)153   inline RingFpImpl::value_t& RingFpImpl::import(RingElemRawPtr rawx)
154   {
155     return *static_cast<value_t*>(rawx.myRawPtr());
156   }
157 
import(RingElemConstRawPtr rawx)158   inline const RingFpImpl::value_t& RingFpImpl::import(RingElemConstRawPtr rawx)
159   {
160     return *static_cast<const value_t*>(rawx.myRawPtr());
161   }
162 
163 
164   // Returns generator of I as a long; returns 0 if value is too large to fit.
PrincipalGen(const ideal & I)165   long RingFpImpl::PrincipalGen(const ideal& I)
166   {
167     if (IsZero(I)) return 0;
168     const BigInt GenI = ConvertTo<BigInt>(TidyGens(I)[0]);
169     long p;
170     if (!IsConvertible(p, GenI))  // check that the value of the principal generator will fit
171       return 0; // 0 will trigger an error in ctor for SmallFpImpl
172     return p;
173   }
174 
175 
RingFpImpl(const ideal & I,GlobalSettings::ResidueSetting ResidueChoice)176   RingFpImpl::RingFpImpl(const ideal& I, GlobalSettings::ResidueSetting ResidueChoice):
177       QuotientRingBase(RingZZ(), I),  // confirms that I is an ideal of Z
178       myModulus(PrincipalGen(I)),
179       myImpl(myModulus, ResidueChoice),  // also checks that myModulus is a small prime
180       myMemMgr(SmallFpImpl::ourDatumSize, "RingFpImpl.myMemMgr")
181   {
182     myRefCountInc();  // this is needed for exception cleanliness, in case one of the lines below throws
183     myZeroPtr.reset(new RingElem(ring(this)));
184     myOnePtr.reset(new RingElem(ring(this), 1));
185     myRefCountZero();
186   }
187 
188 
~RingFpImpl()189   RingFpImpl::~RingFpImpl()
190   {}
191 
192 
myCharacteristic(BigInt & p)193   void RingFpImpl::myCharacteristic(BigInt& p) const
194   {
195     p = myModulus;
196   }
197 
198 
myLogCardinality()199   long RingFpImpl::myLogCardinality() const
200   {
201     return 1;
202   }
203 
204 
IamCommutative()205   bool RingFpImpl::IamCommutative() const
206   {
207     return true;
208   }
209 
210 
IamIntegralDomain3(bool)211   bool3 RingFpImpl::IamIntegralDomain3(bool) const
212   {
213     return true3;
214   }
215 
216 
IamField()217   bool RingFpImpl::IamField() const
218   {
219     return true;
220   }
221 
222 
IamFiniteField()223   bool RingFpImpl::IamFiniteField() const
224   {
225     return true;
226   }
227 
228 
IamExact()229   bool RingFpImpl::IamExact() const
230   {
231     return true;
232   }
233 
234 
myZero()235   ConstRefRingElem RingFpImpl::myZero() const
236   {
237     return *myZeroPtr;
238   }
239 
240 
myOne()241   ConstRefRingElem RingFpImpl::myOne() const
242   {
243     return *myOnePtr;
244   }
245 
246 
myNew()247   RingElemRawPtr RingFpImpl::myNew() const
248   {
249     value_t* ans = static_cast<value_t*>(myMemMgr.alloc());
250     new(ans) value_t(); // init to 0
251     return RingElemRawPtr(ans);
252   }
253 
254 
myNew(const MachineInt & n)255   RingElemRawPtr RingFpImpl::myNew(const MachineInt& n) const
256   {
257     value_t* ans = static_cast<value_t*>(myMemMgr.alloc());
258     new(ans) value_t();
259     *ans = myImpl.myReduce(n);
260     return RingElemRawPtr(ans);
261   }
262 
263 
myNew(const BigInt & N)264   RingElemRawPtr RingFpImpl::myNew(const BigInt& N) const
265   {
266     value_t* ans = static_cast<value_t*>(myMemMgr.alloc());
267     new(ans) value_t();
268     *ans = myImpl.myReduce(N);
269     return RingElemRawPtr(ans);
270   }
271 
272 
myNew(ConstRawPtr rawy)273   RingElemRawPtr RingFpImpl::myNew(ConstRawPtr rawy) const
274   {
275     value_t* ans = static_cast<value_t*>(myMemMgr.alloc());
276     new(ans) value_t(import(rawy));
277     return RingElemRawPtr(ans);
278   }
279 
280 
myDelete(RawPtr rawx)281   void RingFpImpl::myDelete(RawPtr rawx) const
282   {
283     import(rawx).~value(); // dtor actually does nothing (currently)
284     myMemMgr.free(rawx.myRawPtr());
285   }
286 
287 
mySwap(RawPtr rawx,RawPtr rawy)288   void RingFpImpl::mySwap(RawPtr rawx, RawPtr rawy) const
289   {
290     std::swap(import(rawx), import(rawy));
291   }
292 
293 
myAssign(RawPtr rawlhs,ConstRawPtr rawx)294   void RingFpImpl::myAssign(RawPtr rawlhs, ConstRawPtr rawx) const
295   {
296     import(rawlhs) = import(rawx);
297   }
298 
299 
myAssign(RawPtr rawlhs,const MachineInt & n)300   void RingFpImpl::myAssign(RawPtr rawlhs, const MachineInt& n) const
301   {
302     import(rawlhs) = myImpl.myReduce(n);
303   }
304 
305 
myAssign(RawPtr rawlhs,const BigInt & N)306   void RingFpImpl::myAssign(RawPtr rawlhs, const BigInt& N) const
307   {
308     import(rawlhs) = myImpl.myReduce(N);
309   }
310 
311 
myAssignZero(RawPtr rawlhs)312   void RingFpImpl::myAssignZero(RawPtr rawlhs) const
313   {
314     import(rawlhs) = zero(SmallFp);
315   }
316 
317 
myRecvTwinFloat(RawPtr,ConstRawPtr)318   void RingFpImpl::myRecvTwinFloat(RawPtr /*rawlhs*/, ConstRawPtr /*rawx*/) const
319   {
320     CoCoA_ERROR(ERR::ShouldNeverGetHere, "RingFpImpl::myRecvTwinFloat");
321   }
322 
323 
myNegate(RawPtr rawlhs,ConstRawPtr rawx)324   void RingFpImpl::myNegate(RawPtr rawlhs, ConstRawPtr rawx) const
325   {
326     import(rawlhs) = myImpl.myNegate(import(rawx));
327   }
328 
329 
myAdd(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)330   void RingFpImpl::myAdd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
331   {
332     import(rawlhs) = myImpl.myAdd(import(rawx), import(rawy));
333   }
334 
335 
mySub(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)336   void RingFpImpl::mySub(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
337   {
338     import(rawlhs) = myImpl.mySub(import(rawx), import(rawy));
339   }
340 
341 
myMul(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)342   void RingFpImpl::myMul(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
343   {
344     import(rawlhs) = myImpl.myMul(import(rawx), import(rawy));
345   }
346 
347 
myDiv(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)348   void RingFpImpl::myDiv(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
349   {
350     CoCoA_ASSERT(!myIsZero(rawy));
351     import(rawlhs) = myImpl.myDiv(import(rawx), import(rawy));
352   }
353 
354 
myIsDivisible(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)355   bool RingFpImpl::myIsDivisible(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
356   {
357     if (IsZero(import(rawy))) return false;
358     import(rawlhs) = myImpl.myDiv(import(rawx), import(rawy));
359     return true;
360   }
361 
362 
myIsInvertible(ConstRawPtr rawx)363   bool RingFpImpl::myIsInvertible(ConstRawPtr rawx) const
364   {
365     return !myIsZero(rawx);
366   }
367 
368 
myGcd(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)369   void RingFpImpl::myGcd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const
370   {
371     myGcdInField(rawlhs, rawx, rawy);
372   }
373 
374 
myPowerSmallExp(RawPtr rawlhs,ConstRawPtr rawx,long n)375   void RingFpImpl::myPowerSmallExp(RawPtr rawlhs, ConstRawPtr rawx, long n) const  // assumes n > 1
376   {
377     // Assert that we have a genuinely non-trivial case.
378     CoCoA_ASSERT(n > 1);
379     CoCoA_ASSERT(!myIsZero(rawx) && !myIsOne(rawx) && !myIsMinusOne(rawx));
380     import(rawlhs) = myImpl.myPower(import(rawx), n);
381   }
382 
myPowerBigExp(RawPtr rawlhs,ConstRawPtr rawx,const BigInt & N)383   void RingFpImpl::myPowerBigExp(RawPtr rawlhs, ConstRawPtr rawx, const BigInt& N) const
384   {
385     // Assert that we have a genuinely non-trivial case.
386     CoCoA_ASSERT(N > 1);
387     CoCoA_ASSERT(!myIsZero(rawx) && !myIsOne(rawx) && !myIsMinusOne(rawx));
388     // Use Fermat's Little Theorem to reduce exponent...
389     import(rawlhs) = myImpl.myPower(import(rawx), N%(myModulus-1));
390   }
391 
392 
myOutput(ostream & out,ConstRawPtr rawx)393   void RingFpImpl::myOutput(ostream& out, ConstRawPtr rawx) const
394   {
395     if (!out) return;  // short-cut for bad ostreams
396     out << myImpl.myExport(import(rawx));
397   }
398 
399 
myIsPrintAtom(ConstRawPtr rawx)400   bool RingFpImpl::myIsPrintAtom(ConstRawPtr rawx) const
401   {
402     return myImpl.myExport(import(rawx)) >= 0;
403   }
404 
405 
myIsPrintedWithMinus(ConstRawPtr rawx)406   bool RingFpImpl::myIsPrintedWithMinus(ConstRawPtr rawx) const
407   {
408     return myImpl.myExport(import(rawx)) < 0;
409   }
410 
411 
myOutputSelfShort(ostream & out)412   void RingFpImpl::myOutputSelfShort(ostream& out) const
413   {
414     if (!out) return;  // short-cut for bad ostreams
415     out << "ZZ/(" << myModulus << ")";
416   }
417 
myOutputSelf(ostream & out)418   void RingFpImpl::myOutputSelf(ostream& out) const
419   {
420     if (!out) return;  // short-cut for bad ostreams
421     out << "RingWithID(" << myID << ", \"ZZ/(" << myModulus << ")\")";
422   }
423 
424 
myOutputSelf(OpenMathOutput & OMOut)425   void RingFpImpl::myOutputSelf(OpenMathOutput& OMOut) const
426   {
427     OMOut->mySendApplyStart();
428     OMOut << OpenMathSymbol("setname2", "GFp");
429     OMOut << myModulus;
430     OMOut->mySendApplyEnd();
431   }
432 
433 
myOutput(OpenMathOutput & OMOut,ConstRawPtr rawx)434   void RingFpImpl::myOutput(OpenMathOutput& OMOut, ConstRawPtr rawx) const
435   {
436     OMOut << myImpl.myExport(import(rawx));
437   }
438 
439 
myIsZero(ConstRawPtr rawx)440   bool RingFpImpl::myIsZero(ConstRawPtr rawx) const
441   {
442     return IsZero(import(rawx));
443   }
444 
445 
myIsOne(ConstRawPtr rawx)446   bool RingFpImpl::myIsOne(ConstRawPtr rawx) const
447   {
448     return IsOne(import(rawx));
449   }
450 
451 
myIsMinusOne(ConstRawPtr rawx)452   bool RingFpImpl::myIsMinusOne(ConstRawPtr rawx) const
453   {
454     return import(rawx) == myImpl.myReduce(-1);
455   }
456 
457 
myIsInteger(BigInt & N,ConstRawPtr rawx)458   bool RingFpImpl::myIsInteger(BigInt& N, ConstRawPtr rawx) const
459   {
460     N = myImpl.myExport(import(rawx));
461     return true;
462   }
463 
464 
myIsRational(BigRat & Q,ConstRawPtr rawx)465   bool RingFpImpl::myIsRational(BigRat& Q, ConstRawPtr rawx) const
466   {
467     Q = myImpl.myExport(import(rawx));
468     return true;
469   }
470 
471 
myIsDouble(double & d,ConstRawPtr rawx)472   bool RingFpImpl::myIsDouble(double& d, ConstRawPtr rawx) const
473   {
474     d = myImpl.myExport(import(rawx));
475     return true;
476   }
477 
478 
myIsZeroAddMul(RawPtr rawlhs,ConstRawPtr rawfact1,ConstRawPtr rawfact2)479   bool RingFpImpl::myIsZeroAddMul(RawPtr rawlhs, ConstRawPtr rawfact1, ConstRawPtr rawfact2) const
480   {
481     return myImpl.myIsZeroAddMul(import(rawlhs), import(rawfact1), import(rawfact2));
482   }
483 
484 
myIsZeroAddMul(RawPtr rawlhs,RawPtr,ConstRawPtr rawfact1,ConstRawPtr rawfact2)485   bool RingFpImpl::myIsZeroAddMul(RawPtr rawlhs, RawPtr /*rawtmp*/, ConstRawPtr rawfact1, ConstRawPtr rawfact2) const
486   { // same as above: just to avoid calling RingBase::myIsZeroAddMul with 4 args
487     return myImpl.myIsZeroAddMul(import(rawlhs), import(rawfact1), import(rawfact2));
488   }
489 
490 
myIsEqual(ConstRawPtr rawx,ConstRawPtr rawy)491   bool RingFpImpl::myIsEqual(ConstRawPtr rawx, ConstRawPtr rawy) const
492   {
493     return import(rawx) == import(rawy);
494   }
495 
496 
497 
498 
myIdealCtor(const std::vector<RingElem> & gens)499   ideal RingFpImpl::myIdealCtor(const std::vector<RingElem>& gens) const
500   {
501     return NewFieldIdeal(ring(this), gens);
502   }
503 
504 
myCompose(const RingHom & phi,const RingHom & theta)505   RingHom RingFpImpl::myCompose(const RingHom& phi, const RingHom& theta) const
506   {
507     // No need to check compatibility -- it was checked when theta and phi were built
508     return RingHom(new InducedHomImpl(QuotientRing(this), phi(theta(myQuotientingHomCtor()))));
509   }
510 
511 
myImageLiesInSubfield(const RingHom & phi)512   bool RingFpImpl::myImageLiesInSubfield(const RingHom& phi) const
513   {
514     (void)(phi); // to avoid compiler warning about unused parameter
515     CoCoA_ASSERT(codomain(phi) == ring(this));
516     return true;
517   }
518 
519 
520 
myCanonicalRepr(ConstRawPtr rawx)521   RingElem RingFpImpl::myCanonicalRepr(ConstRawPtr rawx) const
522   {
523     return RingElem(myReprRing, myImpl.myExport(import(rawx)));
524   }
525 
526 
myReduction(RawPtr rawimage,ConstRawPtr rawarg)527   void RingFpImpl::myReduction(RawPtr rawimage, ConstRawPtr rawarg) const
528   {
529     BigInt tmp;
530     CoCoA_ASSERT(myReprRing->myIsInteger(tmp, rawarg));
531     myReprRing->myIsInteger(tmp, rawarg);
532     import(rawimage) = myImpl.myReduce(tmp);
533   }
534 
535 
myInducedHomCtor(const RingHom & InducingHom)536   RingHom RingFpImpl::myInducedHomCtor(const RingHom& InducingHom) const
537   {
538     // Compatibility has already been checked (see InducedHom in QuotientRing.C)
539     CoCoA_ASSERT(IsZero(InducingHom(myModulus)));
540     return RingHom(new InducedHomImpl(QuotientRing(this), InducingHom));
541   }
542 
543 
myModularArith()544   const SmallFpImpl& RingFpImpl::myModularArith() const
545   {
546     return myImpl;
547   }
548 
549 
550   //---------------------------------------------------------------------------
551   // Functions to do with ring homomorphisms
552 
553 
InducedHomImpl(const QuotientRing & domain,const RingHom & InducingHom)554   RingFpImpl::InducedHomImpl::InducedHomImpl(const QuotientRing& domain, const RingHom& InducingHom):
555       RingHomBase(domain, codomain(InducingHom))
556   { /* Compatibility already checked in InducedHom in QuotientRing.C */  }
557 
558 
myApply(RingElemRawPtr rawimage,RingElemConstRawPtr rawarg)559   void RingFpImpl::InducedHomImpl::myApply(RingElemRawPtr rawimage, RingElemConstRawPtr rawarg) const
560   {
561     BigInt tmp;  //??? wasteful new/delete
562     CoCoA_ASSERT(myDomain->myIsInteger(tmp, rawarg));
563     myDomain->myIsInteger(tmp, rawarg);  // must necessarily succeed
564     myCodomain->myAssign(rawimage, tmp);
565   }
566 
567 
568 
NewRingFp(const MachineInt & p,GlobalSettings::ResidueSetting ResidueChoice)569   QuotientRing NewRingFp(const MachineInt& p, GlobalSettings::ResidueSetting ResidueChoice)
570   {
571     return QuotientRing(new RingFpImpl(ideal(RingElem(RingZZ(), p)), ResidueChoice));
572   }
573 
NewRingFp(const BigInt & P)574   QuotientRing NewRingFp(const BigInt& P)
575   {
576     return QuotientRing(new RingFpImpl(ideal(RingElem(RingZZ(), P))));
577   }
578 
NewRingFp(const ideal & I)579   QuotientRing NewRingFp(const ideal& I)
580   {
581     if (!IsZZ(RingOf(I))) CoCoA_ERROR(ERR::IdealNotInRing, "NewRingFp(I)");
582     return QuotientRing(new RingFpImpl(I));
583   }
584 
585 
IsGoodForRingFp(const MachineInt & p)586   bool IsGoodForRingFp(const MachineInt& p)
587   {
588     if (IsNegative(p) || !IsSignedLong(p)) return false;
589     const long n = AsSignedLong(p);
590     return SmallFpImpl::IsGoodCtorArg(n);
591   }
592 
IsGoodForRingFp(const BigInt & P)593   bool IsGoodForRingFp(const BigInt& P)
594   {
595     if (P <= 0) return false;
596     long p;
597     if (!IsConvertible(p, P)) return false;
598     return IsGoodForRingFp(p);
599   }
600 
IsGoodForRingFp(const ideal & I)601   bool IsGoodForRingFp(const ideal& I)
602   {
603     if (!IsZZ(RingOf(I))) return false;
604     if (IsZero(I)) return false;
605     return IsGoodForRingFp(ConvertTo<BigInt>(TidyGens(I)[0]));
606   }
607 
608 
IsRingFp(const ring & R)609   bool IsRingFp(const ring& R)
610   {
611     return dynamic_cast<const RingFpImpl*>(R.myRawPtr()) != nullptr;
612   }
613 
ModularArith(const ring & R)614   const SmallFpImpl& ModularArith(const ring& R)
615   {
616     return dynamic_cast<const RingFpImpl*>(R.myRawPtr())->myModularArith();
617   }
618 
619 } // end of namespace CoCoA
620 
621 
622 // RCS header/log
623 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/RingFp.C,v 1.52 2020/02/11 16:56:41 abbott Exp $
624 // $Log: RingFp.C,v $
625 // Revision 1.52  2020/02/11 16:56:41  abbott
626 // Summary: Corrected last update (see redmine 969)
627 //
628 // Revision 1.51  2020/02/11 16:12:19  abbott
629 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969
630 //
631 // Revision 1.50  2019/09/25 13:33:34  abbott
632 // Summary: Changed "compact" printed form of finite fields from FFp(...)  to ZZ/(...)
633 //
634 // Revision 1.49  2019/09/23 08:12:27  abbott
635 // Summary: Added myOutputSelfShort
636 //
637 // Revision 1.48  2019/03/19 11:07:07  abbott
638 // Summary: Replaced 0 by nullptr where appropriate
639 //
640 // Revision 1.47  2019/03/04 10:40:41  abbott
641 // Summary: Changed auto_ptr into unique_ptr
642 //
643 // Revision 1.46  2018/05/18 12:15:56  bigatti
644 // -- renamed IntOperations --> BigIntOps
645 //
646 // Revision 1.45  2018/02/15 14:43:53  abbott
647 // Summary: update
648 //
649 // Revision 1.44  2017/09/06 11:56:29  abbott
650 // Summary: Changed ERR::SERIOUS into ERR::ShouldNeverGetHere
651 //
652 // Revision 1.43  2015/11/04 12:11:55  abbott
653 // Summary: Many consequential changes (after revision to SmallFpImpl)
654 //
655 // Revision 1.42  2015/07/29 11:04:55  bigatti
656 // -- added space after comma in printing rings
657 //
658 // Revision 1.41  2014/07/30 14:08:49  abbott
659 // Summary: Changed name AmbientRing --> RingOf
660 // Author: JAA
661 //
662 // Revision 1.40  2014/07/28 16:04:43  abbott
663 // Summary: Renamed myQuotientingHom to myQuotientingHomCtor
664 // Author: JAA
665 //
666 // Revision 1.39  2014/07/28 15:48:59  abbott
667 // Summary: Redesign: ringhoms no longer cached in rings (caused ref count trouble)
668 // Author: JAA
669 //
670 // Revision 1.38  2014/07/04 13:08:08  bigatti
671 // -- RingID into RingWithID
672 //
673 // Revision 1.37  2014/07/02 16:33:13  bigatti
674 // -- new way of printing rings with ID
675 //
676 // Revision 1.36  2014/06/17 10:12:53  abbott
677 // Summary: Added (void)(phi) to avoid compiler warning about unused param
678 // Author: JAA
679 //
680 // Revision 1.35  2014/05/14 15:57:15  bigatti
681 // -- added "using" for clang with superpedantic flag
682 //
683 // Revision 1.34  2014/04/02 10:57:46  abbott
684 // Summary: Revised design of IamIntegralDomain3
685 // Author: JAA
686 //
687 // Revision 1.33  2014/03/27 17:17:31  abbott
688 // Summary: Added new fn IsIntegralDomain3 (and mem fn IamIntegralDomain3)
689 // Author: JAA
690 //
691 // Revision 1.32  2014/01/28 10:02:48  abbott
692 // Replaced some calls to IsInteger by calls to ConvertTo<BigInt>.
693 //
694 // Revision 1.31  2013/03/25 17:04:19  abbott
695 // Major clean-up of interface to SmallFpImpl/SmallFpLogImpl/SmallFpDoubleImpl
696 // (underlying impl remains much the same).  Removed lots of cruft.
697 // Consequential changes to RingFp* classes; small change to SparsePolyRing.
698 //
699 // Revision 1.30  2012/09/07 15:21:13  abbott
700 // First stage of revision of SmallFpImpl interface (and SmallFpLog, SmallFpDouble).
701 //
702 // Revision 1.29  2012/05/28 09:18:21  abbott
703 // Created IntOperations which gathers together all operations on
704 // integers (both big and small).  Many consequential changes.
705 //
706 // Revision 1.28  2012/04/27 15:04:10  abbott
707 // Added mem fns IamFiniteField & myLogCardinality.
708 //
709 // Revision 1.27  2012/02/10 10:28:08  bigatti
710 // -- changed RingZ.H, RingQ.H --> RingZZ.H, RingQQ.H
711 //
712 // Revision 1.26  2012/02/08 13:48:13  bigatti
713 // -- changed Z,Q --> ZZ,QQ
714 //
715 // Revision 1.25  2012/01/30 12:58:36  abbott
716 // Realigned some comments.
717 //
718 // Revision 1.24  2012/01/25 13:32:38  bigatti
719 // -- added myIsZeroAddMul with 4 args
720 // -- some tidying
721 //
722 // Revision 1.23  2011/11/09 14:10:49  bigatti
723 // -- renamed MachineInteger --> MachineInt
724 //
725 // Revision 1.22  2011/08/24 10:28:49  bigatti
726 // -- renamed QQ --> BigRat
727 // -- sorted #include
728 //
729 // Revision 1.21  2011/08/14 15:52:16  abbott
730 // Changed ZZ into BigInt (phase 1: just the library sources).
731 //
732 // Revision 1.20  2011/06/23 16:04:47  abbott
733 // Added IamExact mem fn for rings.
734 // Added myRecvTwinFloat mem fn for rings.
735 // Added first imple of RingHom from RingTwinFloat to other rings.
736 //
737 // Revision 1.19  2011/05/24 14:54:29  abbott
738 // Consquential changes from removing several ctors for principal ideals.
739 //
740 // Revision 1.18  2011/05/20 19:26:05  abbott
741 // Updated SmallFp*Impl: removed all output-related fns (must use myExport instead).
742 //
743 // Revision 1.17  2011/05/20 09:45:04  abbott
744 // Harmonized RingFp, RingFpLog, RingFpDouble -- they are now almost ready to be merged into a single class!
745 //
746 // Revision 1.16  2011/05/19 14:38:27  abbott
747 // Updated small prime finite field impls to allow user to specify
748 // separately for each whether to use symmetric or non-negative
749 // residues for export operations (myExport and printing).
750 //
751 // Revision 1.15  2011/03/22 20:00:37  abbott
752 // Added IsGoodForXXX fns to test whether a given arg is suitable as
753 // characteristic for the given type of small prime finite field.
754 //
755 // Revision 1.14  2011/03/11 21:50:21  abbott
756 // Removed 1 line of commented out old code.
757 //
758 // Revision 1.13  2011/03/10 16:39:34  abbott
759 // Replaced (very many) size_t by long in function interfaces (for rings,
760 // PPMonoids and modules).  Also replaced most size_t inside fn defns.
761 //
762 // Revision 1.12  2010/10/06 14:10:24  abbott
763 // Added increments to the ref count in ring and PPMonoid ctors to make
764 // them exception safe.
765 //
766 // Revision 1.11  2009/12/11 11:46:32  abbott
767 // Changed fn  convert  into  IsConvertible.
768 // Added template procedure  convert.
769 // New version because change is not backward compatible.
770 //
771 // Revision 1.10  2009/09/25 14:01:11  abbott
772 // Cleaned up include directives.
773 //
774 // Revision 1.9  2009/09/24 16:22:13  abbott
775 // Tidied up include directives.  Removed some unnecessary "std::" prefixes.
776 //
777 // Revision 1.8  2009/07/02 16:32:11  abbott
778 // Consequential changes stemming from new class QQ, and modified interface to the member
779 // function RingBase::myIsRational.  Also some new conversion functions.
780 //
781 // Revision 1.7  2009/06/05 12:08:28  abbott
782 // Changed return type of operator%(ZZ,MachineInt); it is now unsigned long
783 // instead of ZZ.
784 //
785 // Revision 1.6  2008/12/17 12:11:52  abbott
786 // Changed type from long to MachineInt in operations which use a machine integer
787 // in place of a RingElem.  The change is "superficial" but affects many files.
788 //
789 // Revision 1.5  2007/10/30 17:14:07  abbott
790 // Changed licence from GPL-2 only to GPL-3 or later.
791 // New version for such an important change.
792 //
793 // Revision 1.4  2007/05/22 22:45:14  abbott
794 // Changed fn name IsUnit to IsInvertible.
795 //
796 // Revision 1.3  2007/05/21 12:44:25  abbott
797 // Changed impl of powering routine as a consequence of changed signature
798 // to the modulus operator for ZZ modulo machine integer.
799 //
800 // Revision 1.2  2007/03/23 18:38:42  abbott
801 // Separated the "convert" functions (and CheckedCast) into their own files.
802 // Many consequential changes.  Also corrected conversion to doubles.
803 //
804 // Revision 1.1.1.1  2007/03/09 15:16:11  abbott
805 // Imported files
806 //
807 // Revision 1.16  2007/03/08 18:22:29  cocoa
808 // Just whitespace cleaning.
809 //
810 // Revision 1.15  2007/03/08 10:23:29  bigatti
811 // -- CanonHom --> CanonicalHom
812 //
813 // Revision 1.14  2007/03/05 21:06:07  cocoa
814 // New names for homomorphism pseudo-ctors: removed the "New" prefix.
815 //
816 // Revision 1.13  2007/03/03 14:07:23  bigatti
817 // -- "foundations" renamed into "GlobalManager"
818 //
819 // Revision 1.12  2007/03/02 10:47:53  cocoa
820 // First stage of RingZ modifications -- tests do not compile currently, Anna will fix this.
821 //
822 // Revision 1.11  2007/01/17 12:32:39  cocoa
823 // Changed a few more "raw" variable names so that the code compiles fine
824 // also when CoCoA_DEBUG is set.
825 //
826 // Revision 1.10  2007/01/15 15:47:57  cocoa
827 // -- added prefix "raw" to RawPtr arguments names
828 // -- changed rhs into rawx, n, or N
829 //
830 // Revision 1.9  2007/01/13 14:14:34  cocoa
831 // Overhaul of RingHom code: it nows uses SmartPtrIRC, and printing is more logical.
832 // Have not yet updated the documentation.
833 //
834 // Revision 1.8  2006/12/06 17:37:29  cocoa
835 // -- rearranged #include
836 //
837 // Revision 1.7  2006/11/08 16:21:59  cocoa
838 // Structural cleaning of RingHom; many consequential changes.
839 //
840 // Revision 1.6  2006/11/03 14:01:46  cocoa
841 // -- changed: reference counting in ring, PPMonoids and OrdvArith now
842 //    uses SmartPtrIRC
843 //
844 // Revision 1.5  2006/11/02 13:25:44  cocoa
845 // Simplification of header files: the OpenMath classes have been renamed.
846 // Many minor consequential changes.
847 //
848 // Revision 1.4  2006/10/16 23:18:59  cocoa
849 // Corrected use of std::swap and various special swap functions.
850 // Improved myApply memfn for homs of RingDistrMPolyInlPP.
851 //
852 // Revision 1.3  2006/10/06 14:04:14  cocoa
853 // Corrected position of #ifndef in header files.
854 // Separated CoCoA_ASSERT into assert.H from config.H;
855 // many minor consequential changes (have to #include assert.H).
856 // A little tidying of #include directives (esp. in Max's code).
857 //
858 // Revision 1.2  2006/10/06 10:15:52  cocoa
859 // In response to Susan's bug: a fiasco when compiling with CoCoA_MEMPOOL_DEBUG
860 // set wrongly.  Moved several implementation classes out of their header files
861 // into the implementation files.  Several functions had to be uninlined.
862 // Also corrected position of #include, etc.
863 //
864 // Revision 1.1.1.1  2006/05/30 11:39:37  cocoa
865 // Imported files
866 //
867 // Revision 1.8  2006/05/29 16:22:37  cocoa
868 // Third time lucky???
869 // Added myIsInteger member function to all rings (NYI for RingFloat).
870 //
871 // Revision 1.7  2006/05/12 16:10:58  cocoa
872 // Added OpenMathFwd.H, and tidied OpenMath.H.
873 // Many consequential but trivial changes.
874 //
875 // Revision 1.6  2006/04/21 15:01:36  cocoa
876 // Changed default implementation of RingBase::myGcd -- it now gives a SERIOUS
877 // error.  All fields must now handle a call to gcd explicitly: they can use
878 // the new myGcdInField function.  It's now cleaner than it was.
879 //
880 // Revision 1.5  2006/03/15 18:09:31  cocoa
881 // Changed names of member functions which print out their object
882 // into myOutputSelf -- hope this will appease the Intel C++ compiler.
883 //
884 // Revision 1.4  2006/03/14 15:01:49  cocoa
885 // Improved the implementation of ring member fns for computing powers.
886 // Should keep Intel C++ compiler quieter too.
887 //
888 // Revision 1.3  2006/03/12 21:28:33  cocoa
889 // Major check in after many changes
890 //
891 // Revision 1.2  2005/10/18 12:06:36  cocoa
892 // Cleaned Makefiles, and fixed them so they should work wherever
893 // CoCoALib is unpacked.
894 //
895 // Replaced VERSION cpp macro with COCOA_VERSION.
896 //
897 // Revision 1.1.1.1  2005/10/17 10:46:54  cocoa
898 // Imported files
899 //
900 // Revision 1.5  2005/10/14 15:25:07  cocoa
901 // Major tidying and cleaning to small prime finite fields.
902 // Several consequential changes.  Improved their documentation.
903 //
904 // Added Makefile and script to include/CoCoA/ directory to
905 // keep library.H up to date.
906 //
907 // Revision 1.4  2005/10/12 15:52:09  cocoa
908 // Completed test-RingFp1 and corrected/cleaned the SmallFp*
909 // and RingFp* files.
910 //
911 // Some minor tidying elsewhere.
912 //
913 // Revision 1.3  2005/10/11 16:37:30  cocoa
914 // Added new small prime finite field class (see RingFpDouble).
915 //
916 // Cleaned makefiles and configuration script.
917 //
918 // Tidied PPMonoid code (to eliminate compiler warnings).
919 //
920 // Fixed bug in RingFloat::myIsInteger.
921 //
922 // Revision 1.2  2005/09/22 18:04:17  cocoa
923 // It compiles; the tests run OK.  The examples compile.
924 // No documentation -- the mindless eurocrats have rendered
925 // me mindless too.
926 //
927 // Revision 1.1.1.1  2005/05/03 15:47:31  cocoa
928 // Imported files
929 //
930 // Revision 1.5  2005/04/20 15:40:48  cocoa
931 // Major change: modified the standard way errors are to be signalled
932 // (now via a macro which records filename and line number).  Updated
933 // documentation in error.txt accordingly.
934 //
935 // Improved the documentation in matrix.txt (still more work to be done).
936 //
937 // Revision 1.4  2005/04/19 14:06:03  cocoa
938 // Added GPL and GFDL licence stuff.
939 //
940 // Revision 1.3  2005/02/11 16:45:24  cocoa
941 // Removed the useless and misleading functions myInit and myKill
942 // from the SmallFp*Impl classes; various consequential changes.
943 //
944 // Revision 1.2  2005/02/11 14:15:20  cocoa
945 // New style ring elements and references to ring elements;
946 // I hope I have finally got it right!
947 //
948 // Revision 1.1.1.1  2005/01/27 15:12:13  cocoa
949 // Imported files
950 //
951 // Revision 1.20  2004/11/18 18:33:41  cocoa
952 // Now every ring know its own "one" element (as well as "zero").
953 // Several consequential changes.
954 //
955 // Revision 1.19  2004/11/12 15:49:29  cocoa
956 // Tidying prior to 0.90 release.
957 // (a) documentation improved (or marked as poor)
958 // (b) sundry minor improvements to the code
959 //
960 // Revision 1.18  2004/11/09 15:47:29  cocoa
961 // -- changed myOutput: FF --> FFp
962 //
963 // Revision 1.17  2004/11/05 15:34:33  cocoa
964 // Consequential change following from the renaming of
965 // FieldIdealImpl and the introduction of the new pseudo-ctor.
966 //
967 // Revision 1.16  2004/11/04 18:47:43  cocoa
968 // (1) Ring member functions which previously expected mpz_t args
969 //     now expect ZZ args.  Numerous minor consequential changes.
970 // (2) Renamed function which gives access to the mpz_t value inside
971 //     a ZZ object: previously was raw(...), now is mpzref(...).
972 //     Plenty of calls had to be altered.
973 //
974 // Revision 1.15  2004/11/02 15:09:45  cocoa
975 // -- added name to MemPool
976 //
977 // Revision 1.14  2004/07/27 16:03:39  cocoa
978 // Added IsCommutative test and IamCommutative member function
979 // to all rings.  Tidied geobuckets a little.
980 //
981 // Revision 1.13  2004/07/14 16:40:42  cocoa
982 // Separated RingFpLog from its implementation which now resides in
983 // a new class: SmallFpLogImpl.  This is analogous to the change made
984 // to RingFp yesterday.
985 //
986 // Some tidying and other sundry minor changes.
987 //
988 // Revision 1.12  2004/07/13 16:32:26  cocoa
989 // First stage of major revamp of ring elements.
990 // Implementation of RingFp has been split into "ring interface"
991 // and "algorithms plus data structures".
992 //
993 // Revision 1.11  2004/05/24 15:52:13  cocoa
994 // Major update:
995 //   new error mechanism
996 //   many fixes
997 //   RingHoms almost work now
998 //   RingFloat much improved
999 //
1000 // Revision 1.10  2004/04/08 15:33:34  cocoa
1001 // Added function IsInteger, and the related RingBase::myIsInteger
1002 // virtual function, plus all necessary implementations.
1003 //
1004 // Revision 1.9  2004/03/20 17:46:10  cocoa
1005 // Check in prior to departure to RWCA
1006 //
1007 // Revision 1.8  2004/02/03 16:16:20  cocoa
1008 // Removed pointless IamGCDDomain functions from several concrete rings.
1009 // Added IamOrderedDomain functions where appropriate.
1010 // Tidied ctors for the small finite fields.
1011 //
1012 // Revision 1.7  2004/01/30 14:07:10  cocoa
1013 // Tidied RingRawValue union: now it contains just two fields,
1014 // and has no need of forward declarations of types used internally
1015 // by the concrete rings -- it uses explicitly a void* instead.
1016 //
1017 // I have tidied the "import" functions used by most concrete rings.
1018 //
1019 // I have moved the choice of representation type for RingFp and RingFpLog
1020 // into a typedef in config.H -- this is to recognise that different
1021 // choices may work best on different platforms.
1022 //
1023 // Revision 1.6  2004/01/28 15:50:20  cocoa
1024 // Better arrangement for #includes.
1025 //
1026 // Revision 1.5  2003/11/14 13:06:05  cocoa
1027 // -- New function "myIsPrintAtom" for printing polynomials and fractions
1028 //
1029 // Revision 1.4  2003/10/17 10:51:06  cocoa
1030 // Major cleaning, and new naming convention.
1031 //
1032 // Revision 1.3  2003/10/09 14:55:19  cocoa
1033 // - minor debugging after merge
1034 //
1035 // Revision 1.2  2003/10/09 12:15:45  cocoa
1036 // New coding convention for rings.
1037 //
1038 // Revision 1.21  2003/06/23 16:54:00  abbott
1039 // Minor cleaning prior to public release.
1040 // Just a name change.
1041 //
1042 // Revision 1.20  2003/04/24 16:11:32  abbott
1043 // Made exgcd a static member function so it could "see" the private type
1044 // ring_Fp::FpElem (previously it had been public).
1045 //
1046 // Revision 1.19  2003/04/23 10:07:44  abbott
1047 // Consequential changes following the modifications to ring_Fp.H:
1048 //  * first parameter to ring_Fp::hom ctor is now QuotientRing
1049 //  * commented out code for using doubles in ring_Fp::mul.
1050 //
1051 // Revision 1.18  2003/04/17 16:51:38  abbott
1052 // See detailed comments in ring_Fp.  Added handling for ring homomorphisms
1053 // and for ideals.  Also ring_Fp is now derived from QuotientRingBase.
1054 //
1055 // Revision 1.17  2002/11/14 18:05:54  abbott
1056 // Revised in line with the renaming in ring.H
1057 // Fixed a couple of buglets, improved some error messages.
1058 //
1059 // Revision 1.16  2002/07/05 15:23:00  abbott
1060 // Added definition of member function IsDivisible.
1061 //
1062 // Revision 1.15  2002/06/28 14:50:00  abbott
1063 // Now the zero element is pointed by an auto_ptr (to be consistent with
1064 // other rings).  The member typedef "elem" is now called "FpElem".
1065 // Added a size check on the argument to the constructor: its square
1066 // must fit in a ring_Fp::FpElem.
1067 //
1068 // Revision 1.14  2002/06/27 16:08:19  abbott
1069 // Added "smart" specialized definition of ring_Fp::power;
1070 // previously it used the default definition (sequential powering).
1071 //
1072 // Revision 1.13  2002/06/26 14:37:15  abbott
1073 // Fixed Anna's bug in ring_Fp::assign(RawValue&, long).
1074 //
1075 // Revision 1.12  2002/06/22 17:09:11  abbott
1076 // Changed name of "equal" member function to "IsEqual" (as per new ring.H).
1077 //
1078 // Revision 1.11  2002/05/30 13:35:27  abbott
1079 // Corrected return type of zero function.
1080 //
1081 // Revision 1.10  2002/05/19 17:40:09  abbott
1082 // Added IsField and zero member functions.
1083 // Consquential changes to ctor and dtor.
1084 //
1085 // Revision 1.9  2002/05/15 15:03:10  abbott
1086 // Added characteristic and negate functions as required by new ring.H interface.
1087 // Consequential changes due to change of data member in ring_Fp.H.
1088 // Tidied indentation.
1089 //
1090 // Revision 1.8  2002/02/08 11:17:06  bigatti
1091 // - changed syntax to IsZeroAddMul
1092 //
1093 // Revision 1.7  2002/01/30 15:16:56  abbott
1094 // Tidied "using" declaration.
1095 // Added definition of IsZeroAddMul.
1096 //
1097 // Revision 1.6  2001/12/07 18:23:51  abbott
1098 // Changed names in accordance with new coding conventions.
1099 //
1100 // Revision 1.5  2001/11/23 20:57:57  abbott
1101 // Added assignment from a long.
1102 //
1103 // Revision 1.4  2001/11/16 19:11:57  bigatti
1104 // added:   using namespace std;
1105 // for compatibility with gcc-3
1106 //
1107 // Revision 1.3  2001/11/07 20:57:33  abbott
1108 // The change of type of ring::raw_elem to a union (from a void*) allows
1109 // "inline" small finite field coefficients.  Almost every function here
1110 // has undergone a (minor) consequential change: a union selector instead
1111 // of a cast (hidden inside a function).
1112 //
1113 // Revision 1.2  2001/10/29 20:41:30  abbott
1114 // Several minor additions to fit the ring model.
1115 // Added MemPool management for the heap-based values: reconsidering the
1116 // question of how to implement ring::raw_elem values for small finite
1117 // fields [how important is efficiency/cleanliness here?]
1118 //
1119 // Revision 1.1  2001/10/05 12:56:00  abbott
1120 // Initial revision
1121 //
1122