1 // Copyright (c) 2005-2012,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/RingFpDouble.H" 19 20 #include "CoCoA/BigIntOps.H" 21 #include "CoCoA/BigRat.H" 22 #include "CoCoA/FieldIdeal.H" 23 #include "CoCoA/GlobalManager.H" 24 #include "CoCoA/MemPool.H" 25 #include "CoCoA/OpenMath.H" 26 #include "CoCoA/QuotientRing.H" 27 #include "CoCoA/RingHom.H" 28 #include "CoCoA/RingZZ.H" 29 #include "CoCoA/SmallFpDoubleImpl.H" 30 #include "CoCoA/assert.H" 31 #include "CoCoA/convert.H" 32 #include "CoCoA/error.H" 33 #include "CoCoA/ideal.H" 34 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 RingFpDoubleImpl: public QuotientRingBase 52 { 53 private: // data members 54 typedef SmallFpDoubleImpl::value_t value_t; 55 const unsigned long myModulus; 56 const SmallFpDoubleImpl 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 unsigned 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: 67 RingFpDoubleImpl(const ideal& I, GlobalSettings::ResidueSetting ResidueChoice = DefaultResidueSetting()); // called only by NewRingFpDouble 68 ~RingFpDoubleImpl(); 69 friend QuotientRing NewRingFpDouble(const MachineInt& p, GlobalSettings::ResidueSetting ResidueChoice); 70 friend QuotientRing NewRingFpDouble(const BigInt& P); 71 friend QuotientRing NewRingFpDouble(const ideal& I); 72 private: 73 RingFpDoubleImpl(const RingFpDoubleImpl&); ///< NEVER DEFINED -- disallow copy construction 74 RingFpDoubleImpl& operator=(const RingFpDoubleImpl&); ///< NEVER DEFINED -- disallow assignment 75 public: 76 77 // functions inherited by RingBase (ring.H) 78 //-- ring 79 virtual void myCharacteristic(BigInt& p) const; 80 virtual long myLogCardinality() const; 81 virtual bool IamCommutative() const; 82 virtual bool3 IamIntegralDomain3(bool) const; 83 virtual bool IamField() const; 84 virtual bool IamFiniteField() const; 85 virtual bool IamExact() const; 86 virtual void myOutputSelf(std::ostream& out) const; 87 virtual void myOutputSelf(OpenMathOutput& OMOut) const; 88 //-- RingElem: memory 89 virtual ConstRefRingElem myZero() const; 90 virtual ConstRefRingElem myOne() const; 91 using RingBase::myNew; // disable warnings of overloading 92 using RingBase::myAssign; // disable warnings of overloading 93 virtual RingElemRawPtr myNew() const; 94 virtual RingElemRawPtr myNew(const MachineInt& n) const; 95 virtual RingElemRawPtr myNew(const BigInt& N) const; 96 virtual RingElemRawPtr myNew(ConstRawPtr rawx) const; 97 virtual void myDelete(RawPtr rawx) const; 98 //-- RingElem: assignments 99 virtual void myAssign(RawPtr rawlhs, ConstRawPtr rawx) const; 100 virtual void myAssign(RawPtr rawlhs, const MachineInt& n) const; 101 virtual void myAssign(RawPtr rawlhs, const BigInt& N) const; 102 virtual void myAssignZero(RawPtr rawlhs) const; 103 virtual void myRecvTwinFloat(RawPtr rawlhs, ConstRawPtr rawx) const; 104 virtual void mySwap(RawPtr rawx, RawPtr rawy) const; 105 //-- RingElem: arithmetic 106 virtual void myNegate(RawPtr rawlhs, ConstRawPtr rawx) const; 107 virtual void myAdd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const; 108 virtual void mySub(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const; 109 virtual void myMul(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const; 110 virtual void myDiv(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const; 111 virtual void myGcd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const; // lhs = gcd(x,y) in a field 112 //-- RingElem: queries 113 virtual bool myIsZero(ConstRawPtr rawx) const; 114 virtual bool myIsOne(ConstRawPtr rawx) const; 115 virtual bool myIsMinusOne(ConstRawPtr rawx) const; 116 virtual bool myIsEqual(ConstRawPtr rawx, ConstRawPtr rawy) const; 117 virtual bool myIsInteger(BigInt& N, ConstRawPtr rawx) const; ///< always true 118 virtual bool myIsRational(BigRat& Q, ConstRawPtr rawx) const; 119 virtual bool myIsDouble(double& d, ConstRawPtr rawx) const; 120 virtual bool myIsDivisible(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const; 121 virtual bool myIsInvertible(ConstRawPtr rawx) const; 122 virtual bool myIsZeroAddMul(RawPtr rawlhs, ConstRawPtr rawy, ConstRawPtr rawz) const; 123 virtual bool myIsZeroAddMul(RawPtr rawlhs, RawPtr /*rawtmp*/, ConstRawPtr rawy, ConstRawPtr rawz) const; 124 //-- RingElem: printing 125 virtual void myOutput(std::ostream& out, ConstRawPtr rawx) const; 126 virtual void myOutput(OpenMathOutput& OMOut, ConstRawPtr rawx) const; 127 virtual bool myIsPrintAtom(ConstRawPtr rawx) const; 128 virtual bool myIsPrintedWithMinus(ConstRawPtr rawx) const; 129 //-- ideal 130 virtual ideal myIdealCtor(const std::vector<RingElem>& gens) const; 131 //-- RingHom 132 virtual RingHom myCompose(const RingHom& phi, const RingHom& theta) const; // phi(theta(...)) 133 134 virtual bool myImageLiesInSubfield(const RingHom& phi) const; 135 136 //-- protected in RingBase 137 virtual void myPowerSmallExp(RawPtr rawlhs, ConstRawPtr rawx, long n) const; 138 virtual void myPowerBigExp(RawPtr rawlhs, ConstRawPtr rawx, const BigInt& N) const; // lhs = x^N, N big, x not -1,0,1 139 140 // functions inherited by QuotientRingBase (QuotientRing.H) 141 virtual RingElem myCanonicalRepr(ConstRawPtr rawx) const; 142 virtual void myReduction(RawPtr rawimage, ConstRawPtr rawarg) const; 143 virtual RingHom myInducedHomCtor(const RingHom& InducingHom) const; 144 145 146 private: 147 class InducedHomImpl: public RingHomBase 148 { 149 public: 150 InducedHomImpl(const QuotientRing& domain, const RingHom& InducingHom); 151 virtual void myApply(RingElemRawPtr rawimage, RingElemConstRawPtr rawarg) const; IamPartial()152 virtual bool IamPartial() const { return false; } 153 }; 154 155 }; 156 157 158 import(RingElemRawPtr rawx)159 inline RingFpDoubleImpl::value_t& RingFpDoubleImpl::import(RingElemRawPtr rawx) 160 { 161 return *static_cast<value_t*>(rawx.myRawPtr()); 162 } 163 import(RingElemConstRawPtr rawx)164 inline const RingFpDoubleImpl::value_t& RingFpDoubleImpl::import(RingElemConstRawPtr rawx) 165 { 166 return *static_cast<const value_t*>(rawx.myRawPtr()); 167 } 168 169 170 // Returns generator of I as a value_t; returns 0 if value is too large to fit. PrincipalGen(const ideal & I)171 unsigned long RingFpDoubleImpl::PrincipalGen(const ideal& I) 172 { 173 if (IsZero(I)) return 0; 174 const BigInt GenI = ConvertTo<BigInt>(TidyGens(I)[0]); 175 unsigned long p; 176 if (!IsConvertible(p, GenI)) // check that the value of the principal generator will fit 177 return 0; 178 return p; 179 } 180 181 RingFpDoubleImpl(const ideal & I,GlobalSettings::ResidueSetting ResidueChoice)182 RingFpDoubleImpl::RingFpDoubleImpl(const ideal& I, GlobalSettings::ResidueSetting ResidueChoice): 183 QuotientRingBase(RingZZ(), I), // confirms that I is an ideal of Z 184 myModulus(PrincipalGen(I)), 185 myImpl(myModulus, ResidueChoice), // also checks that myModulus is a small prime 186 myMemMgr(SmallFpDoubleImpl::ourDatumSize, "RingFpDoubleImpl.myMemMgr") 187 { 188 myRefCountInc(); // this is needed for exception cleanliness, in case one of the lines below throws 189 myZeroPtr.reset(new RingElem(ring(this))); 190 myOnePtr.reset(new RingElem(ring(this), 1)); 191 myRefCountZero(); 192 } 193 194 ~RingFpDoubleImpl()195 RingFpDoubleImpl::~RingFpDoubleImpl() 196 {} 197 198 myCharacteristic(BigInt & p)199 void RingFpDoubleImpl::myCharacteristic(BigInt& p) const 200 { 201 p = myModulus; 202 } 203 204 myLogCardinality()205 long RingFpDoubleImpl::myLogCardinality() const 206 { 207 return 1; 208 } 209 210 IamCommutative()211 bool RingFpDoubleImpl::IamCommutative() const 212 { 213 return true; 214 } 215 216 IamIntegralDomain3(bool)217 bool3 RingFpDoubleImpl::IamIntegralDomain3(bool) const 218 { 219 return true3; 220 } 221 222 IamField()223 bool RingFpDoubleImpl::IamField() const 224 { 225 return true; 226 } 227 228 IamFiniteField()229 bool RingFpDoubleImpl::IamFiniteField() const 230 { 231 return true; 232 } 233 234 IamExact()235 bool RingFpDoubleImpl::IamExact() const 236 { 237 return true; 238 } 239 240 myZero()241 ConstRefRingElem RingFpDoubleImpl::myZero() const 242 { 243 return *myZeroPtr; 244 } 245 246 myOne()247 ConstRefRingElem RingFpDoubleImpl::myOne() const 248 { 249 return *myOnePtr; 250 } 251 252 myNew()253 RingElemRawPtr RingFpDoubleImpl::myNew() const 254 { 255 value_t* ans = static_cast<value_t*>(myMemMgr.alloc()); 256 *ans = 0; 257 return RingElemRawPtr(ans); 258 } 259 260 myNew(const MachineInt & n)261 RingElemRawPtr RingFpDoubleImpl::myNew(const MachineInt& n) const 262 { 263 value_t* ans = static_cast<value_t*>(myMemMgr.alloc()); 264 *ans = myImpl.myReduce(n); 265 return RingElemRawPtr(ans); 266 } 267 268 myNew(const BigInt & N)269 RingElemRawPtr RingFpDoubleImpl::myNew(const BigInt& N) const 270 { 271 value_t* ans = static_cast<value_t*>(myMemMgr.alloc()); 272 *ans = myImpl.myReduce(N); 273 return RingElemRawPtr(ans); 274 } 275 276 myNew(ConstRawPtr rawy)277 RingElemRawPtr RingFpDoubleImpl::myNew(ConstRawPtr rawy) const 278 { 279 value_t* ans = static_cast<value_t*>(myMemMgr.alloc()); 280 *ans = import(rawy); 281 return RingElemRawPtr(ans); 282 } 283 284 myDelete(RawPtr rawx)285 void RingFpDoubleImpl::myDelete(RawPtr rawx) const 286 { 287 myMemMgr.free(rawx.myRawPtr()); 288 } 289 290 mySwap(RawPtr rawx,RawPtr rawy)291 void RingFpDoubleImpl::mySwap(RawPtr rawx, RawPtr rawy) const 292 { 293 std::swap(import(rawx), import(rawy)); 294 } 295 296 myAssign(RawPtr rawlhs,ConstRawPtr rawx)297 void RingFpDoubleImpl::myAssign(RawPtr rawlhs, ConstRawPtr rawx) const 298 { 299 import(rawlhs) = import(rawx); 300 } 301 302 myAssign(RawPtr rawlhs,const MachineInt & n)303 void RingFpDoubleImpl::myAssign(RawPtr rawlhs, const MachineInt& n) const 304 { 305 import(rawlhs) = myImpl.myReduce(n); 306 } 307 308 myAssign(RawPtr rawlhs,const BigInt & N)309 void RingFpDoubleImpl::myAssign(RawPtr rawlhs, const BigInt& N) const 310 { 311 import(rawlhs) = myImpl.myReduce(N); 312 } 313 314 myAssignZero(RawPtr rawlhs)315 void RingFpDoubleImpl::myAssignZero(RawPtr rawlhs) const 316 { 317 import(rawlhs) = 0; 318 } 319 320 myRecvTwinFloat(RawPtr,ConstRawPtr)321 void RingFpDoubleImpl::myRecvTwinFloat(RawPtr /*rawlhs*/, ConstRawPtr /*rawx*/) const 322 { 323 CoCoA_THROW_ERROR(ERR::ShouldNeverGetHere, "RingFpDoubleImpl::myRecvTwinFloat"); 324 } 325 326 myNegate(RawPtr rawlhs,ConstRawPtr rawx)327 void RingFpDoubleImpl::myNegate(RawPtr rawlhs, ConstRawPtr rawx) const 328 { 329 import(rawlhs) = myImpl.myNegate(import(rawx)); 330 } 331 332 myAdd(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)333 void RingFpDoubleImpl::myAdd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const 334 { 335 import(rawlhs) = myImpl.myAdd(import(rawx), import(rawy)); 336 } 337 338 mySub(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)339 void RingFpDoubleImpl::mySub(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const 340 { 341 import(rawlhs) = myImpl.mySub(import(rawx), import(rawy)); 342 } 343 344 myMul(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)345 void RingFpDoubleImpl::myMul(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const 346 { 347 import(rawlhs) = myImpl.myMul(import(rawx), import(rawy)); 348 } 349 350 myDiv(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)351 void RingFpDoubleImpl::myDiv(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const 352 { 353 CoCoA_ASSERT(!myIsZero(rawy)); 354 import(rawlhs) = myImpl.myDiv(import(rawx), import(rawy)); 355 } 356 357 myIsDivisible(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)358 bool RingFpDoubleImpl::myIsDivisible(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const 359 { 360 if (myIsZero(rawy)) return false; 361 myDiv(rawlhs, rawx, rawy); 362 return true; 363 } 364 365 myIsInvertible(ConstRawPtr rawx)366 bool RingFpDoubleImpl::myIsInvertible(ConstRawPtr rawx) const 367 { 368 return !myIsZero(rawx); 369 } 370 371 myGcd(RawPtr rawlhs,ConstRawPtr rawx,ConstRawPtr rawy)372 void RingFpDoubleImpl::myGcd(RawPtr rawlhs, ConstRawPtr rawx, ConstRawPtr rawy) const 373 { 374 myGcdInField(rawlhs, rawx, rawy); 375 } 376 377 myPowerSmallExp(RawPtr rawlhs,ConstRawPtr rawx,long n)378 void RingFpDoubleImpl::myPowerSmallExp(RawPtr rawlhs, ConstRawPtr rawx, long n) const // assumes n > 1 379 { 380 // Assert that we have a genuinely non-trivial case. 381 CoCoA_ASSERT(n > 1); 382 CoCoA_ASSERT(!myIsZero(rawx) && !myIsOne(rawx) && !myIsMinusOne(rawx)); 383 import(rawlhs) = myImpl.myPower(import(rawx), n); 384 } 385 myPowerBigExp(RawPtr rawlhs,ConstRawPtr rawx,const BigInt & N)386 void RingFpDoubleImpl::myPowerBigExp(RawPtr rawlhs, ConstRawPtr rawx, const BigInt& N) const 387 { 388 // Assert that we have a genuinely non-trivial case. 389 CoCoA_ASSERT(N > 1); 390 CoCoA_ASSERT(!myIsZero(rawx) && !myIsOne(rawx) && !myIsMinusOne(rawx)); 391 // Use Fermat's Little Theorem to reduce exponent... 392 import(rawlhs) = myImpl.myPower(import(rawx), N%(myModulus-1)); 393 } 394 395 myOutput(ostream & out,ConstRawPtr rawx)396 void RingFpDoubleImpl::myOutput(ostream& out, ConstRawPtr rawx) const 397 { 398 if (!out) return; // short-cut for bad ostreams 399 out << myImpl.myExport(import(rawx)); 400 } 401 402 myIsPrintAtom(ConstRawPtr rawx)403 bool RingFpDoubleImpl::myIsPrintAtom(ConstRawPtr rawx) const 404 { 405 return myImpl.myExport(import(rawx)) >= 0; 406 } 407 408 myIsPrintedWithMinus(ConstRawPtr rawx)409 bool RingFpDoubleImpl::myIsPrintedWithMinus(ConstRawPtr rawx) const 410 { 411 return myImpl.myExport(import(rawx)) < 0; 412 } 413 414 myOutputSelf(ostream & out)415 void RingFpDoubleImpl::myOutputSelf(ostream& out) const 416 { 417 if (!out) return; // short-cut for bad ostreams 418 out << "RingWithID(" << myID << ", \"ZZ/(" << myModulus << ")\")"; 419 } 420 421 myOutputSelf(OpenMathOutput & OMOut)422 void RingFpDoubleImpl::myOutputSelf(OpenMathOutput& OMOut) const 423 { 424 OMOut->mySendApplyStart(); 425 OMOut << OpenMathSymbol("setname2", "GFp"); 426 OMOut << myModulus; 427 OMOut->mySendApplyEnd(); 428 } 429 430 myOutput(OpenMathOutput & OMOut,ConstRawPtr rawx)431 void RingFpDoubleImpl::myOutput(OpenMathOutput& OMOut, ConstRawPtr rawx) const 432 { 433 OMOut << myImpl.myExport(import(rawx)); 434 } 435 436 myIsZero(ConstRawPtr rawx)437 bool RingFpDoubleImpl::myIsZero(ConstRawPtr rawx) const 438 { 439 return (import(rawx) == 0); 440 } 441 442 myIsOne(ConstRawPtr rawx)443 bool RingFpDoubleImpl::myIsOne(ConstRawPtr rawx) const 444 { 445 return (import(rawx) == 1); 446 } 447 448 myIsMinusOne(ConstRawPtr rawx)449 bool RingFpDoubleImpl::myIsMinusOne(ConstRawPtr rawx) const 450 { 451 return (import(rawx) == myImpl.myReduce(-1)); 452 } 453 454 myIsInteger(BigInt & N,ConstRawPtr rawx)455 bool RingFpDoubleImpl::myIsInteger(BigInt& N, ConstRawPtr rawx) const 456 { 457 N = myImpl.myExport(import(rawx)); 458 return true; 459 } 460 461 myIsRational(BigRat & Q,ConstRawPtr rawx)462 bool RingFpDoubleImpl::myIsRational(BigRat& Q, ConstRawPtr rawx) const 463 { 464 Q = myImpl.myExport(import(rawx)); 465 return true; 466 } 467 468 myIsDouble(double & d,ConstRawPtr rawx)469 bool RingFpDoubleImpl::myIsDouble(double& d, ConstRawPtr rawx) const 470 { 471 d = myImpl.myExport(import(rawx)); 472 return true; 473 } 474 475 myIsZeroAddMul(RawPtr rawlhs,ConstRawPtr rawfact1,ConstRawPtr rawfact2)476 bool RingFpDoubleImpl::myIsZeroAddMul(RawPtr rawlhs, ConstRawPtr rawfact1, ConstRawPtr rawfact2) const 477 { 478 return myImpl.myIsZeroAddMul(import(rawlhs), import(rawfact1), import(rawfact2)); 479 } 480 481 myIsZeroAddMul(RawPtr rawlhs,RawPtr,ConstRawPtr rawfact1,ConstRawPtr rawfact2)482 bool RingFpDoubleImpl::myIsZeroAddMul(RawPtr rawlhs, RawPtr /*rawtmp*/, ConstRawPtr rawfact1, ConstRawPtr rawfact2) const 483 { 484 return myImpl.myIsZeroAddMul(import(rawlhs), import(rawfact1), import(rawfact2)); 485 } 486 487 myIsEqual(ConstRawPtr rawx,ConstRawPtr rawy)488 bool RingFpDoubleImpl::myIsEqual(ConstRawPtr rawx, ConstRawPtr rawy) const 489 { 490 return (import(rawx) == import(rawy)); 491 } 492 493 494 495 myIdealCtor(const std::vector<RingElem> & gens)496 ideal RingFpDoubleImpl::myIdealCtor(const std::vector<RingElem>& gens) const 497 { 498 return NewFieldIdeal(ring(this), gens); 499 } 500 501 myCompose(const RingHom & phi,const RingHom & theta)502 RingHom RingFpDoubleImpl::myCompose(const RingHom& phi, const RingHom& theta) const 503 { 504 // No need to check compatibility -- it was checked when theta and phi were built 505 return RingHom(new InducedHomImpl(QuotientRing(this), phi(theta(myQuotientingHomCtor())))); 506 } 507 508 myImageLiesInSubfield(const RingHom & phi)509 bool RingFpDoubleImpl::myImageLiesInSubfield(const RingHom& phi) const 510 { 511 (void)(phi); // to avoid compiler warning about unused parameter 512 CoCoA_ASSERT(codomain(phi) == ring(this)); 513 return true; 514 } 515 516 myCanonicalRepr(ConstRawPtr rawx)517 RingElem RingFpDoubleImpl::myCanonicalRepr(ConstRawPtr rawx) const 518 { 519 return RingElem(myReprRing, myImpl.myExport(import(rawx))); 520 } 521 522 myReduction(RawPtr rawimage,ConstRawPtr rawarg)523 void RingFpDoubleImpl::myReduction(RawPtr rawimage, ConstRawPtr rawarg) const 524 { 525 BigInt tmp; 526 CoCoA_ASSERT(myReprRing->myIsInteger(tmp, rawarg)); 527 myReprRing->myIsInteger(tmp, rawarg); 528 import(rawimage) = myImpl.myReduce(tmp); 529 } 530 531 myInducedHomCtor(const RingHom & InducingHom)532 RingHom RingFpDoubleImpl::myInducedHomCtor(const RingHom& InducingHom) const 533 { 534 // Compatibility has already been checked (see InducedHom in QuotientRing.C) 535 CoCoA_ASSERT(IsZero(InducingHom(myModulus))); 536 return RingHom(new InducedHomImpl(QuotientRing(this), InducingHom)); 537 } 538 539 540 //--------------------------------------------------------------------------- 541 // Functions to do with ring homomorphisms 542 543 InducedHomImpl(const QuotientRing & domain,const RingHom & InducingHom)544 RingFpDoubleImpl::InducedHomImpl::InducedHomImpl(const QuotientRing& domain, const RingHom& InducingHom): 545 RingHomBase(domain, codomain(InducingHom)) 546 { /* Compatibility already checked in InducedHom in QuotientRing.C */ } 547 548 myApply(RingElemRawPtr rawimage,RingElemConstRawPtr rawarg)549 void RingFpDoubleImpl::InducedHomImpl::myApply(RingElemRawPtr rawimage, RingElemConstRawPtr rawarg) const 550 { 551 BigInt tmp; //??? wasteful new/delete 552 CoCoA_ASSERT(myDomain->myIsInteger(tmp, rawarg)); 553 myDomain->myIsInteger(tmp, rawarg); // must necessarily succeed 554 myCodomain->myAssign(rawimage, tmp); 555 } 556 557 558 NewRingFpDouble(const MachineInt & p,GlobalSettings::ResidueSetting ResidueChoice)559 QuotientRing NewRingFpDouble(const MachineInt& p, GlobalSettings::ResidueSetting ResidueChoice) 560 { 561 return QuotientRing(new RingFpDoubleImpl(ideal(RingElem(RingZZ(), p)), ResidueChoice)); 562 } 563 NewRingFpDouble(const BigInt & P)564 QuotientRing NewRingFpDouble(const BigInt& P) 565 { 566 return QuotientRing(new RingFpDoubleImpl(ideal(RingElem(RingZZ(), P)))); 567 } 568 NewRingFpDouble(const ideal & I)569 QuotientRing NewRingFpDouble(const ideal& I) 570 { 571 if (!IsZZ(RingOf(I))) CoCoA_THROW_ERROR(ERR::IdealNotInRing, "NewRingFpDouble(I)"); 572 return QuotientRing(new RingFpDoubleImpl(I)); 573 } 574 575 IsGoodForRingFpDouble(const MachineInt & p)576 bool IsGoodForRingFpDouble(const MachineInt& p) 577 { 578 if (IsNegative(p) || !IsSignedLong(p)) return false; 579 const long n = AsSignedLong(p); 580 return SmallFpDoubleImpl::IsGoodCtorArg(n); 581 } 582 IsGoodForRingFpDouble(const BigInt & P)583 bool IsGoodForRingFpDouble(const BigInt& P) 584 { 585 if (P <= 0) return false; 586 long p; 587 if (!IsConvertible(p, P)) return false; 588 return IsGoodForRingFpDouble(p); 589 } 590 IsGoodForRingFpDouble(const ideal & I)591 bool IsGoodForRingFpDouble(const ideal& I) 592 { 593 if (!IsZZ(RingOf(I))) return false; 594 if (IsZero(I)) return false; 595 return IsGoodForRingFpDouble(ConvertTo<BigInt>(TidyGens(I)[0])); 596 } 597 598 599 } // end of namespace CoCoA 600 601 602 // RCS header/log 603 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/RingFpDouble.C,v 1.49 2020/06/17 15:49:26 abbott Exp $ 604 // $Log: RingFpDouble.C,v $ 605 // Revision 1.49 2020/06/17 15:49:26 abbott 606 // Summary: Changed CoCoA_ERROR into CoCoA_THROW_ERROR 607 // 608 // Revision 1.48 2020/02/11 16:56:41 abbott 609 // Summary: Corrected last update (see redmine 969) 610 // 611 // Revision 1.47 2020/02/11 16:12:19 abbott 612 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969 613 // 614 // Revision 1.46 2019/09/25 13:33:34 abbott 615 // Summary: Changed "compact" printed form of finite fields from FFp(...) to ZZ/(...) 616 // 617 // Revision 1.45 2019/03/04 10:57:05 abbott 618 // Summary: Changed auto_ptr into unique_ptr 619 // 620 // Revision 1.44 2018/05/18 12:22:30 bigatti 621 // -- renamed IntOperations --> BigIntOps 622 // 623 // Revision 1.43 2017/09/06 11:56:29 abbott 624 // Summary: Changed ERR::SERIOUS into ERR::ShouldNeverGetHere 625 // 626 // Revision 1.42 2015/07/29 11:04:55 bigatti 627 // -- added space after comma in printing rings 628 // 629 // Revision 1.41 2014/07/30 14:08:57 abbott 630 // Summary: Changed name AmbientRing --> RingOf 631 // Author: JAA 632 // 633 // Revision 1.40 2014/07/28 16:04:49 abbott 634 // Summary: Renamed myQuotientingHom to myQuotientingHomCtor 635 // Author: JAA 636 // 637 // Revision 1.39 2014/07/28 15:49:35 abbott 638 // Summary: Redesign: ringhoms no longer cached in rings (caused ref count trouble) 639 // Author: JAA 640 // 641 // Revision 1.38 2014/07/04 13:08:08 bigatti 642 // -- RingID into RingWithID 643 // 644 // Revision 1.37 2014/07/02 16:35:04 bigatti 645 // -- new way of printing ring with ID 646 // 647 // Revision 1.36 2014/06/17 10:13:10 abbott 648 // Summary: Added (void)(phi) to avoid compiler warning about unused param 649 // Author: JAA 650 // 651 // Revision 1.35 2014/05/14 15:57:15 bigatti 652 // -- added "using" for clang with superpedantic flag 653 // 654 // Revision 1.34 2014/04/02 10:57:46 abbott 655 // Summary: Revised design of IamIntegralDomain3 656 // Author: JAA 657 // 658 // Revision 1.33 2014/03/27 17:17:31 abbott 659 // Summary: Added new fn IsIntegralDomain3 (and mem fn IamIntegralDomain3) 660 // Author: JAA 661 // 662 // Revision 1.32 2014/01/28 10:02:48 abbott 663 // Replaced some calls to IsInteger by calls to ConvertTo<BigInt>. 664 // 665 // Revision 1.31 2013/03/25 17:04:19 abbott 666 // Major clean-up of interface to SmallFpImpl/SmallFpLogImpl/SmallFpDoubleImpl 667 // (underlying impl remains much the same). Removed lots of cruft. 668 // Consequential changes to RingFp* classes; small change to SparsePolyRing. 669 // 670 // Revision 1.30 2012/09/07 15:21:13 abbott 671 // First stage of revision of SmallFpImpl interface (and SmallFpLog, SmallFpDouble). 672 // 673 // Revision 1.29 2012/05/28 09:18:21 abbott 674 // Created IntOperations which gathers together all operations on 675 // integers (both big and small). Many consequential changes. 676 // 677 // Revision 1.28 2012/04/27 15:04:10 abbott 678 // Added mem fns IamFiniteField & myLogCardinality. 679 // 680 // Revision 1.27 2012/03/16 14:43:48 bigatti 681 // -- re-sorted 682 // 683 // Revision 1.26 2012/02/10 10:28:08 bigatti 684 // -- changed RingZ.H, RingQ.H --> RingZZ.H, RingQQ.H 685 // 686 // Revision 1.25 2012/02/08 17:06:40 bigatti 687 // -- changed: Z,Q -> ZZ,QQ 688 // -- reordered member functions (to be completed) 689 // 690 // Revision 1.24 2012/01/30 23:20:48 abbott 691 // Realigned comments (I hope, CVS did something funny though). 692 // 693 // Revision 1.23 2012/01/25 13:33:51 bigatti 694 // -- added myIsZeroAddMul with 4 args 695 // -- some tidying 696 // 697 // Revision 1.22 2011/11/09 14:11:58 bigatti 698 // -- renamed MachineInteger --> MachineInt 699 // 700 // Revision 1.21 2011/08/24 10:28:49 bigatti 701 // -- renamed QQ --> BigRat 702 // -- sorted #include 703 // 704 // Revision 1.20 2011/08/14 15:52:16 abbott 705 // Changed ZZ into BigInt (phase 1: just the library sources). 706 // 707 // Revision 1.19 2011/06/23 16:04:47 abbott 708 // Added IamExact mem fn for rings. 709 // Added myRecvTwinFloat mem fn for rings. 710 // Added first imple of RingHom from RingTwinFloat to other rings. 711 // 712 // Revision 1.18 2011/05/24 14:54:29 abbott 713 // Consquential changes from removing several ctors for principal ideals. 714 // 715 // Revision 1.17 2011/05/20 19:26:05 abbott 716 // Updated SmallFp*Impl: removed all output-related fns (must use myExport instead). 717 // 718 // Revision 1.16 2011/05/20 09:45:04 abbott 719 // Harmonized RingFp, RingFpLog, RingFpDouble -- they are now almost ready to be merged into a single class! 720 // 721 // Revision 1.15 2011/05/19 14:38:27 abbott 722 // Updated small prime finite field impls to allow user to specify 723 // separately for each whether to use symmetric or non-negative 724 // residues for export operations (myExport and printing). 725 // 726 // Revision 1.14 2011/03/22 20:00:37 abbott 727 // Added IsGoodForXXX fns to test whether a given arg is suitable as 728 // characteristic for the given type of small prime finite field. 729 // 730 // Revision 1.13 2011/03/10 16:39:34 abbott 731 // Replaced (very many) size_t by long in function interfaces (for rings, 732 // PPMonoids and modules). Also replaced most size_t inside fn defns. 733 // 734 // Revision 1.12 2010/10/06 14:10:24 abbott 735 // Added increments to the ref count in ring and PPMonoid ctors to make 736 // them exception safe. 737 // 738 // Revision 1.11 2009/12/11 11:46:32 abbott 739 // Changed fn convert into IsConvertible. 740 // Added template procedure convert. 741 // New version because change is not backward compatible. 742 // 743 // Revision 1.10 2009/09/25 14:01:11 abbott 744 // Cleaned up include directives. 745 // 746 // Revision 1.9 2009/09/24 16:22:29 abbott 747 // Tidied up include directives. Removed some unnecessary "std::" prefixes. 748 // 749 // Revision 1.8 2009/07/02 16:32:11 abbott 750 // Consequential changes stemming from new class QQ, and modified interface to the member 751 // function RingBase::myIsRational. Also some new conversion functions. 752 // 753 // Revision 1.7 2009/06/05 12:08:28 abbott 754 // Changed return type of operator%(ZZ,MachineInteger); it is now unsigned long 755 // instead of ZZ. 756 // 757 // Revision 1.6 2008/12/17 12:11:52 abbott 758 // Changed type from long to MachineInteger in operations which use a machine integer 759 // in place of a RingElem. The change is "superficial" but affects many files. 760 // 761 // Revision 1.5 2007/10/30 17:14:07 abbott 762 // Changed licence from GPL-2 only to GPL-3 or later. 763 // New version for such an important change. 764 // 765 // Revision 1.4 2007/05/22 22:45:14 abbott 766 // Changed fn name IsUnit to IsInvertible. 767 // 768 // Revision 1.3 2007/05/21 12:44:25 abbott 769 // Changed impl of powering routine as a consequence of changed signature 770 // to the modulus operator for ZZ modulo machine integer. 771 // 772 // Revision 1.2 2007/03/23 18:38:42 abbott 773 // Separated the "convert" functions (and CheckedCast) into their own files. 774 // Many consequential changes. Also corrected conversion to doubles. 775 // 776 // Revision 1.1.1.1 2007/03/09 15:16:11 abbott 777 // Imported files 778 // 779 // Revision 1.14 2007/03/08 18:22:29 cocoa 780 // Just whitespace cleaning. 781 // 782 // Revision 1.13 2007/03/08 10:23:29 bigatti 783 // -- CanonHom --> CanonicalHom 784 // 785 // Revision 1.12 2007/03/05 21:06:07 cocoa 786 // New names for homomorphism pseudo-ctors: removed the "New" prefix. 787 // 788 // Revision 1.11 2007/03/03 14:07:23 bigatti 789 // -- "foundations" renamed into "GlobalManager" 790 // 791 // Revision 1.10 2007/03/02 10:47:53 cocoa 792 // First stage of RingZ modifications -- tests do not compile currently, Anna will fix this. 793 // 794 // Revision 1.9 2007/01/17 12:32:39 cocoa 795 // Changed a few more "raw" variable names so that the code compiles fine 796 // also when CoCoA_DEBUG is set. 797 // 798 // Revision 1.8 2007/01/15 16:00:10 cocoa 799 // -- added prefix "raw" to RawPtr arguments names 800 // -- changed rhs into rawx, n, or N 801 // 802 // Revision 1.7 2007/01/13 14:14:34 cocoa 803 // Overhaul of RingHom code: it nows uses SmartPtrIRC, and printing is more logical. 804 // Have not yet updated the documentation. 805 // 806 // Revision 1.6 2006/11/08 16:21:59 cocoa 807 // Structural cleaning of RingHom; many consequential changes. 808 // 809 // Revision 1.5 2006/11/02 13:25:44 cocoa 810 // Simplification of header files: the OpenMath classes have been renamed. 811 // Many minor consequential changes. 812 // 813 // Revision 1.4 2006/10/16 23:18:59 cocoa 814 // Corrected use of std::swap and various special swap functions. 815 // Improved myApply memfn for homs of RingDistrMPolyInlPP. 816 // 817 // Revision 1.3 2006/10/06 14:04:14 cocoa 818 // Corrected position of #ifndef in header files. 819 // Separated CoCoA_ASSERT into assert.H from config.H; 820 // many minor consequential changes (have to #include assert.H). 821 // A little tidying of #include directives (esp. in Max's code). 822 // 823 // Revision 1.2 2006/10/06 10:15:52 cocoa 824 // In response to Susan's bug: a fiasco when compiling with CoCoA_MEMPOOL_DEBUG 825 // set wrongly. Moved several implementation classes out of their header files 826 // into the implementation files. Several functions had to be uninlined. 827 // Also corrected position of #include, etc. 828 // 829 // Revision 1.1.1.1 2006/05/30 11:39:37 cocoa 830 // Imported files 831 // 832 // Revision 1.7 2006/05/29 16:22:37 cocoa 833 // Third time lucky??? 834 // Added myIsInteger member function to all rings (NYI for RingFloat). 835 // 836 // Revision 1.6 2006/05/12 16:10:58 cocoa 837 // Added OpenMathFwd.H, and tidied OpenMath.H. 838 // Many consequential but trivial changes. 839 // 840 // Revision 1.5 2006/04/21 15:01:36 cocoa 841 // Changed default implementation of RingBase::myGcd -- it now gives a SERIOUS 842 // error. All fields must now handle a call to gcd explicitly: they can use 843 // the new myGcdInField function. It's now cleaner than it was. 844 // 845 // Revision 1.4 2006/03/15 18:09:31 cocoa 846 // Changed names of member functions which print out their object 847 // into myOutputSelf -- hope this will appease the Intel C++ compiler. 848 // 849 // Revision 1.3 2006/03/14 15:01:49 cocoa 850 // Improved the implementation of ring member fns for computing powers. 851 // Should keep Intel C++ compiler quieter too. 852 // 853 // Revision 1.2 2006/03/12 21:28:33 cocoa 854 // Major check in after many changes 855 // 856 // Revision 1.1.1.1 2005/10/17 10:46:54 cocoa 857 // Imported files 858 // 859 // Revision 1.3 2005/10/14 15:25:07 cocoa 860 // Major tidying and cleaning to small prime finite fields. 861 // Several consequential changes. Improved their documentation. 862 // 863 // Added Makefile and script to include/CoCoA/ directory to 864 // keep library.H up to date. 865 // 866 // Revision 1.2 2005/10/12 15:52:09 cocoa 867 // Completed test-RingFp1 and corrected/cleaned the SmallFp* 868 // and RingFp* files. 869 // 870 // Some minor tidying elsewhere. 871 // 872 // Revision 1.1 2005/10/11 16:37:30 cocoa 873 // Added new small prime finite field class (see RingFpDouble). 874 // 875 // Cleaned makefiles and configuration script. 876 // 877 // Tidied PPMonoid code (to eliminate compiler warnings). 878 // 879 // Fixed bug in RingFloat::myIsInteger. 880 // 881