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