1 // Copyright (c) 2001-2017 John Abbott and Anna M. Bigatti 2 // Author: 2005-2010 John Abbott 3 4 // This file is part of the source of CoCoALib, the CoCoA Library. 5 6 // CoCoALib is free software: you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation, either version 3 of the License, or 9 // (at your option) any later version. 10 11 // CoCoALib is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // You should have received a copy of the GNU General Public License 17 // along with CoCoALib. If not, see <http://www.gnu.org/licenses/>. 18 19 20 // Implementation of classes PPMonoidOvImpl 21 22 #include "CoCoA/PPMonoidOv.H" 23 24 #include "CoCoA/BigInt.H" 25 #include "CoCoA/DivMask.H" 26 #include "CoCoA/MemPool.H" 27 #include "CoCoA/OrdvArith.H" 28 #include "CoCoA/PPMonoid.H" 29 #include "CoCoA/assert.H" 30 #include "CoCoA/convert.H" 31 #include "CoCoA/error.H" 32 #include "CoCoA/symbol.H" 33 #include "CoCoA/utils.H" 34 //#include "CoCoA/VectorOps.H" // for debugging only 35 36 #include <algorithm> 37 using std::min; 38 using std::max; 39 #include <iostream> 40 using std::ostream; 41 #include<limits> 42 using std::numeric_limits; 43 #include <memory> 44 using std::unique_ptr; 45 #include <vector> 46 using std::vector; 47 48 49 namespace CoCoA 50 { 51 52 class PPMonoidOvImpl: public PPMonoidBase 53 { 54 typedef PPMonoidElemRawPtr RawPtr; // just to save typing 55 typedef PPMonoidElemConstRawPtr ConstRawPtr; // just to save typing 56 typedef OrdvArith::OrdvElem OrdvElem; // just to save typing 57 58 static const unsigned long ourMaxExp; // defined below, it is just numeric_limits<SmallExponent_t>::max() 59 60 public: 61 PPMonoidOvImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord); 62 ~PPMonoidOvImpl(); 63 private: // disable copy ctor and assignment 64 PPMonoidOvImpl(const PPMonoidOvImpl& copy); // NEVER DEFINED -- copy ctor disabled 65 PPMonoidOvImpl& operator=(const PPMonoidOvImpl& rhs); // NEVER DEFINED -- assignment disabled 66 67 public: 68 void contents() const; // FOR DEBUGGING ONLY 69 70 const std::vector<PPMonoidElem>& myIndets() const; ///< std::vector whose n-th entry is n-th indet as PPMonoidElem 71 72 // The functions below are operations on power products owned by PPMonoidOvImpl 73 const PPMonoidElem& myOne() const; 74 using PPMonoidBase::myNew; // disable warnings of overloading 75 PPMonoidElemRawPtr myNew() const; ///< ctor from nothing 76 PPMonoidElemRawPtr myNew(PPMonoidElemConstRawPtr rawpp) const; ///< ctor by assuming ownership 77 PPMonoidElemRawPtr myNew(const std::vector<long>& expv) const; ///< ctor from exp vector 78 //NYI PPMonoidElemRawPtr myNew(const std::vector<BigInt>& EXPV) const;///< ctor from exp vector 79 void myDelete(RawPtr rawpp) const; ///< dtor, frees pp 80 void mySwap(RawPtr rawpp1, RawPtr rawpp2) const; ///< swap(pp1, pp2); 81 void myAssignOne(RawPtr rawpp) const; ///< pp = 1 82 void myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const; ///< p = pp1 83 void myAssign(RawPtr rawpp, const std::vector<long>& expv) const; ///< pp = expv (assign from exp vector) 84 85 void myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1*pp2 86 using PPMonoidBase::myMulIndetPower; // disable warnings of overloading 87 void myMulIndetPower(RawPtr rawpp, long indet, long exp) const; ///< pp *= indet^exp, assumes exp >= 0 88 void myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1/pp2 89 void myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1/gcd(pp1,pp2) 90 void myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = gcd(pp1,pp2) 91 void myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = lcm(pp1,pp2) 92 void myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const; ///< pp = radical(pp1) 93 void myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long exp) const; ///< pp = pp1^exp, assumes exp >= 0 94 void myPowerOverflowCheck(ConstRawPtr rawpp1, long exp) const; ///< throw if pp1^exp would overflow, assumes exp >= 0 95 96 bool myIsOne(ConstRawPtr rawpp) const; ///< is pp = 1? 97 bool myIsIndet(long& index, ConstRawPtr rawpp) const; ///< true iff pp is an indet 98 bool myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< are pp1 & pp2 coprime? 99 bool myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< is pp1 equal to pp2? 100 bool myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< does pp2 divide pp1? 101 bool myIsSqFree(ConstRawPtr rawpp) const; ///< is pp equal to its radical? 102 103 int myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< -1,0,1 as pp1 < = > pp2 104 long myStdDeg(ConstRawPtr rawpp) const; ///< standard degree of pp 105 void myWDeg(degree& d, ConstRawPtr rawpp) const; ///< d = grading(pp) 106 int myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< <0, =0, >0 as wdeg(pp1) < = > wdeg(pp2) 107 int myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long) const; ///< as myCmpWDeg wrt the first weights 108 long myExponent(ConstRawPtr rawpp, long indet) const; ///< exponent of indet in pp 109 void myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const; ///< EXP = exponent of indet in pp 110 void myExponents(std::vector<long>& expv, ConstRawPtr rawpp) const; ///< expv[i] = exponent(pp,i) 111 void myBigExponents(std::vector<BigInt>& v, ConstRawPtr rawpp) const; ///< get exponents, SHOULD BE myExponents ??? 112 void myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const; ///< v[i] = true if i-th indet has exponent != 0 113 void myOutputSelf(std::ostream& out) const; ///< out << PPM 114 // INHERITED DEFINITION of virtual void myOutput(std::ostream& out, ConstRawPtr rawpp) const; 115 void myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const; ///< print pp in debugging format??? 116 117 118 private: // auxiliary functions 119 OrdvElem* myOrdv(RawPtr) const; 120 const OrdvElem* myOrdv(ConstRawPtr) const; 121 122 void myComputeDivMask(DivMask& dm, const DivMaskRule& DivMaskImpl, ConstRawPtr rawpp) const; ///< used by PPWithMask 123 void myComputeExpv(std::vector<long>& expv, RawPtr rawpp) const; 124 bool myCheckExponents(const std::vector<long>& expv) const; 125 //??? void mySetExpv(RawPtr, const std::vector<long>& expv) const; 126 127 private: // data members 128 ///@name Class members 129 //@{ 130 OrdvArith::reference myOrdvArith; //??? should be const 131 const long myEntrySize; 132 mutable vector<long> myExpv1; // buffer space 133 mutable vector<long> myExpv2; // buffer space 134 mutable MemPool myMemMgr; // IMPORTANT: this must come *before* myIndetVector and myOnePtr. 135 //??? std::vector<long> myDelta; 136 vector<PPMonoidElem> myIndetVector; ///< the indets as PPMonoidElems 137 unique_ptr<PPMonoidElem> myOnePtr; 138 //@} 139 }; 140 141 // static constant value 142 const unsigned long PPMonoidOvImpl::ourMaxExp = numeric_limits<SmallExponent_t>::max(); 143 144 // File local inline functions 145 myOrdv(RawPtr rawpp)146 inline PPMonoidOvImpl::OrdvElem* PPMonoidOvImpl::myOrdv(RawPtr rawpp) const 147 { 148 return static_cast<OrdvElem*>(rawpp.myRawPtr()); 149 150 } 151 myOrdv(ConstRawPtr rawpp)152 inline const PPMonoidOvImpl::OrdvElem* PPMonoidOvImpl::myOrdv(ConstRawPtr rawpp) const 153 { 154 return static_cast<const OrdvElem*>(rawpp.myRawPtr()); 155 } 156 157 myCheckExponents(const std::vector<long> & expv)158 bool PPMonoidOvImpl::myCheckExponents(const std::vector<long>& expv) const 159 { 160 // Check len(expv) == myNumIndets. 161 // Check exps are non-neg and not too big. 162 if (len(expv) != myNumIndets) return false; 163 for (long i=0; i < myNumIndets; ++i) 164 if (expv[i] < 0 || static_cast<unsigned long>(expv[i]) > numeric_limits<SmallExponent_t>::max()) return false; 165 return true; 166 } 167 168 169 //---- Constructors & destructor ----// 170 PPMonoidOvImpl(const std::vector<symbol> & IndetNames,const PPOrdering & ord)171 PPMonoidOvImpl::PPMonoidOvImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord): 172 PPMonoidBase(ord, IndetNames), 173 myOrdvArith(NewOrdvArith(ord)), 174 myEntrySize(sizeof(OrdvElem)*OrdvWords(myOrdvArith)), 175 myExpv1(myNumIndets), 176 myExpv2(myNumIndets), 177 myMemMgr(myEntrySize, "PPMonoidOvImpl.myMemMgr"), 178 myIndetVector() 179 { 180 // std::cout << "------PPMonoidOvImpl: called NewOrdvArith" << std::endl; 181 myRefCountInc(); // this is needed for exception cleanliness, in case one of the lines below throws 182 myOnePtr.reset(new PPMonoidElem(PPMonoid(this))); 183 myIndetVector.reserve(myNumIndets); 184 { 185 // IMPORTANT: this block destroys pp *before* the call to myRefCountZero. 186 PPMonoidElem pp(PPMonoid(this)); 187 vector<long> expv(myNumIndets); 188 for (long i=0; i < myNumIndets; ++i) 189 { 190 expv[i] = 1; 191 myAssign(raw(pp), expv); 192 myIndetVector.push_back(pp); 193 expv[i] = 0; 194 } 195 } 196 myRefCountZero(); 197 } 198 199 ~PPMonoidOvImpl()200 PPMonoidOvImpl::~PPMonoidOvImpl() 201 {} 202 203 204 // mySmartPtr is private 205 // const OrdvArith::reference& OrdvA(const PPMonoid& PPM) 206 // { 207 // if (!IsPPMonoidOv(PPM)) 208 // CoCoA_ERROR("PPM must be PPMonoidOvImpl", OrdvA); 209 // return dynamic_cast<const PPMonoidOvImpl*>(PPM.mySmartPtr()).myOrdvArith; 210 // } 211 212 213 ///////////////////////////////////////////////////////////////////////////// 214 215 myIndets()216 const std::vector<PPMonoidElem>& PPMonoidOvImpl::myIndets() const 217 { 218 return myIndetVector; 219 } 220 221 myOne()222 const PPMonoidElem& PPMonoidOvImpl::myOne() const 223 { 224 return *myOnePtr; 225 } 226 227 myNew()228 PPMonoidElemRawPtr PPMonoidOvImpl::myNew() const 229 { 230 PPMonoidElemRawPtr rawpp(myMemMgr.alloc()); 231 myAssignOne(rawpp); // cannot throw 232 return rawpp; 233 } 234 myNew(PPMonoidElemConstRawPtr rawcopypp)235 PPMonoidElemRawPtr PPMonoidOvImpl::myNew(PPMonoidElemConstRawPtr rawcopypp) const 236 { 237 PPMonoidElemRawPtr rawpp(myMemMgr.alloc()); 238 myAssign(rawpp, rawcopypp); // cannot throw 239 return rawpp; 240 } 241 242 myNew(const std::vector<long> & expv)243 PPMonoidElemRawPtr PPMonoidOvImpl::myNew(const std::vector<long>& expv) const 244 { 245 CoCoA_ASSERT(myCheckExponents(expv)); 246 PPMonoidElemRawPtr rawpp(myMemMgr.alloc()); 247 myAssign(rawpp, expv); // cannot throw 248 return rawpp; 249 } 250 251 myAssignOne(RawPtr rawpp)252 void PPMonoidOvImpl::myAssignOne(RawPtr rawpp) const 253 { 254 myOrdvArith->myAssignZero(myOrdv(rawpp)); 255 } 256 257 myAssign(RawPtr rawpp,ConstRawPtr rawpp1)258 void PPMonoidOvImpl::myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const 259 { 260 if (rawpp == rawpp1) return; 261 myOrdvArith->myAssign(myOrdv(rawpp), myOrdv(rawpp1)); 262 } 263 myAssign(RawPtr rawpp,const vector<long> & expv)264 void PPMonoidOvImpl::myAssign(RawPtr rawpp, const vector<long>& expv) const 265 { 266 CoCoA_ASSERT(myCheckExponents(expv)); 267 myOrdvArith->myAssignFromExpv(myOrdv(rawpp), expv); 268 } 269 270 myDelete(RawPtr rawpp)271 void PPMonoidOvImpl::myDelete(RawPtr rawpp) const 272 { 273 myMemMgr.free(rawpp.myRawPtr()); 274 } 275 276 mySwap(RawPtr rawpp1,RawPtr rawpp2)277 void PPMonoidOvImpl::mySwap(RawPtr rawpp1, RawPtr rawpp2) const 278 { 279 if (rawpp1 == rawpp2) return; 280 myOrdvArith->mySwap(myOrdv(rawpp1), myOrdv(rawpp2)); 281 } 282 283 myMul(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)284 void PPMonoidOvImpl::myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 285 { 286 myOrdvArith->myMul(myOrdv(rawpp), myOrdv(rawpp1), myOrdv(rawpp2)); 287 } 288 289 myMulIndetPower(RawPtr rawpp,long indet,long exp)290 void PPMonoidOvImpl::myMulIndetPower(RawPtr rawpp, long indet, long exp) const // assumes exp >= 0 291 { 292 CoCoA_ASSERT(exp >= 0); 293 CoCoA_ASSERT(0 <= indet && indet < myNumIndets); 294 CoCoA_ASSERT("Exponent Overflow" && ourMaxExp - myExponent(rawpp, indet) >= static_cast<unsigned long>(exp)); 295 myOrdvArith->myMulIndetPower(myOrdv(rawpp), indet, exp); 296 } 297 298 myDiv(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)299 void PPMonoidOvImpl::myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 300 { 301 myOrdvArith->myDiv(myOrdv(rawpp), myOrdv(rawpp1), myOrdv(rawpp2)); 302 } 303 304 myColon(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)305 void PPMonoidOvImpl::myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 306 { 307 #ifdef CoCoA_THREADSAFE_HACK 308 vector<long> myExpv1(myNumIndets); 309 vector<long> myExpv2(myNumIndets); 310 #endif 311 myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp1)); 312 myOrdvArith->myComputeExpv(myExpv2, myOrdv(rawpp2)); 313 314 for (long i = 0; i < myNumIndets; ++i) 315 { 316 if (myExpv1[i] > myExpv2[i]) 317 myExpv1[i] -= myExpv2[i]; 318 else 319 myExpv1[i] = 0; 320 } 321 myOrdvArith->myAssignFromExpv(myOrdv(rawpp), myExpv1); 322 } 323 324 myGcd(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)325 void PPMonoidOvImpl::myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 326 { 327 #ifdef CoCoA_THREADSAFE_HACK 328 vector<long> myExpv1(myNumIndets); 329 vector<long> myExpv2(myNumIndets); 330 #endif 331 myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp1)); 332 myOrdvArith->myComputeExpv(myExpv2, myOrdv(rawpp2)); 333 334 for (long i = 0; i < myNumIndets; ++i) 335 myExpv1[i] = min(myExpv1[i], myExpv2[i]); 336 337 myOrdvArith->myAssignFromExpv(myOrdv(rawpp), myExpv1); 338 } 339 340 myLcm(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)341 void PPMonoidOvImpl::myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 342 { 343 #ifdef CoCoA_THREADSAFE_HACK 344 vector<long> myExpv1(myNumIndets); 345 vector<long> myExpv2(myNumIndets); 346 #endif 347 myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp1)); 348 myOrdvArith->myComputeExpv(myExpv2, myOrdv(rawpp2)); 349 350 for (long i = 0; i < myNumIndets; ++i) 351 myExpv1[i] = max(myExpv1[i], myExpv2[i]); 352 353 myOrdvArith->myAssignFromExpv(myOrdv(rawpp), myExpv1); 354 } 355 356 myRadical(RawPtr rawpp,ConstRawPtr rawpp1)357 void PPMonoidOvImpl::myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const 358 { 359 #ifdef CoCoA_THREADSAFE_HACK 360 vector<long> myExpv1(myNumIndets); 361 #endif 362 myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp1)); 363 364 for (long i = 0; i < myNumIndets; ++i) 365 myExpv1[i] = (myExpv1[i] > 0); 366 367 myOrdvArith->myAssignFromExpv(myOrdv(rawpp), myExpv1); 368 } 369 370 myPowerSmallExp(RawPtr rawpp,ConstRawPtr rawpp1,long exp)371 void PPMonoidOvImpl::myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long exp) const // assumes exp >= 0 372 { 373 CoCoA_ASSERT(exp >= 0); 374 #ifdef CoCoA_DEBUG 375 myPowerOverflowCheck(rawpp1, exp); 376 #endif 377 myOrdvArith->myPower(myOrdv(rawpp), myOrdv(rawpp1), exp); 378 } 379 380 myPowerOverflowCheck(ConstRawPtr rawpp,long exp)381 void PPMonoidOvImpl::myPowerOverflowCheck(ConstRawPtr rawpp, long exp) const 382 { 383 CoCoA_ASSERT(exp >= 0); 384 myOrdvArith->myPowerOverflowCheck(myOrdv(rawpp), exp); 385 } 386 387 myIsOne(ConstRawPtr rawpp)388 bool PPMonoidOvImpl::myIsOne(ConstRawPtr rawpp) const 389 { 390 return myOrdvArith->myIsZero(myOrdv(rawpp)); 391 } 392 393 myIsIndet(long & index,ConstRawPtr rawpp)394 bool PPMonoidOvImpl::myIsIndet(long& index, ConstRawPtr rawpp) const 395 { 396 return myOrdvArith->myIsIndet(index, myOrdv(rawpp)); 397 } 398 399 myIsCoprime(ConstRawPtr rawpp1,ConstRawPtr rawpp2)400 bool PPMonoidOvImpl::myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 401 { 402 #ifdef CoCoA_THREADSAFE_HACK 403 vector<long> myExpv1(myNumIndets); 404 vector<long> myExpv2(myNumIndets); 405 #endif 406 myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp1)); 407 myOrdvArith->myComputeExpv(myExpv2, myOrdv(rawpp2)); 408 409 for (long i = 0; i < myNumIndets; ++i) 410 if (myExpv1[i] != 0 && myExpv2[i] != 0) return false; 411 412 return true; 413 } 414 415 myIsEqual(ConstRawPtr rawpp1,ConstRawPtr rawpp2)416 bool PPMonoidOvImpl::myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 417 { 418 return myOrdvArith->myCmp(myOrdv(rawpp1), myOrdv(rawpp2))==0; 419 } 420 421 myIsDivisible(ConstRawPtr rawpp1,ConstRawPtr rawpp2)422 bool PPMonoidOvImpl::myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 423 { 424 #ifdef CoCoA_THREADSAFE_HACK 425 vector<long> myExpv1(myNumIndets); 426 vector<long> myExpv2(myNumIndets); 427 #endif 428 myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp1)); 429 myOrdvArith->myComputeExpv(myExpv2, myOrdv(rawpp2)); 430 431 for (long i = 0; i < myNumIndets; ++i) 432 if (myExpv1[i] < myExpv2[i]) return false; 433 434 return true; 435 } 436 437 myIsSqFree(ConstRawPtr rawpp)438 bool PPMonoidOvImpl::myIsSqFree(ConstRawPtr rawpp) const 439 { 440 #ifdef CoCoA_THREADSAFE_HACK 441 vector<long> myExpv1(myNumIndets); 442 #endif 443 myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp)); 444 for (long i = 0; i < myNumIndets; ++i) 445 if (myExpv1[i] > 1) return false; 446 return true; 447 } 448 449 myCmp(ConstRawPtr rawpp1,ConstRawPtr rawpp2)450 int PPMonoidOvImpl::myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 451 { 452 return myOrdvArith->myCmp(myOrdv(rawpp1), myOrdv(rawpp2)); 453 } 454 455 456 // // should potentially skip the first few packed ordv entries??? 457 // int PPMonoidOvImpl::myHomogCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 458 // { 459 // return myOrdvArith->myCmp(myOrdv(rawpp1), myOrdv(rawpp2)); 460 // } 461 462 myStdDeg(ConstRawPtr rawpp)463 long PPMonoidOvImpl::myStdDeg(ConstRawPtr rawpp) const 464 { 465 return myOrdvArith->myStdDeg(myOrdv(rawpp)); 466 } 467 468 myWDeg(degree & d,ConstRawPtr rawpp)469 void PPMonoidOvImpl::myWDeg(degree& d, ConstRawPtr rawpp) const 470 { 471 myOrdvArith->myWDeg(d, myOrdv(rawpp)); 472 } 473 474 myCmpWDeg(ConstRawPtr rawpp1,ConstRawPtr rawpp2)475 int PPMonoidOvImpl::myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 476 { 477 return myOrdvArith->myCmpWDeg(myOrdv(rawpp1), myOrdv(rawpp2)); 478 } 479 480 myCmpWDegPartial(ConstRawPtr rawpp1,ConstRawPtr rawpp2,long i)481 int PPMonoidOvImpl::myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long i) const 482 { 483 return myOrdvArith->myCmpWDegPartial(myOrdv(rawpp1), myOrdv(rawpp2), i); 484 } 485 486 myExponent(ConstRawPtr rawpp,long indet)487 long PPMonoidOvImpl::myExponent(ConstRawPtr rawpp, long indet) const 488 { 489 CoCoA_ASSERT(0 <= indet && indet < myNumIndets); 490 return myOrdvArith->myExponent(myOrdv(rawpp), indet); 491 } 492 myBigExponent(BigInt & EXP,ConstRawPtr rawpp,long indet)493 void PPMonoidOvImpl::myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const 494 { 495 CoCoA_ASSERT(0 <= indet && indet < myNumIndets); 496 EXP = myExponent(rawpp, indet); 497 } 498 499 myExponents(std::vector<long> & expv,ConstRawPtr rawpp)500 void PPMonoidOvImpl::myExponents(std::vector<long>& expv, ConstRawPtr rawpp) const 501 { 502 CoCoA_ASSERT(len(expv) == myNumIndets); 503 myOrdvArith->myComputeExpv(expv, myOrdv(rawpp)); 504 } 505 506 myBigExponents(std::vector<BigInt> & expv,ConstRawPtr rawpp)507 void PPMonoidOvImpl::myBigExponents(std::vector<BigInt>& expv, ConstRawPtr rawpp) const 508 { 509 CoCoA_ASSERT(len(expv) == myNumIndets); 510 std::vector<long> v(myNumIndets); 511 myOrdvArith->myComputeExpv(v, myOrdv(rawpp)); 512 for (long i=0; i < myNumIndets; ++i) expv[i] = v[i]; 513 } 514 515 myIndetsIn(std::vector<bool> & v,ConstRawPtr rawpp)516 void PPMonoidOvImpl::myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const 517 { 518 CoCoA_ASSERT(len(v) == myNumIndets); 519 // SLUG SLUG SLUG 520 vector<long> expv(myNumIndets); 521 myOrdvArith->myComputeExpv(expv, myOrdv(rawpp)); 522 for (int i=0; i < myNumIndets; ++i) 523 if (expv[i] != 0) v[i] = true; 524 } 525 526 myComputeDivMask(DivMask & dm,const DivMaskRule & DivMaskImpl,ConstRawPtr rawpp)527 void PPMonoidOvImpl::myComputeDivMask(DivMask& dm, const DivMaskRule& DivMaskImpl, ConstRawPtr rawpp) const 528 { 529 #ifdef CoCoA_THREADSAFE_HACK 530 vector<long> myExpv1(myNumIndets); 531 #endif 532 myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp)); 533 vector<SmallExponent_t> expv(myNumIndets); 534 for (long i=0; i < myNumIndets; ++i) 535 expv[i] = static_cast<SmallExponent_t>(myExpv1[i]); // no problem as exponent must be non-neg. 536 DivMaskImpl->myAssignFromExpv(dm, &expv[0], myNumIndets); 537 } 538 539 myOutputSelf(std::ostream & out)540 void PPMonoidOvImpl::myOutputSelf(std::ostream& out) const 541 { 542 if (!out) return; // short-cut for bad ostreams 543 out << "PPMonoidOv(" << myNumIndets << ", " << myOrd << ")"; 544 } 545 546 myDebugPrint(std::ostream & out,ConstRawPtr rawpp)547 void PPMonoidOvImpl::myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const 548 { 549 if (!out) return; // short-cut for bad ostreams 550 551 #ifdef CoCoA_THREADSAFE_HACK 552 vector<long> myExpv1(myNumIndets); 553 #endif 554 myOrdvArith->myComputeExpv(myExpv1, myOrdv(rawpp)); 555 out << "DEBUG PP: myNumIndets=" << myNumIndets << ", exps=["; 556 for (long i=0; i < myNumIndets; ++i) 557 out << myExpv1[i] << " "; 558 out << "]" << std::endl; 559 } 560 561 NewPPMonoidOv(const std::vector<symbol> & IndetNames,const PPOrdering & ord)562 PPMonoid NewPPMonoidOv(const std::vector<symbol>& IndetNames, const PPOrdering& ord) 563 { 564 // Sanity check on the indet names given. 565 const long nvars = NumIndets(ord); 566 567 if (len(IndetNames) != nvars) 568 CoCoA_ERROR(ERR::BadNumIndets, "NewPPMonoidOv(IndetNames,ord)"); 569 if (!AreDistinct(IndetNames)) 570 CoCoA_ERROR(ERR::BadIndetNames, "NewPPMonoidOv(IndetNames,ord)"); 571 if (!AreArityConsistent(IndetNames)) 572 CoCoA_ERROR(ERR::BadIndetNames, "NewPPMonoidOv(IndetNames,ord)"); 573 574 return PPMonoid(new PPMonoidOvImpl(IndetNames, ord)); 575 } 576 NewPPMonoidOv(const std::vector<symbol> & IndetNames,const PPOrderingCtor & OrdCtor)577 PPMonoid NewPPMonoidOv(const std::vector<symbol>& IndetNames, const PPOrderingCtor& OrdCtor) 578 { 579 return NewPPMonoidOv(IndetNames, OrdCtor(len(IndetNames))); 580 } 581 582 IsPPMonoidOv(const PPMonoid & PPM)583 bool IsPPMonoidOv(const PPMonoid& PPM) 584 { 585 return dynamic_cast<const PPMonoidOvImpl*>(PPM.operator->()) != nullptr; 586 } 587 588 } // end of namespace CoCoA 589 590 591 // RCS header/log in the next few lines 592 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/PPMonoidOv.C,v 1.38 2020/02/11 16:56:41 abbott Exp $ 593 // $Log: PPMonoidOv.C,v $ 594 // Revision 1.38 2020/02/11 16:56:41 abbott 595 // Summary: Corrected last update (see redmine 969) 596 // 597 // Revision 1.37 2020/02/11 16:12:18 abbott 598 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969 599 // 600 // Revision 1.36 2019/10/15 11:54:08 abbott 601 // Summary: Changed 0 into nullptr (where appropriate) 602 // 603 // Revision 1.35 2019/03/04 10:32:03 abbott 604 // Summary: Changed auto_ptr into unqiue_ptr 605 // 606 // Revision 1.34 2018/05/17 15:38:11 bigatti 607 // -- renamed VectorOperations --> VectorOps 608 // 609 // Revision 1.33 2018/04/20 16:15:31 bigatti 610 // -- minor 611 // 612 // Revision 1.32 2017/12/01 17:29:21 bigatti 613 // // -- updated Copyright line 614 // // -- removed doxygen initial comment 615 // // -- some commented out debugging info 616 // 617 // Revision 1.31 2017/04/18 15:52:27 abbott 618 // Summary: Corrected an ifdef directive 619 // 620 // Revision 1.30 2017/04/18 12:50:06 abbott 621 // Summary: Corrected ifdef use of CoCoA_THREADSAFE_HACK and CoCoA_DEBUG 622 // 623 // Revision 1.29 2016/11/03 12:25:25 abbott 624 // Summary: Changed IsRadical (for PPMonoidElem) into IsSqFree 625 // 626 // Revision 1.28 2015/12/01 13:11:01 abbott 627 // Summary: Changed mem fn PPOrderingCtor::myCtor into operator(); also for ModuleOrderingCtor; see issue 829 628 // 629 // Revision 1.27 2015/11/30 21:53:55 abbott 630 // Summary: Major update to matrices for orderings (not yet complete, some tests fail) 631 // 632 // Revision 1.26 2015/06/30 12:55:00 abbott 633 // Summary: Added new fn myIndetsIn 634 // Author: JAA 635 // 636 // Revision 1.25 2015/04/16 16:36:33 abbott 637 // Summary: Cleaned impls of myPowerOverflowCheck 638 // Author: JAA 639 // 640 // Revision 1.24 2015/04/13 14:42:08 abbott 641 // Summary: Added myPowerOverflowCheck (1st version) 642 // Author: JAA 643 // 644 // Revision 1.23 2014/07/03 15:36:35 abbott 645 // Summary: Cleaned up impl of PPMonoids: moved myIndetSymbols & myNumIndets to base class 646 // Author: JAA 647 // 648 // Revision 1.22 2014/05/14 15:57:15 bigatti 649 // -- added "using" for clang with superpedantic flag 650 // 651 // Revision 1.21 2014/01/30 17:28:42 abbott 652 // Summary: Added new fn IsPPMonoidOv 653 // Author: JAA 654 // 655 // Revision 1.20 2014/01/28 16:46:21 abbott 656 // Made code threadsafe; also some cleaning (buffer expv no longer needed). 657 // 658 // Revision 1.19 2012/01/26 16:50:55 bigatti 659 // -- changed back_inserter into insert 660 // 661 // Revision 1.18 2011/08/14 15:52:17 abbott 662 // Changed ZZ into BigInt (phase 1: just the library sources). 663 // 664 // Revision 1.17 2011/05/03 09:56:16 abbott 665 // Introduced static data member "ourMaxExp" to avoid compiler complaints 666 // (it does improve readability too). 667 // 668 // Revision 1.16 2011/03/22 22:46:01 abbott 669 // Corrected wrong static_cast in a CoCoA_ASSERT. 670 // 671 // Revision 1.15 2011/03/10 17:28:28 bigatti 672 // -- changed unsigned long into long in some CoCoA_ASSERT 673 // -- removed assert in myCmpWDegPartial (done in OrdvArith) 674 // 675 // Revision 1.14 2011/03/10 16:39:34 abbott 676 // Replaced (very many) size_t by long in function interfaces (for rings, 677 // PPMonoids and modules). Also replaced most size_t inside fn defns. 678 // 679 // Revision 1.13 2010/11/30 11:18:11 bigatti 680 // -- renamed IndetName --> IndetSymbol 681 // 682 // Revision 1.12 2010/11/05 16:21:08 bigatti 683 // -- added ZZExponents 684 // 685 // Revision 1.11 2010/10/06 14:10:24 abbott 686 // Added increments to the ref count in ring and PPMonoid ctors to make 687 // them exception safe. 688 // 689 // Revision 1.10 2010/02/03 16:13:52 abbott 690 // Added new single word tags for specifying the ordering in PPMonoid 691 // pseudo-ctors. 692 // 693 // Revision 1.9 2010/02/02 16:44:31 abbott 694 // Added radical & IsRadical (via mem fns myRadical & myIsRadical) 695 // for PPMonoidElems. 696 // 697 // Revision 1.8 2009/09/22 14:01:33 bigatti 698 // -- added myCmpWDegPartial (ugly name, I know....) 699 // -- cleaned up and realigned code in PPMonoid*.C files 700 // 701 // Revision 1.7 2007/12/05 11:06:24 bigatti 702 // -- changed "size_t StdDeg/myStdDeg(f)" into "long" (and related functions) 703 // -- changed "log/myLog(f, i)" into "MaxExponent/myMaxExponent(f, i)" 704 // -- fixed bug in "IsOne(ideal)" in SparsePolyRing.C 705 // 706 // Revision 1.6 2007/12/04 14:27:06 bigatti 707 // -- changed "log(pp, i)" into "exponent(pp, i)" 708 // 709 // Revision 1.5 2007/10/30 17:14:07 abbott 710 // Changed licence from GPL-2 only to GPL-3 or later. 711 // New version for such an important change. 712 // 713 // Revision 1.4 2007/05/31 14:54:31 bigatti 714 // -- now using AreDistinct and AreArityConsistent for sanity check on 715 // indet names 716 // 717 // Revision 1.2 2007/05/03 10:35:23 abbott 718 // Added new PPMonoidEvZZ with (virtually) unlimited exponents. 719 // Modified test-PPMonoid1.C accordingly. 720 // Added warning in doc about silent/unchecked exponent overflow in other 721 // PPMonoids. 722 // 723 // Revision 1.1.1.1 2007/03/09 15:16:11 abbott 724 // Imported files 725 // 726 // Revision 1.11 2007/03/08 18:22:29 cocoa 727 // Just whitespace cleaning. 728 // 729 // Revision 1.10 2007/03/08 17:43:11 cocoa 730 // Swapped order of args to the NewPPMonoid pseudo ctors. 731 // 732 // Revision 1.9 2007/03/08 11:07:12 cocoa 733 // Made pseudo ctors for polynomial rings more uniform. This allowed me to 734 // remove an include of CoCoA/symbol.H from the RingDistrM*.H files, but then 735 // I had to put the include in several .C files. 736 // 737 // Revision 1.8 2006/12/06 17:35:58 cocoa 738 // -- style: RawPtr args are now called "raw.." 739 // 740 // Revision 1.7 2006/11/24 17:04:32 cocoa 741 // -- reorganized includes of header files 742 // 743 // Revision 1.6 2006/11/23 17:39:26 cocoa 744 // -- added #include 745 // 746 // Revision 1.5 2006/11/16 11:27:20 cocoa 747 // -- reinserted myRefCountZero(): sometimes really necessary, in general safe 748 // 749 // Revision 1.4 2006/11/14 17:29:20 cocoa 750 // -- commented out myRefCountZero() (not necessary???) 751 // 752 // Revision 1.3 2006/10/06 14:04:14 cocoa 753 // Corrected position of #ifndef in header files. 754 // Separated CoCoA_ASSERT into assert.H from config.H; 755 // many minor consequential changes (have to #include assert.H). 756 // A little tidying of #include directives (esp. in Max's code). 757 // 758 // Revision 1.2 2006/08/07 21:23:25 cocoa 759 // Removed almost all publicly visible references to SmallExponent_t; 760 // changed to long in all PPMonoid functions and SparsePolyRing functions. 761 // DivMask remains to sorted out. 762 // 763 // Revision 1.1.1.1 2006/05/30 11:39:37 cocoa 764 // Imported files 765 // 766 // Revision 1.6 2006/03/15 18:09:31 cocoa 767 // Changed names of member functions which print out their object 768 // into myOutputSelf -- hope this will appease the Intel C++ compiler. 769 // 770 // Revision 1.5 2006/03/14 17:21:18 cocoa 771 // Moved concrete PPMonoid impls entirely into their respective .C files. 772 // Now the corresponding .H files are very compact. 773 // 774 // Revision 1.4 2006/03/12 21:28:33 cocoa 775 // Major check in after many changes 776 // 777 // Revision 1.3 2006/02/20 22:41:20 cocoa 778 // All forms of the log function for power products now return SmallExponent_t 779 // (instead of int). exponents now resizes the vector rather than requiring 780 // the user to pass in the correct size. 781 // 782 // Revision 1.2 2006/01/17 10:23:08 cocoa 783 // Updated DivMask; many consequential changes. 784 // A few other minor fixes. 785 // 786 // Revision 1.1.1.1 2005/10/17 10:46:54 cocoa 787 // Imported files 788 // 789 // Revision 1.7 2005/10/11 16:37:30 cocoa 790 // Added new small prime finite field class (see RingFpDouble). 791 // 792 // Cleaned makefiles and configuration script. 793 // 794 // Tidied PPMonoid code (to eliminate compiler warnings). 795 // 796 // Fixed bug in RingFloat::myIsInteger. 797 // 798 // Revision 1.6 2005/08/08 16:36:32 cocoa 799 // Just checking in before going on holiday. 800 // Don't really recall what changes have been made. 801 // Added IsIndet function for RingElem, PPMonoidElem, 802 // and a member function of OrdvArith. 803 // Improved the way failed assertions are handled. 804 // 805 // Revision 1.5 2005/07/19 15:30:20 cocoa 806 // A first attempt at iterators over sparse polynomials. 807 // Main additions are to SparsePolyRing, DistrMPoly*. 808 // Some consequential changes to PPMonoid*. 809 // 810 // Revision 1.4 2005/07/08 15:09:28 cocoa 811 // Added new symbol class (to represent names of indets). 812 // Integrated the new class into concrete polynomial rings 813 // and PPMonoid -- many consequential changes. 814 // Change ctors for the "inline" sparse poly rings: they no 815 // longer expect a PPMonoid, but build their own instead 816 // (has to be a PPMonoidOv). 817 // 818 // Revision 1.3 2005/07/01 16:08:15 cocoa 819 // Friday check-in. Major change to structure under PolyRing: 820 // now SparsePolyRing and DUPolyRing are separated (in preparation 821 // for implementing iterators). 822 // 823 // A number of other relatively minor changes had to be chased through 824 // (e.g. IndetPower). 825 // 826 // Revision 1.2 2005/06/23 15:42:41 cocoa 827 // Fixed typo in GNU fdl -- all doc/*.txt files affected. 828 // Minor corrections to PPMonoid (discovered while writing doc). 829 // 830 // Revision 1.1 2005/06/22 14:47:56 cocoa 831 // PPMonoids and PPMonoidElems updated to mirror the structure 832 // used for rings and RingElems. Many consequential changes. 833 // 834