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