1 // Copyright (c) 2004-2011 John Abbott 2 3 // This file is part of the source of CoCoALib, the CoCoA Library. 4 5 // CoCoALib is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 10 // CoCoALib is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 15 // You should have received a copy of the GNU General Public License 16 // along with CoCoALib. If not, see <http://www.gnu.org/licenses/>. 17 18 19 // Implementation of class PPMonoidEvImpl 20 21 #include "CoCoA/PPMonoidEv.H" 22 23 #include "CoCoA/BigIntOps.H" 24 #include "CoCoA/DivMask.H" 25 #include "CoCoA/MemPool.H" 26 #include "CoCoA/PPMonoid.H" 27 #include "CoCoA/PPOrdering.H" 28 #include "CoCoA/assert.H" 29 #include "CoCoA/convert.H" 30 #include "CoCoA/degree.H" 31 #include "CoCoA/error.H" 32 #include "CoCoA/matrix.H" 33 #include "CoCoA/symbol.H" 34 35 #include <algorithm> 36 using std::min; 37 using std::max; 38 //using std::swap; 39 #include <cstring> 40 using std::memcpy; 41 #include <iostream> 42 using std::ostream; 43 #include<limits> 44 using std::numeric_limits; 45 #include <memory> 46 using std::unique_ptr; 47 #include <vector> 48 using std::vector; 49 50 51 namespace CoCoA 52 { 53 54 /*-- class PPMonoidEvSmallExpImpl ---------------------------------------*/ 55 /*-- class PPMonoidEvImpl ---------------------------------------*/ 56 /** 57 58 \brief Implementation power product monoid with exponent vector 59 60 PPMonoidEvSmallExpImpl implements a power product monoid for safe testing. 61 It stores the exponents as a C vector of SmallExponent_t. 62 It is not designed to be efficient (but it might be ;-) 63 64 */ 65 /*-----------------------------------------------------------------*/ 66 67 class PPMonoidEvSmallExpImpl: public PPMonoidBase 68 { 69 typedef PPMonoidElemRawPtr RawPtr; // just to save typing 70 typedef PPMonoidElemConstRawPtr ConstRawPtr; // just to save typing 71 72 static const unsigned long ourMaxExp; // defined below; value is just numeric_limits<SmallExponent_t>::max() 73 74 class CmpBase 75 { 76 public: 77 CmpBase(long NumIndets, long GradingDim); 78 virtual ~CmpBase(); 79 public: 80 virtual int myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const =0; 81 virtual void myWDeg(degree& d, const SmallExponent_t* v) const =0; 82 // virtual int myCmpWDeg(const SmallExponent_t* v1, const SmallExponent_t* v2) const =0; 83 virtual int myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long) const =0; myCmpWDeg(const SmallExponent_t * v1,const SmallExponent_t * v2)84 int myCmpWDeg(const SmallExponent_t* v1, const SmallExponent_t* v2) const { return myCmpWDegPartial(v1, v2, myGradingDim); } 85 86 protected: 87 long myNumIndets; 88 long myGradingDim; 89 }; 90 91 class LexImpl: public CmpBase 92 { 93 public: 94 LexImpl(long NumIndets); 95 virtual int myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const; 96 virtual void myWDeg(degree& d, const SmallExponent_t* v) const; 97 virtual int myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long) const; 98 }; 99 100 101 class StdDegLexImpl: public CmpBase 102 { 103 public: 104 StdDegLexImpl(long NumIndets); 105 virtual int myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const; 106 virtual void myWDeg(degree& d, const SmallExponent_t* v) const; 107 virtual int myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long) const; 108 }; 109 110 111 class StdDegRevLexImpl: public CmpBase 112 { 113 public: 114 StdDegRevLexImpl(long NumIndets); 115 virtual int myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const; 116 virtual void myWDeg(degree& d, const SmallExponent_t* v) const; 117 virtual int myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long) const; 118 }; 119 120 121 class MatrixOrderingImpl: public CmpBase 122 { 123 public: 124 MatrixOrderingImpl(long NumIndets, long GradingDim, const ConstMatrixView& OrderMatrix); 125 virtual int myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const; 126 virtual void myWDeg(degree& d, const SmallExponent_t* v) const; 127 virtual int myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long) const; 128 private: 129 std::vector< std::vector<BigInt> > myOrderMatrix; 130 }; 131 132 133 public: 134 PPMonoidEvSmallExpImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord); 135 ~PPMonoidEvSmallExpImpl(); 136 private: // disable copy ctor and assignment 137 explicit PPMonoidEvSmallExpImpl(const PPMonoidEvSmallExpImpl& copy); // NEVER DEFINED -- copy ctor disabled 138 PPMonoidEvSmallExpImpl& operator=(const PPMonoidEvSmallExpImpl& rhs); // NEVER DEFINED -- assignment disabled 139 140 public: 141 void contents() const; // FOR DEBUGGING ONLY 142 143 const std::vector<PPMonoidElem>& myIndets() const; ///< std::vector whose n-th entry is n-th indet as PPMonoidElem 144 145 // The functions below are operations on power products owned by PPMonoidEvSmallExpImpl 146 const PPMonoidElem& myOne() const; 147 using PPMonoidBase::myNew; // disable warnings of overloading 148 PPMonoidElemRawPtr myNew() const; ///< ctor from nothing 149 PPMonoidElemRawPtr myNew(PPMonoidElemConstRawPtr rawpp) const; ///< ctor by assuming ownership 150 PPMonoidElemRawPtr myNew(const std::vector<long>& expv) const; ///< ctor from exp vector 151 void myDelete(RawPtr rawpp) const; ///< dtor, frees pp 152 void mySwap(RawPtr rawpp1, RawPtr rawpp2) const; ///< swap(pp1, pp2); 153 void myAssignOne(RawPtr rawpp) const; ///< pp = 1 154 void myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const; ///< p = pp1 155 void myAssign(RawPtr rawpp, const std::vector<long>& expv) const;///< pp = expv (assign from exp vector, all exps >= 0) 156 157 void myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1*pp2 158 using PPMonoidBase::myMulIndetPower; // disable warnings of overloading 159 void myMulIndetPower(RawPtr rawpp, long indet, long exp) const; ///< pp *= indet^exp, assumes exp >= 0 160 void myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1/pp2 161 void myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1/gcd(pp1,pp2) 162 void myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = gcd(pp1,pp2) 163 void myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = lcm(pp1,pp2) 164 void myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const; ///< pp = radical(pp1) 165 void myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long exp) const; ///< pp = pp1^exp, assumes exp >= 0 166 void myPowerOverflowCheck(ConstRawPtr rawpp1, long exp) const; ///< throw if pp1^exp would overflow, assumes exp >= 0 167 168 169 bool myIsOne(ConstRawPtr rawpp) const; ///< is pp = 1? 170 bool myIsIndet(long& index, ConstRawPtr rawpp) const; ///< true iff pp is an indet 171 bool myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< are pp1 & pp2 coprime? 172 bool myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< is pp1 equal to pp2? 173 bool myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< does pp2 divide pp1? 174 bool myIsSqFree(ConstRawPtr rawpp) const; ///< is pp equal to its radical? 175 176 int myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< -1,0,1 as pp1 < = > pp2 177 long myStdDeg(ConstRawPtr rawpp) const; ///< standard degree of pp 178 void myWDeg(degree& d, ConstRawPtr rawpp) const; ///< d = grading(pp) 179 int myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< <0, =0, >0 as wdeg(pp1) < = > wdeg(pp2) 180 int myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long) const; ///< as myCmpWDeg wrt the first weights 181 long myExponent(ConstRawPtr rawpp, long indet) const; ///< exponent of indet in pp 182 void myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const; ///< EXP = exponent of indet in pp 183 void myExponents(std::vector<long>& expv, ConstRawPtr rawpp) const; ///< expv[i] = exponent(pp,i) 184 void myBigExponents(std::vector<BigInt>& v, ConstRawPtr rawpp) const; ///< get exponents, SHOULD BE myExponents ??? 185 void myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const; ///< v[i] = true if i-th indet has exponent != 0 186 void myOutputSelf(std::ostream& out) const; ///< out << PPM 187 // INHERITED DEFINITION of virtual void myOutput(std::ostream& out, ConstRawPtr rawpp) const; 188 void myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const; ///< print pp in debugging format??? 189 190 191 private: // auxiliary functions 192 SmallExponent_t* myExpv(RawPtr) const; 193 const SmallExponent_t* myExpv(ConstRawPtr) const; 194 195 void myComputeDivMask(DivMask& dm, const DivMaskRule& DivMaskImpl, ConstRawPtr rawpp) const; ///< used by PPWithMask 196 bool myCheckExponents(const std::vector<long>& expv) const; 197 198 private: // data members 199 ///@name Class members 200 //@{ 201 const long myEntrySize; ///< size in ?bytes??? 202 mutable MemPool myMemMgr; // IMPORTANT: this must come *before* myIndetVector and myOnePtr. 203 vector<PPMonoidElem> myIndetVector; ///< the indets as PPMonoidElems 204 unique_ptr<CmpBase> myOrdPtr; ///< actual implementation of the ordering [should be const???] 205 unique_ptr<PPMonoidElem> myOnePtr; 206 //@} 207 }; 208 209 // static variable 210 const unsigned long PPMonoidEvSmallExpImpl::ourMaxExp = numeric_limits<SmallExponent_t>::max(); 211 212 213 // dtor not inline for some compiler (?) on PPC ~CmpBase()214 PPMonoidEvSmallExpImpl::CmpBase::~CmpBase() {} 215 216 217 // File local inline functions 218 myExpv(RawPtr rawpp)219 inline SmallExponent_t* PPMonoidEvSmallExpImpl::myExpv(RawPtr rawpp) const 220 { 221 return static_cast<SmallExponent_t*>(rawpp.myRawPtr()); 222 } 223 224 myExpv(ConstRawPtr rawpp)225 inline const SmallExponent_t* PPMonoidEvSmallExpImpl::myExpv(ConstRawPtr rawpp) const 226 { 227 return static_cast<const SmallExponent_t*>(rawpp.myRawPtr()); 228 } 229 230 myCheckExponents(const std::vector<long> & expv)231 bool PPMonoidEvSmallExpImpl::myCheckExponents(const std::vector<long>& expv) const 232 { 233 // Check expv.size == myNumIndets. 234 // Check exps are non-neg and not too big. 235 if (len(expv) != myNumIndets) return false; 236 for (long i=0; i < myNumIndets; ++i) 237 if (expv[i] < 0 || static_cast<unsigned long>(expv[i]) > numeric_limits<SmallExponent_t>::max()) return false; 238 return true; 239 } 240 241 242 //---- Constructors & destructor ----// 243 PPMonoidEvSmallExpImpl(const std::vector<symbol> & IndetNames,const PPOrdering & ord)244 PPMonoidEvSmallExpImpl::PPMonoidEvSmallExpImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord): 245 PPMonoidBase(ord, IndetNames), 246 myEntrySize(sizeof(SmallExponent_t)*myNumIndets), 247 myMemMgr(myEntrySize, "PPMonoidEvSmallExpImpl.myMemMgr"), 248 myIndetVector() 249 { 250 // Put the correct implementation in myOrdPtr... [VERY UGLY CODE!!!] 251 if (IsLex(ord)) 252 myOrdPtr.reset(new LexImpl(myNumIndets)); 253 else if (IsStdDegLex(ord)) 254 myOrdPtr.reset(new StdDegLexImpl(myNumIndets)); 255 else if (IsStdDegRevLex(ord)) 256 myOrdPtr.reset(new StdDegRevLexImpl(myNumIndets)); 257 else 258 myOrdPtr.reset(new MatrixOrderingImpl(myNumIndets, GradingDim(ord), OrdMat(ord))); 259 260 myRefCountInc(); // this is needed for exception cleanliness, in case one of the lines below throws 261 myOnePtr.reset(new PPMonoidElem(PPMonoid(this))); 262 { 263 // IMPORTANT: this block destroys pp *before* the call to myRefCountZero. 264 PPMonoidElem pp(PPMonoid(this)); 265 vector<long> expv(myNumIndets); 266 for (long i=0; i < myNumIndets; ++i) 267 { 268 expv[i] = 1; 269 myAssign(raw(pp), expv); 270 myIndetVector.push_back(pp); 271 expv[i] = 0; 272 } 273 } 274 myRefCountZero(); 275 } 276 277 ~PPMonoidEvSmallExpImpl()278 PPMonoidEvSmallExpImpl::~PPMonoidEvSmallExpImpl() 279 {} 280 281 ///////////////////////////////////////////////////////////////////////////// 282 283 284 myIndets()285 const std::vector<PPMonoidElem>& PPMonoidEvSmallExpImpl::myIndets() const 286 { 287 return myIndetVector; 288 } 289 290 myOne()291 const PPMonoidElem& PPMonoidEvSmallExpImpl::myOne() const 292 { 293 return *myOnePtr; 294 } 295 296 myNew()297 PPMonoidElemRawPtr PPMonoidEvSmallExpImpl::myNew() const 298 { 299 PPMonoidElemRawPtr rawpp(myMemMgr.alloc()); 300 myAssignOne(rawpp); // cannot throw 301 return rawpp; 302 } 303 myNew(PPMonoidElemConstRawPtr rawcopypp)304 PPMonoidElemRawPtr PPMonoidEvSmallExpImpl::myNew(PPMonoidElemConstRawPtr rawcopypp) const 305 { 306 PPMonoidElemRawPtr rawpp(myMemMgr.alloc()); 307 myAssign(rawpp, rawcopypp); // cannot throw 308 return rawpp; 309 } 310 311 myNew(const std::vector<long> & expv)312 PPMonoidElemRawPtr PPMonoidEvSmallExpImpl::myNew(const std::vector<long>& expv) const 313 { 314 CoCoA_ASSERT(myCheckExponents(expv)); 315 PPMonoidElemRawPtr rawpp(myMemMgr.alloc()); 316 myAssign(rawpp, expv); // cannot throw 317 return rawpp; 318 } 319 320 myAssignOne(RawPtr rawpp)321 void PPMonoidEvSmallExpImpl::myAssignOne(RawPtr rawpp) const 322 { 323 SmallExponent_t* const expv = myExpv(rawpp); 324 for (long i = 0; i < myNumIndets; ++i) 325 expv[i] = 0; 326 } 327 328 myAssign(RawPtr rawpp,ConstRawPtr rawpp1)329 void PPMonoidEvSmallExpImpl::myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const 330 { 331 if (rawpp == rawpp1) return; 332 333 // SmallExponent_t* const expv = myExpv(rawpp); 334 // const SmallExponent_t* const expv1 = myExpv(rawpp1); 335 // std::copy(expv1, expv1+myNumIndets, expv); 336 memcpy(myExpv(rawpp), myExpv(rawpp1), myNumIndets*sizeof(SmallExponent_t)); 337 } 338 myAssign(RawPtr rawpp,const vector<long> & expv1)339 void PPMonoidEvSmallExpImpl::myAssign(RawPtr rawpp, const vector<long>& expv1) const 340 { 341 CoCoA_ASSERT(myCheckExponents(expv1)); 342 343 SmallExponent_t* const expv = myExpv(rawpp); 344 for (long i = 0; i < myNumIndets; ++i) 345 expv[i] = NumericCast<SmallExponent_t>(expv1[i]); 346 } 347 348 myDelete(RawPtr rawpp)349 void PPMonoidEvSmallExpImpl::myDelete(RawPtr rawpp) const 350 { 351 myMemMgr.free(rawpp.myRawPtr()); 352 } 353 354 mySwap(RawPtr rawpp1,RawPtr rawpp2)355 void PPMonoidEvSmallExpImpl::mySwap(RawPtr rawpp1, RawPtr rawpp2) const 356 { 357 if (rawpp1 == rawpp2) return; 358 SmallExponent_t* const expv1 = myExpv(rawpp1); 359 SmallExponent_t* const expv2 = myExpv(rawpp2); 360 for (long i = 0; i < myNumIndets; ++i) 361 std::swap(expv1[i], expv2[i]); 362 } 363 364 myMul(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)365 void PPMonoidEvSmallExpImpl::myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 366 { 367 // No worries about aliasing. 368 SmallExponent_t* const expv = myExpv(rawpp); 369 const SmallExponent_t* const expv1 = myExpv(rawpp1); 370 const SmallExponent_t* const expv2 = myExpv(rawpp2); 371 for (long i=0; i < myNumIndets; ++i) 372 { 373 CoCoA_ASSERT("Exponent Overflow" && expv1[i] <= std::numeric_limits<SmallExponent_t>::max()-expv2[i]); 374 expv[i] = expv1[i] + expv2[i]; 375 } 376 } 377 378 myMulIndetPower(RawPtr rawpp,long indet,long exp)379 void PPMonoidEvSmallExpImpl::myMulIndetPower(RawPtr rawpp, long indet, long exp) const // assumes exp >= 0 380 { 381 CoCoA_ASSERT(exp >= 0); 382 CoCoA_ASSERT(0 <= indet && indet < myNumIndets); 383 SmallExponent_t* const expv = myExpv(rawpp); 384 // If CoCoA_DEBUG active, check for exponent overflow... 385 CoCoA_ASSERT("Exponent Overflow" && ourMaxExp - expv[indet] >= static_cast<unsigned long>(exp)); 386 expv[indet] += static_cast<SmallExponent_t>(exp); // cast to keep M$ compiler quiet 387 } 388 389 myDiv(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)390 void PPMonoidEvSmallExpImpl::myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 391 { 392 // No worries about aliasing. 393 SmallExponent_t* const expv = myExpv(rawpp); 394 const SmallExponent_t* const expv1 = myExpv(rawpp1); 395 const SmallExponent_t* const expv2 = myExpv(rawpp2); 396 for (long i=0; i < myNumIndets; ++i) 397 { 398 CoCoA_ASSERT("Exponent Underflow" && expv1[i] >= expv2[i]); 399 expv[i] = expv1[i] - expv2[i]; 400 } 401 } 402 403 myColon(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)404 void PPMonoidEvSmallExpImpl::myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 405 { 406 // No worries about aliasing. 407 SmallExponent_t* const expv = myExpv(rawpp); 408 const SmallExponent_t* const expv1 = myExpv(rawpp1); 409 const SmallExponent_t* const expv2 = myExpv(rawpp2); 410 411 for (long i = 0; i < myNumIndets; ++i) 412 if (expv1[i] > expv2[i]) 413 expv[i] = expv1[i] - expv2[i]; 414 else 415 expv[i] = 0; 416 } 417 418 myGcd(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)419 void PPMonoidEvSmallExpImpl::myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 420 { 421 // No worries about aliasing. 422 SmallExponent_t* const expv = myExpv(rawpp); 423 const SmallExponent_t* const expv1 = myExpv(rawpp1); 424 const SmallExponent_t* const expv2 = myExpv(rawpp2); 425 426 for (long i = 0; i < myNumIndets; ++i) 427 expv[i] = min(expv1[i], expv2[i]); 428 } 429 430 myLcm(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)431 void PPMonoidEvSmallExpImpl::myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 432 { 433 // No worries about aliasing. 434 SmallExponent_t* const expv = myExpv(rawpp); 435 const SmallExponent_t* const expv1 = myExpv(rawpp1); 436 const SmallExponent_t* const expv2 = myExpv(rawpp2); 437 438 for (long i = 0; i < myNumIndets; ++i) 439 expv[i] = max(expv1[i], expv2[i]); 440 } 441 442 myRadical(RawPtr rawpp,ConstRawPtr rawpp1)443 void PPMonoidEvSmallExpImpl::myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const 444 { 445 SmallExponent_t* const expv = myExpv(rawpp); 446 const SmallExponent_t* const expv1 = myExpv(rawpp1); 447 448 for (long i = 0; i < myNumIndets; ++i) 449 expv[i] = (expv1[i] > 0); 450 } 451 452 myPowerSmallExp(RawPtr rawpp,ConstRawPtr rawpp1,long LongExp)453 void PPMonoidEvSmallExpImpl::myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long LongExp) const // assumes exp >= 0 454 { 455 CoCoA_ASSERT(LongExp >= 0); 456 #ifdef CoCoA_DEBUG 457 myPowerOverflowCheck(rawpp1, LongExp); 458 #endif 459 if (static_cast<unsigned long>(LongExp) > ourMaxExp) 460 CoCoA_ERROR(ERR::ExpTooBig, "PPMonoidEvSmallExpImpl::myPowerSmallExp"); 461 const SmallExponent_t exp = static_cast<SmallExponent_t>(LongExp); 462 463 SmallExponent_t* const expv = myExpv(rawpp); 464 const SmallExponent_t* const expv1 = myExpv(rawpp1); 465 for (long i = 0; i < myNumIndets; ++i) 466 expv[i] = exp * expv1[i]; 467 } 468 469 myPowerOverflowCheck(ConstRawPtr rawpp,long LongExp)470 void PPMonoidEvSmallExpImpl::myPowerOverflowCheck(ConstRawPtr rawpp, long LongExp) const 471 { 472 if (LongExp == 0 || LongExp == 1) return; 473 CoCoA_ASSERT(LongExp >= 0); 474 const char* const FnName = "PPMonoidEvSmallExpImpl::myPowerOverflowCheck"; 475 if (static_cast<unsigned long>(LongExp) > ourMaxExp) 476 CoCoA_ERROR(ERR::ExpTooBig, FnName); 477 const SmallExponent_t exp = static_cast<SmallExponent_t>(LongExp); 478 const SmallExponent_t limit = ourMaxExp/exp; 479 480 const SmallExponent_t* const expv = myExpv(rawpp); 481 for (long i = 0; i < myNumIndets; ++i) 482 { 483 if (expv[i] > limit) 484 CoCoA_ERROR(ERR::ExpTooBig, FnName); 485 } 486 } 487 488 myIsOne(ConstRawPtr rawpp)489 bool PPMonoidEvSmallExpImpl::myIsOne(ConstRawPtr rawpp) const 490 { 491 const SmallExponent_t* const expv = myExpv(rawpp); 492 493 for (long i = 0; i < myNumIndets; ++i) 494 if (expv[i] != 0) return false; 495 496 return true; 497 } 498 499 myIsIndet(long & index,ConstRawPtr rawpp)500 bool PPMonoidEvSmallExpImpl::myIsIndet(long& index, ConstRawPtr rawpp) const 501 { 502 const SmallExponent_t* const expv = myExpv(rawpp); 503 long j = myNumIndets; 504 for (long i = 0; i < myNumIndets; ++i) 505 { 506 if (expv[i] == 0) continue; 507 if (j != myNumIndets || expv[i] != 1) return false; 508 j = i; 509 } 510 if (j == myNumIndets) return false; 511 index = j; 512 return true; 513 } 514 515 myIsCoprime(ConstRawPtr rawpp1,ConstRawPtr rawpp2)516 bool PPMonoidEvSmallExpImpl::myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 517 { 518 const SmallExponent_t* const expv1 = myExpv(rawpp1); 519 const SmallExponent_t* const expv2 = myExpv(rawpp2); 520 521 for (long i = 0; i < myNumIndets; ++i) 522 if (expv1[i] != 0 && expv2[i] != 0) return false; 523 524 return true; 525 } 526 527 myIsEqual(ConstRawPtr rawpp1,ConstRawPtr rawpp2)528 bool PPMonoidEvSmallExpImpl::myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 529 { 530 const SmallExponent_t* const expv1 = myExpv(rawpp1); 531 const SmallExponent_t* const expv2 = myExpv(rawpp2); 532 533 for (long i = 0; i < myNumIndets; ++i) 534 if (expv1[i] != expv2[i]) return false; 535 return true; 536 } 537 538 myIsDivisible(ConstRawPtr rawpp1,ConstRawPtr rawpp2)539 bool PPMonoidEvSmallExpImpl::myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 540 { 541 const SmallExponent_t* const expv1 = myExpv(rawpp1); 542 const SmallExponent_t* const expv2 = myExpv(rawpp2); 543 544 for (long i = 0; i < myNumIndets; ++i) 545 if (expv1[i] < expv2[i]) return false; 546 547 return true; 548 } 549 550 myIsSqFree(ConstRawPtr rawpp)551 bool PPMonoidEvSmallExpImpl::myIsSqFree(ConstRawPtr rawpp) const 552 { 553 const SmallExponent_t* const expv = myExpv(rawpp); 554 555 for (long i = 0; i < myNumIndets; ++i) 556 if (expv[i] > 1) return false; 557 558 return true; 559 } 560 561 myCmp(ConstRawPtr rawpp1,ConstRawPtr rawpp2)562 int PPMonoidEvSmallExpImpl::myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 563 { 564 return myOrdPtr->myCmpExpvs(myExpv(rawpp1), myExpv(rawpp2)); 565 } 566 567 myStdDeg(ConstRawPtr rawpp)568 long PPMonoidEvSmallExpImpl::myStdDeg(ConstRawPtr rawpp) const 569 { 570 const SmallExponent_t* const expv = myExpv(rawpp); 571 long d=0; 572 for (long i=0; i < myNumIndets; ++i) 573 d += expv[i]; 574 return d; 575 } 576 577 myWDeg(degree & d,ConstRawPtr rawpp)578 void PPMonoidEvSmallExpImpl::myWDeg(degree& d, ConstRawPtr rawpp) const 579 { 580 myOrdPtr->myWDeg(d, myExpv(rawpp)); 581 } 582 583 myCmpWDeg(ConstRawPtr rawpp1,ConstRawPtr rawpp2)584 int PPMonoidEvSmallExpImpl::myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 585 { 586 return myOrdPtr->myCmpWDeg(myExpv(rawpp1), myExpv(rawpp2)); 587 } 588 589 myCmpWDegPartial(ConstRawPtr rawpp1,ConstRawPtr rawpp2,long i)590 int PPMonoidEvSmallExpImpl::myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long i) const 591 { 592 return myOrdPtr->myCmpWDegPartial(myExpv(rawpp1), myExpv(rawpp2), i); 593 } 594 595 myExponent(ConstRawPtr rawpp,long indet)596 long PPMonoidEvSmallExpImpl::myExponent(ConstRawPtr rawpp, long indet) const 597 { 598 CoCoA_ASSERT(indet < myNumIndets); 599 return NumericCast<long>(myExpv(rawpp)[indet]); 600 } 601 myBigExponent(BigInt & EXP,ConstRawPtr rawpp,long indet)602 void PPMonoidEvSmallExpImpl::myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const 603 { 604 CoCoA_ASSERT(indet < myNumIndets); 605 EXP = myExpv(rawpp)[indet]; 606 } 607 608 myExponents(std::vector<long> & v,ConstRawPtr rawpp)609 void PPMonoidEvSmallExpImpl::myExponents(std::vector<long>& v, ConstRawPtr rawpp) const 610 { 611 CoCoA_ASSERT(len(v) == myNumIndets); 612 const SmallExponent_t* const expv = myExpv(rawpp); 613 for (long i=0; i < myNumIndets; ++i) 614 v[i] = NumericCast<long>(expv[i]); 615 } 616 617 myBigExponents(std::vector<BigInt> & expv,ConstRawPtr rawpp)618 void PPMonoidEvSmallExpImpl::myBigExponents(std::vector<BigInt>& expv, ConstRawPtr rawpp) const 619 { 620 CoCoA_ASSERT(len(expv) == myNumIndets); 621 const SmallExponent_t* const v = myExpv(rawpp); 622 for (long i=0; i < myNumIndets; ++i) expv[i] = v[i]; 623 } 624 625 myIndetsIn(std::vector<bool> & v,ConstRawPtr rawpp)626 void PPMonoidEvSmallExpImpl::myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const 627 { 628 CoCoA_ASSERT(len(v) == myNumIndets); 629 const SmallExponent_t* const expv = myExpv(rawpp); 630 for (long i=0; i < myNumIndets; ++i) 631 if (expv[i] != 0) 632 v[i] = true; 633 } 634 myComputeDivMask(DivMask & dm,const DivMaskRule & DivMaskImpl,ConstRawPtr rawpp)635 void PPMonoidEvSmallExpImpl::myComputeDivMask(DivMask& dm, const DivMaskRule& DivMaskImpl, ConstRawPtr rawpp) const 636 { 637 DivMaskImpl->myAssignFromExpv(dm, myExpv(rawpp), myNumIndets); 638 } 639 640 myOutputSelf(std::ostream & out)641 void PPMonoidEvSmallExpImpl::myOutputSelf(std::ostream& out) const 642 { 643 if (!out) return; // short-cut for bad ostreams 644 out << "PPMonoidEv(" << myNumIndets << ", " << myOrd <<")"; 645 } 646 647 myDebugPrint(std::ostream & out,ConstRawPtr rawpp)648 void PPMonoidEvSmallExpImpl::myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const 649 { 650 if (!out) return; // short-cut for bad ostreams 651 out << "DEBUG PP: myNumIndets=" << myNumIndets << ", exps=["; 652 for (long i=0; i < myNumIndets; ++i) 653 out << myExponent(rawpp, i) << " "; 654 out << "]" << std::endl; 655 } 656 657 658 //--- orderings ---------------------------------------- 659 CmpBase(long NumIndets,long GradingDim)660 PPMonoidEvSmallExpImpl::CmpBase::CmpBase(long NumIndets, long GradingDim): 661 myNumIndets(NumIndets), 662 myGradingDim(GradingDim) 663 { 664 CoCoA_ASSERT(NumIndets > 0); 665 CoCoA_ASSERT(NumIndets < 1000000); // complain about ridiculously large number of indets 666 CoCoA_ASSERT(GradingDim >= 0); 667 CoCoA_ASSERT(GradingDim <= NumIndets); 668 } 669 670 671 //--- LexImpl 672 LexImpl(long NumIndets)673 PPMonoidEvSmallExpImpl::LexImpl::LexImpl(long NumIndets): 674 CmpBase(NumIndets, 0) 675 { 676 } 677 678 myCmpExpvs(const SmallExponent_t * v1,const SmallExponent_t * v2)679 int PPMonoidEvSmallExpImpl::LexImpl::myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const 680 { 681 for (long i=0; i<myNumIndets; ++i) 682 if (v1[i] != v2[i]) 683 { 684 if (v1[i] > v2[i]) return 1; else return -1; 685 } 686 return 0; 687 } 688 689 myWDeg(degree &,const SmallExponent_t *)690 void PPMonoidEvSmallExpImpl::LexImpl::myWDeg(degree& /*d*/, const SmallExponent_t* /*v*/) const 691 { 692 // deliberately does nothing because GradingDim=0 693 //??? should it assign: d = [] 694 } 695 696 myCmpWDegPartial(const SmallExponent_t *,const SmallExponent_t *,long)697 int PPMonoidEvSmallExpImpl::LexImpl::myCmpWDegPartial(const SmallExponent_t* /*v1*/, const SmallExponent_t* /*v2*/, long /*i*/) const 698 { 699 return 0; // GradingDim=0, and all degrees in Z^0 are equal 700 } 701 702 //--- StdDegLexImpl 703 StdDegLexImpl(long NumIndets)704 PPMonoidEvSmallExpImpl::StdDegLexImpl::StdDegLexImpl(long NumIndets): 705 CmpBase(NumIndets, 1) 706 { 707 } 708 709 myWDeg(degree & d,const SmallExponent_t * v)710 void PPMonoidEvSmallExpImpl::StdDegLexImpl::myWDeg(degree& d, const SmallExponent_t* v) const 711 { 712 long deg=0; 713 for (long i=0; i < myNumIndets; ++i) 714 deg += v[i]; 715 SetComponent(d, 0, deg); 716 } 717 718 myCmpExpvs(const SmallExponent_t * v1,const SmallExponent_t * v2)719 int PPMonoidEvSmallExpImpl::StdDegLexImpl::myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const 720 { 721 long deg1=0, deg2=0; 722 for (long i=0; i < myNumIndets; ++i) 723 { 724 deg1 += v1[i]; 725 deg2 += v2[i]; 726 } 727 if (deg1 != deg2) 728 { 729 if (deg1 > deg2) return 1; else return -1; 730 } 731 732 for (long i=0; i < myNumIndets; ++i) 733 if (v1[i] != v2[i]) 734 { 735 if (v1[i] > v2[i]) return 1; else return -1; 736 } 737 return 0; 738 } 739 740 myCmpWDegPartial(const SmallExponent_t * v1,const SmallExponent_t * v2,long i)741 int PPMonoidEvSmallExpImpl::StdDegLexImpl::myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long i) const 742 { 743 if (i==0) return 0; // ie: wrt to 0-grading 744 long deg1=0, deg2=0; 745 for (long i=0; i < myNumIndets; ++i) 746 { 747 deg1 += v1[i]; 748 deg2 += v2[i]; 749 } 750 if (deg1 != deg2) 751 { 752 if (deg1 > deg2) return 1; else return -1; 753 } 754 return 0; 755 } 756 757 758 //--- StdDegRevLexImpl 759 StdDegRevLexImpl(long NumIndets)760 PPMonoidEvSmallExpImpl::StdDegRevLexImpl::StdDegRevLexImpl(long NumIndets): 761 CmpBase(NumIndets, 1) 762 { 763 } 764 765 myWDeg(degree & d,const SmallExponent_t * v)766 void PPMonoidEvSmallExpImpl::StdDegRevLexImpl::myWDeg(degree& d, const SmallExponent_t* v) const 767 { 768 long deg=0; 769 for (long i=0; i < myNumIndets; ++i) 770 deg += v[i]; 771 SetComponent(d, 0, deg); 772 } 773 774 myCmpExpvs(const SmallExponent_t * v1,const SmallExponent_t * v2)775 int PPMonoidEvSmallExpImpl::StdDegRevLexImpl::myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const 776 { 777 long deg1=0, deg2=0; 778 for (long i=0; i < myNumIndets; ++i) 779 { 780 deg1 += v1[i]; 781 deg2 += v2[i]; 782 } 783 if (deg1 != deg2) 784 { 785 if (deg1 > deg2) return 1; else return -1; 786 } 787 788 for (long i = myNumIndets-1; i>0; --i) 789 if (v1[i] != v2[i]) 790 { 791 if (v1[i] > v2[i]) return -1; else return 1; 792 } 793 return 0; 794 } 795 796 myCmpWDegPartial(const SmallExponent_t * v1,const SmallExponent_t * v2,long PartialGrDim)797 int PPMonoidEvSmallExpImpl::StdDegRevLexImpl::myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long PartialGrDim) const 798 { 799 CoCoA_ASSERT(PartialGrDim==0 || PartialGrDim==1); 800 if (PartialGrDim==0) return 0; // ie: wrt to 0-grading 801 long deg1=0, deg2=0; 802 for (long i=0; i < myNumIndets; ++i) 803 { 804 deg1 += v1[i]; 805 deg2 += v2[i]; 806 } 807 if (deg1 != deg2) 808 { 809 if (deg1 > deg2) return 1; else return -1; 810 } 811 return 0; 812 } 813 814 815 //--- MatrixOrderingImpl 816 MatrixOrderingImpl(long NumIndets,long GradingDim,const ConstMatrixView & OrderMatrix)817 PPMonoidEvSmallExpImpl::MatrixOrderingImpl::MatrixOrderingImpl(long NumIndets, long GradingDim, const ConstMatrixView& OrderMatrix): 818 CmpBase(NumIndets, GradingDim) 819 { 820 CoCoA_ASSERT(NumIndets > 0); 821 CoCoA_ASSERT(0 <= GradingDim && GradingDim <= NumIndets); 822 CoCoA_ASSERT(NumRows(OrderMatrix) == NumIndets); 823 CoCoA_ASSERT(NumCols(OrderMatrix) == NumIndets); 824 825 myOrderMatrix.resize(NumIndets, vector<BigInt>(NumIndets)); 826 for (long i=0; i < NumIndets; ++i) 827 for (long j=0; j < NumIndets; ++j) 828 myOrderMatrix[i][j] = ConvertTo<BigInt>(OrderMatrix(i,j)); 829 } 830 831 myWDeg(degree & d,const SmallExponent_t * v)832 void PPMonoidEvSmallExpImpl::MatrixOrderingImpl::myWDeg(degree& d, const SmallExponent_t* v) const 833 { 834 BigInt deg; 835 for (long g=0; g < myGradingDim; ++g) 836 { 837 deg = 0; 838 for (long i=0; i < myNumIndets; ++i) 839 deg += v[i] * myOrderMatrix[g][i]; 840 SetComponent(d, g, deg); 841 } 842 } 843 844 MatrixOrderingCmpArrays(const vector<vector<BigInt>> & M,const SmallExponent_t * v1,const SmallExponent_t * v2,long UpTo)845 static int MatrixOrderingCmpArrays(const vector<vector<BigInt> >& M, const SmallExponent_t* v1, const SmallExponent_t* v2, long UpTo) 846 { 847 CoCoA_ASSERT(0 <= UpTo && UpTo <= len(M)); 848 BigInt s1, s2; // automatically set to 0 849 const long ncols = len(M[0]); 850 for (long r=0; r < UpTo; ++r) 851 { 852 for (long i=0; i < ncols; ++i) 853 { 854 s1 += v1[i]*M[r][i]; 855 s2 += v2[i]*M[r][i]; 856 } 857 if (s1 != s2) 858 { 859 if (s1 > s2) return 1; else return -1; 860 } 861 s1 = 0; 862 s2 = 0; 863 } 864 return 0; 865 } 866 867 myCmpExpvs(const SmallExponent_t * v1,const SmallExponent_t * v2)868 int PPMonoidEvSmallExpImpl::MatrixOrderingImpl::myCmpExpvs(const SmallExponent_t* v1, const SmallExponent_t* v2) const 869 { 870 return MatrixOrderingCmpArrays(myOrderMatrix, v1, v2, myNumIndets); 871 } 872 873 874 // int PPMonoidEvSmallExpImpl::MatrixOrderingImpl::myCmpWDeg(const SmallExponent_t* v1, const SmallExponent_t* v2) const 875 // { 876 // return MatrixOrderingCmpArrays(myOrderMatrix, v1, v2, myGradingDim); 877 // } 878 879 myCmpWDegPartial(const SmallExponent_t * v1,const SmallExponent_t * v2,long PartialGrDim)880 int PPMonoidEvSmallExpImpl::MatrixOrderingImpl::myCmpWDegPartial(const SmallExponent_t* v1, const SmallExponent_t* v2, long PartialGrDim) const 881 { 882 return MatrixOrderingCmpArrays(myOrderMatrix, v1, v2, PartialGrDim); 883 } 884 885 ////////////////////////////////////////////////////////////////// 886 // BIG EXPONENTS 887 888 class PPMonoidEvBigExpImpl: public PPMonoidBase 889 { 890 typedef PPMonoidElemRawPtr RawPtr; // just to save typing 891 typedef PPMonoidElemConstRawPtr ConstRawPtr; // just to save typing 892 893 class CmpBase 894 { 895 public: 896 CmpBase(long NumIndets, long GradingDim); ~CmpBase()897 virtual ~CmpBase() {}; 898 public: 899 virtual int myCmpExpvs(const BigInt* v1, const BigInt* v2) const =0; 900 virtual void myWDeg(degree& d, const BigInt* v) const =0; 901 virtual int myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const =0; 902 // virtual int myCmpWDeg(const BigInt* v1, const BigInt* v2) const =0; myCmpWDeg(const BigInt * v1,const BigInt * v2)903 int myCmpWDeg(const BigInt* v1, const BigInt* v2) const { return myCmpWDegPartial(v1, v2, myGradingDim); } 904 protected: 905 long myNumIndets; 906 long myGradingDim; 907 }; 908 909 class LexImpl: public CmpBase 910 { 911 public: 912 LexImpl(long NumIndets); 913 virtual int myCmpExpvs(const BigInt* v1, const BigInt* v2) const; 914 virtual void myWDeg(degree& d, const BigInt* v) const; 915 virtual int myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const; 916 }; 917 918 919 class StdDegLexImpl: public CmpBase 920 { 921 public: 922 StdDegLexImpl(long NumIndets); 923 virtual int myCmpExpvs(const BigInt* v1, const BigInt* v2) const; 924 virtual void myWDeg(degree& d, const BigInt* v) const; 925 virtual int myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const; 926 }; 927 928 929 class StdDegRevLexImpl: public CmpBase 930 { 931 public: 932 StdDegRevLexImpl(long NumIndets); 933 virtual int myCmpExpvs(const BigInt* v1, const BigInt* v2) const; 934 virtual void myWDeg(degree& d, const BigInt* v) const; 935 virtual int myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const; 936 }; 937 938 939 class MatrixOrderingImpl: public CmpBase 940 { 941 public: 942 MatrixOrderingImpl(long NumIndets, long GradingDim, const ConstMatrixView& OrderMatrix); 943 virtual int myCmpExpvs(const BigInt* v1, const BigInt* v2) const; 944 virtual void myWDeg(degree& d, const BigInt* v) const; 945 virtual int myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const; 946 private: 947 std::vector< std::vector<BigInt> > myOrderMatrix; 948 }; 949 950 951 public: 952 PPMonoidEvBigExpImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord); 953 ~PPMonoidEvBigExpImpl(); 954 private: // disable copy ctor and assignment 955 explicit PPMonoidEvBigExpImpl(const PPMonoidEvBigExpImpl& copy); // NEVER DEFINED -- copy ctor disabled 956 PPMonoidEvBigExpImpl& operator=(const PPMonoidEvBigExpImpl& rhs); // NEVER DEFINED -- assignment disabled 957 958 public: 959 void contents() const; // FOR DEBUGGING ONLY 960 961 const std::vector<PPMonoidElem>& myIndets() const; ///< std::vector whose n-th entry is n-th indet as PPMonoidElem 962 963 // The functions below are operations on power products owned by PPMonoidEvBigExpImpl 964 const PPMonoidElem& myOne() const; 965 PPMonoidElemRawPtr myNew() const; ///< ctor from nothing 966 PPMonoidElemRawPtr myNew(PPMonoidElemConstRawPtr rawpp) const; ///< ctor by assuming ownership 967 PPMonoidElemRawPtr myNew(const std::vector<long>& expv) const; ///< ctor from exp vector 968 PPMonoidElemRawPtr myNew(const std::vector<BigInt>& EXPV) const; ///< ctor from exp vector 969 void myDelete(RawPtr rawpp) const; ///< dtor, frees pp 970 void mySwap(RawPtr rawpp1, RawPtr rawpp2) const; ///< swap(pp1, pp2); 971 void myAssignOne(RawPtr rawpp) const; ///< pp = 1 972 void myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const; ///< p = pp1 973 void myAssign(RawPtr rawpp, const std::vector<long>& expv) const;///< pp = expv (assign from exp vector) 974 975 void myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1*pp2 976 using PPMonoidBase::myMulIndetPower; // disable warnings of overloading 977 void myMulIndetPower(RawPtr rawpp, long indet, long exp) const; ///< pp *= indet^exp, assumes exp >= 0 978 void myMulIndetPower(RawPtr rawpp, long indet, const BigInt& EXP) const; ///< pp *= indet^EXP 979 void myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1/pp2 980 void myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = pp1/gcd(pp1,pp2) 981 void myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = gcd(pp1,pp2) 982 void myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< pp = lcm(pp1,pp2) 983 void myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const; ///< pp = radical(pp1) 984 void myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long exp) const; ///< pp = pp1^exp, assumes exp >= 0 985 void myPowerOverflowCheck(ConstRawPtr rawpp1, long exp) const; ///< throw if pp1^exp would overflow, assumes exp >= 0 986 987 988 bool myIsOne(ConstRawPtr rawpp) const; ///< is pp = 1? 989 bool myIsIndet(long& index, ConstRawPtr rawpp) const; ///< true iff pp is an indet 990 bool myIsIndetPosPower(long& indet, BigInt& EXP, ConstRawPtr rawpp) const; 991 bool myIsIndetPosPower(long& indet, long& pow, ConstRawPtr rawpp) const; 992 bool myIsIndetPosPower(ConstRawPtr rawpp) const; 993 bool myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< are pp1 & pp2 coprime? 994 bool myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< is pp1 equal to pp2? 995 bool myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< does pp2 divide pp1? 996 bool myIsSqFree(ConstRawPtr rawpp) const; ///< is pp equal to its radical? 997 998 int myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< -1,0,1 as pp1 < = > pp2 999 long myStdDeg(ConstRawPtr rawpp) const; ///< standard degree of pp 1000 void myWDeg(degree& d, ConstRawPtr rawpp) const; ///< d = grading(pp) 1001 int myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const; ///< <0, =0, >0 as wdeg(pp1) < = > wdeg(pp2) 1002 int myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long GrDim ) const; ///< as myCmpWDeg wrt the first GrDim weights 1003 long myExponent(ConstRawPtr rawpp, long indet) const; ///< exponent of indet in pp 1004 void myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const; ///< EXP = exponent of indet in pp 1005 void myExponents(std::vector<long>& expv, ConstRawPtr rawpp) const; ///< expv[i] = exponent(pp,i) 1006 void myBigExponents(std::vector<BigInt>& v, ConstRawPtr rawpp) const; ///< get exponents, SHOULD BE myExponents ??? 1007 void myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const; ///< v[i] = true if i-th indet has exponent != 0 1008 void myOutputSelf(std::ostream& out) const; ///< out << PPM 1009 // INHERITED DEFINITION of virtual void myOutput(std::ostream& out, ConstRawPtr rawpp) const; 1010 void myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const; ///< print pp in debugging format??? 1011 1012 1013 private: // auxiliary functions 1014 BigInt* myExpv(RawPtr) const; 1015 const BigInt* myExpv(ConstRawPtr) const; 1016 1017 void myComputeDivMask(DivMask& dm, const DivMaskRule& DivMaskImpl, ConstRawPtr rawpp) const; ///< used by PPWithMask 1018 bool myCheckExponents(const std::vector<long>& expv) const; 1019 bool myCheckExponents(const std::vector<BigInt>& EXPV) const; 1020 1021 private: // data members 1022 ///@name Class members 1023 //@{ 1024 const long myEntrySize; ///< size in ???? 1025 mutable MemPool myMemMgr; // IMPORTANT: this must come *before* myIndetVector and myOnePtr. 1026 std::vector<PPMonoidElem> myIndetVector; ///< the indets as PPMonoidElems 1027 std::unique_ptr<CmpBase> myOrdPtr; ///< actual implementation of the ordering [should be const???] 1028 std::unique_ptr<PPMonoidElem> myOnePtr; 1029 //@} 1030 }; 1031 1032 1033 // File local inline functions 1034 myExpv(RawPtr rawpp)1035 inline BigInt* PPMonoidEvBigExpImpl::myExpv(RawPtr rawpp) const 1036 { 1037 return static_cast<BigInt*>(rawpp.myRawPtr()); 1038 } 1039 1040 myExpv(ConstRawPtr rawpp)1041 inline const BigInt* PPMonoidEvBigExpImpl::myExpv(ConstRawPtr rawpp) const 1042 { 1043 return static_cast<const BigInt*>(rawpp.myRawPtr()); 1044 } 1045 1046 myCheckExponents(const std::vector<long> & expv)1047 bool PPMonoidEvBigExpImpl::myCheckExponents(const std::vector<long>& expv) const 1048 { 1049 // Check len(expv) == myNumIndets. 1050 // Check exps are non-neg and not too big. 1051 if (len(expv) != myNumIndets) return false; 1052 for (long i=0; i < myNumIndets; ++i) 1053 if (expv[i] < 0) return false; 1054 return true; 1055 } 1056 myCheckExponents(const std::vector<BigInt> & expv)1057 bool PPMonoidEvBigExpImpl::myCheckExponents(const std::vector<BigInt>& expv) const 1058 { 1059 // Check len(expv) == myNumIndets. 1060 // Check exps are non-neg and not too big. 1061 if (len(expv) != myNumIndets) return false; 1062 for (long i=0; i < myNumIndets; ++i) 1063 if (expv[i] < 0) return false; 1064 return true; 1065 } 1066 1067 1068 //---- Constructors & destructor ----// 1069 PPMonoidEvBigExpImpl(const std::vector<symbol> & IndetNames,const PPOrdering & ord)1070 PPMonoidEvBigExpImpl::PPMonoidEvBigExpImpl(const std::vector<symbol>& IndetNames, const PPOrdering& ord): 1071 PPMonoidBase(ord, IndetNames), 1072 myEntrySize(sizeof(BigInt)*NumIndets(ord)), 1073 myMemMgr(myEntrySize, "PPMonoidEvBigExpImpl.myMemMgr"), 1074 myIndetVector() 1075 { 1076 // Put the correct implementation in myOrdPtr... [VERY UGLY CODE!!!] 1077 if (IsLex(ord)) 1078 myOrdPtr.reset(new LexImpl(myNumIndets)); 1079 else if (IsStdDegLex(ord)) 1080 myOrdPtr.reset(new StdDegLexImpl(myNumIndets)); 1081 else if (IsStdDegRevLex(ord)) 1082 myOrdPtr.reset(new StdDegRevLexImpl(myNumIndets)); 1083 else 1084 myOrdPtr.reset(new MatrixOrderingImpl(myNumIndets, GradingDim(ord), OrdMat(ord))); 1085 1086 myRefCountInc(); // this is needed for exception cleanliness, in case one of the lines below throws 1087 myOnePtr.reset(new PPMonoidElem(PPMonoid(this))); 1088 { 1089 // IMPORTANT: this block destroys pp *before* the call to myRefCountZero. 1090 PPMonoidElem pp(PPMonoid(this)); 1091 vector<long> expv(myNumIndets); 1092 for (long i=0; i < myNumIndets; ++i) 1093 { 1094 expv[i] = 1; 1095 myAssign(raw(pp), expv); 1096 myIndetVector.push_back(pp); 1097 expv[i] = 0; 1098 } 1099 } 1100 myRefCountZero(); 1101 } 1102 1103 ~PPMonoidEvBigExpImpl()1104 PPMonoidEvBigExpImpl::~PPMonoidEvBigExpImpl() 1105 {} 1106 1107 ///////////////////////////////////////////////////////////////////////////// 1108 1109 1110 myIndets()1111 const std::vector<PPMonoidElem>& PPMonoidEvBigExpImpl::myIndets() const 1112 { 1113 return myIndetVector; 1114 } 1115 1116 myOne()1117 const PPMonoidElem& PPMonoidEvBigExpImpl::myOne() const 1118 { 1119 return *myOnePtr; 1120 } 1121 1122 myNew()1123 PPMonoidElemRawPtr PPMonoidEvBigExpImpl::myNew() const 1124 { 1125 PPMonoidElemRawPtr rawpp(myMemMgr.alloc()); 1126 BigInt* const expv = myExpv(rawpp); 1127 for (long i=0; i < myNumIndets; ++i) // BUG BUG: if this throws, rawpp is leaked 1128 new(&expv[i]) BigInt; 1129 myAssignOne(rawpp); // cannot throw 1130 return rawpp; 1131 } 1132 myNew(PPMonoidElemConstRawPtr rawcopypp)1133 PPMonoidElemRawPtr PPMonoidEvBigExpImpl::myNew(PPMonoidElemConstRawPtr rawcopypp) const 1134 { 1135 PPMonoidElemRawPtr rawpp(myMemMgr.alloc()); 1136 BigInt* const expv = myExpv(rawpp); 1137 for (long i=0; i < myNumIndets; ++i) // BUG BUG: if this throws, rawpp is leaked 1138 new(&expv[i]) BigInt; 1139 myAssign(rawpp, rawcopypp); // cannot throw 1140 return rawpp; 1141 } 1142 1143 myNew(const std::vector<long> & expv)1144 PPMonoidElemRawPtr PPMonoidEvBigExpImpl::myNew(const std::vector<long>& expv) const 1145 { 1146 CoCoA_ASSERT(myCheckExponents(expv)); 1147 PPMonoidElemRawPtr rawpp(myMemMgr.alloc()); 1148 BigInt* const expv1 = myExpv(rawpp); 1149 for (long i=0; i < myNumIndets; ++i) // BUG BUG: if this throws, rawpp is leaked 1150 new(&expv1[i]) BigInt; 1151 myAssign(rawpp, expv); // cannot throw 1152 return rawpp; 1153 } 1154 1155 myNew(const std::vector<BigInt> & EXPV)1156 PPMonoidElemRawPtr PPMonoidEvBigExpImpl::myNew(const std::vector<BigInt>& EXPV) const 1157 { 1158 CoCoA_ASSERT(myCheckExponents(EXPV)); 1159 PPMonoidElemRawPtr rawpp(myMemMgr.alloc()); 1160 BigInt* const expv = myExpv(rawpp); 1161 for (long i=0; i < myNumIndets; ++i) // BUG BUG: if this throws, rawpp is leaked 1162 new(&expv[i]) BigInt; 1163 for (long i = 0; i < myNumIndets; ++i) 1164 expv[i] = EXPV[i]; 1165 return rawpp; 1166 } 1167 1168 myAssignOne(RawPtr rawpp)1169 void PPMonoidEvBigExpImpl::myAssignOne(RawPtr rawpp) const 1170 { 1171 BigInt* const expv = myExpv(rawpp); 1172 for (long i = 0; i < myNumIndets; ++i) 1173 expv[i] = 0; 1174 } 1175 1176 myAssign(RawPtr rawpp,ConstRawPtr rawpp1)1177 void PPMonoidEvBigExpImpl::myAssign(RawPtr rawpp, ConstRawPtr rawpp1) const 1178 { 1179 if (rawpp == rawpp1) return; 1180 1181 BigInt* const expv = myExpv(rawpp); 1182 const BigInt* const expv1 = myExpv(rawpp1); 1183 std::copy(&expv1[0], &expv1[myNumIndets], &expv[0]); 1184 } 1185 myAssign(RawPtr rawpp,const vector<long> & expv1)1186 void PPMonoidEvBigExpImpl::myAssign(RawPtr rawpp, const vector<long>& expv1) const 1187 { 1188 CoCoA_ASSERT(myCheckExponents(expv1)); 1189 1190 BigInt* const expv = myExpv(rawpp); 1191 for (long i = 0; i < myNumIndets; ++i) 1192 expv[i] = expv1[i]; 1193 } 1194 1195 myDelete(RawPtr rawpp)1196 void PPMonoidEvBigExpImpl::myDelete(RawPtr rawpp) const 1197 { 1198 BigInt* const expv = myExpv(rawpp);; 1199 for (long i=0; i < myNumIndets; ++i) 1200 expv[i].~BigInt(); 1201 myMemMgr.free(rawpp.myRawPtr()); 1202 } 1203 1204 mySwap(RawPtr rawpp1,RawPtr rawpp2)1205 void PPMonoidEvBigExpImpl::mySwap(RawPtr rawpp1, RawPtr rawpp2) const 1206 { 1207 if (rawpp1 == rawpp2) return; 1208 BigInt* const expv1 = myExpv(rawpp1); 1209 BigInt* expv2 = myExpv(rawpp2); 1210 for (long i = 0; i < myNumIndets; ++i) 1211 std::swap(expv1[i], expv2[i]); 1212 } 1213 1214 myMul(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)1215 void PPMonoidEvBigExpImpl::myMul(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 1216 { 1217 BigInt* const expv = myExpv(rawpp); 1218 const BigInt* const expv1 = myExpv(rawpp1); 1219 const BigInt* const expv2 = myExpv(rawpp2); 1220 for (long i = 0; i < myNumIndets; ++i) 1221 expv[i] = expv1[i] + expv2[i]; 1222 } 1223 1224 myMulIndetPower(RawPtr rawpp,long indet,long exp)1225 void PPMonoidEvBigExpImpl::myMulIndetPower(RawPtr rawpp, long indet, long exp) const // assumes exp >= 0 1226 { 1227 CoCoA_ASSERT(exp >= 0); 1228 CoCoA_ASSERT(0 <= indet && indet < myNumIndets); 1229 BigInt* const expv = myExpv(rawpp); 1230 expv[indet] += exp; 1231 } 1232 1233 1234 // This fn overrides the default defn in PPMonoid.C (which throws for big exps) myMulIndetPower(RawPtr rawpp,long indet,const BigInt & EXP)1235 void PPMonoidEvBigExpImpl::myMulIndetPower(RawPtr rawpp, long indet, const BigInt& EXP) const 1236 { 1237 CoCoA_ASSERT(0 <= indet && indet < myNumIndets); 1238 CoCoA_ASSERT(EXP >= 0); 1239 BigInt* const expv = myExpv(rawpp); 1240 expv[indet] += EXP; 1241 } 1242 1243 myDiv(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)1244 void PPMonoidEvBigExpImpl::myDiv(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 1245 { 1246 BigInt* const expv = myExpv(rawpp); 1247 const BigInt* const expv1 = myExpv(rawpp1); 1248 const BigInt* const expv2 = myExpv(rawpp2); 1249 for (long i = 0; i < myNumIndets; ++i) 1250 expv[i] = expv1[i] - expv2[i]; // assert that result is positive? 1251 } 1252 1253 myColon(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)1254 void PPMonoidEvBigExpImpl::myColon(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 1255 { 1256 // No worries about aliasing. 1257 BigInt* const expv = myExpv(rawpp); 1258 const BigInt* const expv1 = myExpv(rawpp1); 1259 const BigInt* const expv2 = myExpv(rawpp2); 1260 1261 for (long i = 0; i < myNumIndets; ++i) 1262 if (expv1[i] > expv2[i]) 1263 expv[i] = expv1[i] - expv2[i]; 1264 else 1265 expv[i] = 0; 1266 } 1267 1268 myGcd(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)1269 void PPMonoidEvBigExpImpl::myGcd(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 1270 { 1271 // No worries about aliasing. 1272 BigInt* const expv = myExpv(rawpp); 1273 const BigInt* const expv1 = myExpv(rawpp1); 1274 const BigInt* const expv2 = myExpv(rawpp2); 1275 1276 for (long i = 0; i < myNumIndets; ++i) 1277 expv[i] = min(expv1[i], expv2[i]); 1278 } 1279 1280 myLcm(RawPtr rawpp,ConstRawPtr rawpp1,ConstRawPtr rawpp2)1281 void PPMonoidEvBigExpImpl::myLcm(RawPtr rawpp, ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 1282 { 1283 // No worries about aliasing. 1284 BigInt* const expv = myExpv(rawpp); 1285 const BigInt* const expv1 = myExpv(rawpp1); 1286 const BigInt* const expv2 = myExpv(rawpp2); 1287 1288 for (long i = 0; i < myNumIndets; ++i) 1289 expv[i] = max(expv1[i], expv2[i]); 1290 } 1291 1292 myRadical(RawPtr rawpp,ConstRawPtr rawpp1)1293 void PPMonoidEvBigExpImpl::myRadical(RawPtr rawpp, ConstRawPtr rawpp1) const 1294 { 1295 BigInt* const expv = myExpv(rawpp); 1296 const BigInt* const expv1 = myExpv(rawpp1); 1297 1298 for (long i = 0; i < myNumIndets; ++i) 1299 expv[i] = (expv1[i] > 0); 1300 } 1301 1302 myPowerSmallExp(RawPtr rawpp,ConstRawPtr rawpp1,long exp)1303 void PPMonoidEvBigExpImpl::myPowerSmallExp(RawPtr rawpp, ConstRawPtr rawpp1, long exp) const // assumes exp >= 0 1304 { 1305 CoCoA_ASSERT(exp >= 0); 1306 BigInt* const expv = myExpv(rawpp); 1307 const BigInt* const expv1 = myExpv(rawpp1); 1308 1309 for (long i = 0; i < myNumIndets; ++i) 1310 expv[i] = exp * expv1[i]; 1311 } 1312 1313 myPowerOverflowCheck(ConstRawPtr,long exp)1314 void PPMonoidEvBigExpImpl::myPowerOverflowCheck(ConstRawPtr /*rawpp*/, long exp) const 1315 { 1316 (void)(exp); // just to avoid compiler warning 1317 CoCoA_ASSERT(exp >= 0); 1318 // nothing to check -- exps here cannot overflow :-) 1319 } 1320 1321 myIsOne(ConstRawPtr rawpp)1322 bool PPMonoidEvBigExpImpl::myIsOne(ConstRawPtr rawpp) const 1323 { 1324 const BigInt* const expv = myExpv(rawpp); 1325 1326 for (long i = 0; i < myNumIndets; ++i) 1327 if (!IsZero(expv[i])) return false; 1328 1329 return true; 1330 } 1331 1332 myIsIndet(long & index,ConstRawPtr rawpp)1333 bool PPMonoidEvBigExpImpl::myIsIndet(long& index, ConstRawPtr rawpp) const 1334 { 1335 const BigInt* const expv = myExpv(rawpp); 1336 long j = myNumIndets; 1337 for (long i = 0; i < myNumIndets; ++i) 1338 { 1339 if (IsZero(expv[i])) continue; 1340 if (j != myNumIndets || !IsOne(expv[i])) return false; 1341 j = i; 1342 } 1343 if (j == myNumIndets) return false; 1344 index = j; 1345 return true; 1346 } 1347 1348 myIsIndetPosPower(long & index,BigInt & EXP,ConstRawPtr rawpp)1349 bool PPMonoidEvBigExpImpl::myIsIndetPosPower(long& index, BigInt& EXP, ConstRawPtr rawpp) const 1350 { 1351 const BigInt* const expv = myExpv(rawpp); 1352 long j = myNumIndets; 1353 for (long i = 0; i < myNumIndets; ++i) 1354 { 1355 if (IsZero(expv[i])) continue; 1356 if (j != myNumIndets) return false; 1357 j = i; 1358 } 1359 if (j == myNumIndets) return false; 1360 index = j; 1361 EXP = expv[index]; 1362 return true; 1363 } 1364 myIsIndetPosPower(long & index,long & pow,ConstRawPtr rawpp)1365 bool PPMonoidEvBigExpImpl::myIsIndetPosPower(long& index, long& pow, ConstRawPtr rawpp) const 1366 { 1367 BigInt POW; 1368 long TmpIndex, TmpPow; 1369 if (!myIsIndetPosPower(TmpIndex, POW, rawpp)) return false; 1370 if (!IsConvertible(TmpPow, POW)) 1371 CoCoA_ERROR(ERR::ArgTooBig, "PPMonoidEvBigExpImpl::myIsIndetPosPower"); 1372 index = TmpIndex; 1373 pow = TmpPow; 1374 return true; 1375 } 1376 myIsIndetPosPower(ConstRawPtr rawpp)1377 bool PPMonoidEvBigExpImpl::myIsIndetPosPower(ConstRawPtr rawpp) const 1378 { 1379 const BigInt* const expv = myExpv(rawpp); 1380 long j = myNumIndets; 1381 for (long i = 0; i < myNumIndets; ++i) 1382 { 1383 if (IsZero(expv[i])) continue; 1384 if (j != myNumIndets) return false; 1385 j = i; 1386 } 1387 return j != myNumIndets; 1388 } 1389 1390 myIsCoprime(ConstRawPtr rawpp1,ConstRawPtr rawpp2)1391 bool PPMonoidEvBigExpImpl::myIsCoprime(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 1392 { 1393 const BigInt* const expv1 = myExpv(rawpp1); 1394 const BigInt* const expv2 = myExpv(rawpp2); 1395 1396 for (long i = 0; i < myNumIndets; ++i) 1397 if (!IsZero(expv1[i]) && !IsZero(expv2[i])) return false; 1398 1399 return true; 1400 } 1401 1402 myIsEqual(ConstRawPtr rawpp1,ConstRawPtr rawpp2)1403 bool PPMonoidEvBigExpImpl::myIsEqual(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 1404 { 1405 const BigInt* const expv1 = myExpv(rawpp1); 1406 const BigInt* const expv2 = myExpv(rawpp2); 1407 1408 for (long i = 0; i < myNumIndets; ++i) 1409 if (expv1[i] != expv2[i]) return false; 1410 return true; 1411 } 1412 1413 myIsDivisible(ConstRawPtr rawpp1,ConstRawPtr rawpp2)1414 bool PPMonoidEvBigExpImpl::myIsDivisible(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 1415 { 1416 const BigInt* const expv1 = myExpv(rawpp1); 1417 const BigInt* const expv2 = myExpv(rawpp2); 1418 1419 for (long i = 0; i < myNumIndets; ++i) 1420 if (expv1[i] < expv2[i]) return false; 1421 1422 return true; 1423 } 1424 1425 myIsSqFree(ConstRawPtr rawpp)1426 bool PPMonoidEvBigExpImpl::myIsSqFree(ConstRawPtr rawpp) const 1427 { 1428 const BigInt* const expv = myExpv(rawpp); 1429 1430 for (long i = 0; i < myNumIndets; ++i) 1431 if (expv[i] > 1) return false; 1432 1433 return true; 1434 } 1435 1436 myCmp(ConstRawPtr rawpp1,ConstRawPtr rawpp2)1437 int PPMonoidEvBigExpImpl::myCmp(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 1438 { 1439 return myOrdPtr->myCmpExpvs(myExpv(rawpp1), myExpv(rawpp2)); 1440 } 1441 1442 myStdDeg(ConstRawPtr rawpp)1443 long PPMonoidEvBigExpImpl::myStdDeg(ConstRawPtr rawpp) const 1444 { 1445 const BigInt* const expv = myExpv(rawpp); 1446 BigInt d; 1447 for (long i=0; i < myNumIndets; ++i) 1448 d += expv[i]; 1449 long ans; 1450 if (!IsConvertible(ans, d)) 1451 CoCoA_ERROR(ERR::ArgTooBig, "PPMonoidEvBigExpImpl::myStdDeg"); 1452 return ans; 1453 } 1454 1455 myWDeg(degree & d,ConstRawPtr rawpp)1456 void PPMonoidEvBigExpImpl::myWDeg(degree& d, ConstRawPtr rawpp) const 1457 { 1458 myOrdPtr->myWDeg(d, myExpv(rawpp)); 1459 } 1460 1461 myCmpWDeg(ConstRawPtr rawpp1,ConstRawPtr rawpp2)1462 int PPMonoidEvBigExpImpl::myCmpWDeg(ConstRawPtr rawpp1, ConstRawPtr rawpp2) const 1463 { 1464 return myOrdPtr->myCmpWDeg(myExpv(rawpp1), myExpv(rawpp2)); 1465 } 1466 1467 myCmpWDegPartial(ConstRawPtr rawpp1,ConstRawPtr rawpp2,long GrDim)1468 int PPMonoidEvBigExpImpl::myCmpWDegPartial(ConstRawPtr rawpp1, ConstRawPtr rawpp2, long GrDim) const 1469 { 1470 return myOrdPtr->myCmpWDegPartial(myExpv(rawpp1), myExpv(rawpp2), GrDim); 1471 } 1472 1473 myExponent(ConstRawPtr rawpp,long indet)1474 long PPMonoidEvBigExpImpl::myExponent(ConstRawPtr rawpp, long indet) const 1475 { 1476 CoCoA_ASSERT(0 <= indet && indet < myNumIndets); 1477 long ans; 1478 if (!IsConvertible(ans, myExpv(rawpp)[indet])) 1479 CoCoA_ERROR(ERR::ArgTooBig, "PPMonoidEvBigExpImpl::myExponent"); 1480 return ans; 1481 } 1482 myBigExponent(BigInt & EXP,ConstRawPtr rawpp,long indet)1483 void PPMonoidEvBigExpImpl::myBigExponent(BigInt& EXP, ConstRawPtr rawpp, long indet) const 1484 { 1485 CoCoA_ASSERT(0 <= indet && indet < myNumIndets); 1486 EXP = myExpv(rawpp)[indet]; 1487 } 1488 1489 myExponents(vector<long> & v,ConstRawPtr rawpp)1490 void PPMonoidEvBigExpImpl::myExponents(vector<long>& v, ConstRawPtr rawpp) const 1491 { 1492 CoCoA_ASSERT(len(v) == myNumIndets); 1493 const BigInt* const expv = myExpv(rawpp); 1494 bool OK = true; 1495 for (long i=0; i < myNumIndets; ++i) 1496 { 1497 if (!IsConvertible(v[i], expv[i])) 1498 { 1499 OK = false; 1500 if (expv[i] > 0) 1501 v[i] = numeric_limits<long>::max(); 1502 else 1503 v[i] = numeric_limits<long>::min(); 1504 } 1505 if (!OK) 1506 CoCoA_ERROR(ERR::ArgTooBig, "PPMonoidEvBigExpImpl::myExponents"); 1507 } 1508 } 1509 1510 myBigExponents(vector<BigInt> & expv,ConstRawPtr rawpp)1511 void PPMonoidEvBigExpImpl::myBigExponents(vector<BigInt>& expv, ConstRawPtr rawpp) const 1512 { 1513 CoCoA_ASSERT(len(expv) == myNumIndets); 1514 const BigInt* const v = myExpv(rawpp); 1515 for (long i=0; i < myNumIndets; ++i) expv[i] = v[i]; 1516 } 1517 1518 myIndetsIn(std::vector<bool> & v,ConstRawPtr rawpp)1519 void PPMonoidEvBigExpImpl::myIndetsIn(std::vector<bool>& v, ConstRawPtr rawpp) const 1520 { 1521 CoCoA_ASSERT(len(v) == myNumIndets); 1522 const BigInt* const expv = myExpv(rawpp); 1523 for (long i=0; i < myNumIndets; ++i) 1524 if (!IsZero(expv[i])) 1525 v[i] = true; 1526 } 1527 1528 myComputeDivMask(DivMask &,const DivMaskRule &,ConstRawPtr)1529 void PPMonoidEvBigExpImpl::myComputeDivMask(DivMask& /*dm*/, const DivMaskRule& /*DivMaskImpl*/, ConstRawPtr /*rawpp*/) const 1530 { 1531 CoCoA_ERROR(ERR::NYI, "PPMonoidEvBigExpImpl::myComputeDivMask"); 1532 // BUG BUG can't do this (yet) DivMaskImpl->myAssignFromExpv(dm, myExpv(rawpp), myNumIndets); 1533 } 1534 1535 myOutputSelf(std::ostream & out)1536 void PPMonoidEvBigExpImpl::myOutputSelf(std::ostream& out) const 1537 { 1538 if (!out) return; // short-cut for bad ostreams 1539 out << "PPMonoidBigEv(" << myNumIndets << ", " << myOrd <<")"; 1540 } 1541 1542 myDebugPrint(std::ostream & out,ConstRawPtr rawpp)1543 void PPMonoidEvBigExpImpl::myDebugPrint(std::ostream& out, ConstRawPtr rawpp) const 1544 { 1545 if (!out) return; // short-cut for bad ostreams 1546 out << "DEBUG PP: myNumIndets=" << myNumIndets << ", exps=["; 1547 for (long i=0; i < myNumIndets; ++i) 1548 out << myExponent(rawpp, i) << " "; 1549 out << "]" << std::endl; 1550 } 1551 1552 1553 //--- orderings ---------------------------------------- 1554 CmpBase(long NumIndets,long GradingDim)1555 PPMonoidEvBigExpImpl::CmpBase::CmpBase(long NumIndets, long GradingDim): 1556 myNumIndets(NumIndets), 1557 myGradingDim(GradingDim) 1558 { 1559 CoCoA_ASSERT(NumIndets > 0); 1560 CoCoA_ASSERT(NumIndets < 1000000); // complain about ridiculously large number of indets 1561 CoCoA_ASSERT(0 <= GradingDim && GradingDim <= NumIndets); 1562 } 1563 1564 1565 //--- LexImpl 1566 LexImpl(long NumIndets)1567 PPMonoidEvBigExpImpl::LexImpl::LexImpl(long NumIndets): 1568 CmpBase(NumIndets, 0) 1569 { 1570 } 1571 1572 myCmpExpvs(const BigInt * v1,const BigInt * v2)1573 int PPMonoidEvBigExpImpl::LexImpl::myCmpExpvs(const BigInt* v1, const BigInt* v2) const 1574 { 1575 for (long i=0; i<myNumIndets; ++i) 1576 if (v1[i] != v2[i]) return (v1[i]>v2[i] ? 1 : -1 ); 1577 return 0; 1578 } 1579 1580 myWDeg(degree &,const BigInt *)1581 void PPMonoidEvBigExpImpl::LexImpl::myWDeg(degree& /*d*/, const BigInt* /*v*/) const 1582 { 1583 // deliberately does nothing because GradingDim=0 1584 //??? should it assign: d = [] 1585 } 1586 1587 myCmpWDegPartial(const BigInt *,const BigInt *,long)1588 int PPMonoidEvBigExpImpl::LexImpl::myCmpWDegPartial(const BigInt* /*v1*/, const BigInt* /*v2*/, long /*GrDim*/) const 1589 { 1590 return 0; // GradingDim=0, and all degrees in Z^0 are equal 1591 } 1592 1593 //--- StdDegLexImpl 1594 StdDegLexImpl(long NumIndets)1595 PPMonoidEvBigExpImpl::StdDegLexImpl::StdDegLexImpl(long NumIndets): 1596 CmpBase(NumIndets, 1) 1597 { 1598 } 1599 1600 myWDeg(degree & d,const BigInt * v)1601 void PPMonoidEvBigExpImpl::StdDegLexImpl::myWDeg(degree& d, const BigInt* v) const 1602 { 1603 BigInt deg; 1604 for (long i=0; i < myNumIndets; ++i) 1605 deg += v[i]; 1606 SetComponent(d, 0, deg); 1607 } 1608 1609 myCmpExpvs(const BigInt * v1,const BigInt * v2)1610 int PPMonoidEvBigExpImpl::StdDegLexImpl::myCmpExpvs(const BigInt* v1, const BigInt* v2) const 1611 { 1612 BigInt deg1; 1613 BigInt deg2; 1614 for (long i=0; i < myNumIndets; ++i) 1615 { 1616 deg1 += v1[i]; 1617 deg2 += v2[i]; 1618 } 1619 if (deg1 != deg2) return (deg1>deg2 ? 1 : -1 ); 1620 1621 for (long i=0; i < myNumIndets; ++i) 1622 if (v1[i] != v2[i]) return (v1[i]>v2[i] ? 1 : -1 ); 1623 return 0; 1624 } 1625 1626 myCmpWDegPartial(const BigInt * v1,const BigInt * v2,long GrDim)1627 int PPMonoidEvBigExpImpl::StdDegLexImpl::myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const 1628 { 1629 CoCoA_ASSERT(0 <= GrDim && GrDim <= 1); 1630 if (GrDim == 0) return 0; // ie: wrt to 0-grading 1631 BigInt deg1; 1632 BigInt deg2; 1633 for (long i=0; i < myNumIndets; ++i) 1634 { 1635 deg1 += v1[i]; 1636 deg2 += v2[i]; 1637 } 1638 if (deg1 != deg2) return (deg1>deg2 ? 1 : -1 ); 1639 return 0; 1640 } 1641 1642 1643 //--- StdDegRevLexImpl 1644 StdDegRevLexImpl(long NumIndets)1645 PPMonoidEvBigExpImpl::StdDegRevLexImpl::StdDegRevLexImpl(long NumIndets): 1646 CmpBase(NumIndets, 1) 1647 { 1648 } 1649 1650 myWDeg(degree & d,const BigInt * v)1651 void PPMonoidEvBigExpImpl::StdDegRevLexImpl::myWDeg(degree& d, const BigInt* v) const 1652 { 1653 BigInt deg; 1654 for (long i=0; i < myNumIndets; ++i) 1655 deg += v[i]; 1656 SetComponent(d, 0, deg); 1657 } 1658 1659 myCmpExpvs(const BigInt * v1,const BigInt * v2)1660 int PPMonoidEvBigExpImpl::StdDegRevLexImpl::myCmpExpvs(const BigInt* v1, const BigInt* v2) const 1661 { 1662 BigInt deg1; 1663 BigInt deg2; 1664 for (long i=0; i < myNumIndets; ++i) 1665 { 1666 deg1 += v1[i]; 1667 deg2 += v2[i]; 1668 } 1669 if (deg1 != deg2) return (deg1>deg2 ? 1 : -1 ); 1670 1671 for (long i = myNumIndets-1; i>0; --i) 1672 if (v1[i] != v2[i]) return (v1[i]>v2[i] ? -1 : 1 ); 1673 return 0; 1674 } 1675 1676 myCmpWDegPartial(const BigInt * v1,const BigInt * v2,long GrDim)1677 int PPMonoidEvBigExpImpl::StdDegRevLexImpl::myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const 1678 { 1679 CoCoA_ASSERT(0 <= GrDim && GrDim <= 1); 1680 if (GrDim == 0) return 0; // ie: wrt to 0-grading 1681 BigInt deg1; 1682 BigInt deg2; 1683 for (long i=0; i < myNumIndets; ++i) 1684 { 1685 deg1 += v1[i]; 1686 deg2 += v2[i]; 1687 } 1688 if (deg1 != deg2) return (deg1>deg2 ? 1 : -1 ); 1689 return 0; 1690 } 1691 1692 1693 //--- MatrixOrderingImpl 1694 MatrixOrderingImpl(long NumIndets,long GradingDim,const ConstMatrixView & OrderMatrix)1695 PPMonoidEvBigExpImpl::MatrixOrderingImpl::MatrixOrderingImpl(long NumIndets, long GradingDim, const ConstMatrixView& OrderMatrix): 1696 CmpBase(NumIndets, GradingDim) 1697 { 1698 CoCoA_ASSERT(0 <= NumIndets); 1699 CoCoA_ASSERT(0 <= GradingDim && GradingDim <= NumIndets); 1700 CoCoA_ASSERT(NumRows(OrderMatrix) == NumIndets); 1701 CoCoA_ASSERT(NumCols(OrderMatrix) == NumIndets); 1702 1703 myOrderMatrix.resize(NumIndets, vector<BigInt>(NumIndets)); 1704 for (long i=0; i < NumIndets; ++i) 1705 for (long j=0; j < NumIndets; ++j) 1706 myOrderMatrix[i][j] = ConvertTo<BigInt>(OrderMatrix(i,j)); 1707 } 1708 1709 myWDeg(degree & d,const BigInt * v)1710 void PPMonoidEvBigExpImpl::MatrixOrderingImpl::myWDeg(degree& d, const BigInt* v) const 1711 { 1712 BigInt deg; 1713 for (long g=0; g < myGradingDim; ++g) 1714 { 1715 deg = 0; 1716 for (long i=0; i < myNumIndets; ++i) 1717 deg += v[i] * myOrderMatrix[g][i]; 1718 SetComponent(d, g, deg); 1719 } 1720 } 1721 1722 MatrixOrderingCmpArrays(const vector<vector<BigInt>> & M,const BigInt * v1,const BigInt * v2,long UpTo)1723 static int MatrixOrderingCmpArrays(const vector<vector<BigInt> >& M, const BigInt* v1, const BigInt* v2, long UpTo) 1724 { 1725 CoCoA_ASSERT(0 <= UpTo && UpTo <= len(M)); 1726 BigInt s1, s2; // automatically set to 0 1727 const long ncols = len(M[0]); 1728 for (long r=0; r < UpTo; ++r) 1729 { 1730 for (long i=0; i < ncols; ++i) 1731 { 1732 s1 += v1[i]*M[r][i]; 1733 s2 += v2[i]*M[r][i]; 1734 } 1735 if (s1 != s2) return (s1>s2 ? 1 : -1 ); 1736 s1 = 0; 1737 s2 = 0; 1738 } 1739 return 0; 1740 } 1741 1742 myCmpExpvs(const BigInt * v1,const BigInt * v2)1743 int PPMonoidEvBigExpImpl::MatrixOrderingImpl::myCmpExpvs(const BigInt* v1, const BigInt* v2) const 1744 { 1745 return MatrixOrderingCmpArrays(myOrderMatrix, v1, v2, myNumIndets); 1746 } 1747 1748 myCmpWDegPartial(const BigInt * v1,const BigInt * v2,long GrDim)1749 int PPMonoidEvBigExpImpl::MatrixOrderingImpl::myCmpWDegPartial(const BigInt* v1, const BigInt* v2, long GrDim) const 1750 { 1751 CoCoA_ASSERT(0 <= GrDim && GrDim <= myGradingDim); 1752 return MatrixOrderingCmpArrays(myOrderMatrix, v1, v2, GrDim); 1753 } 1754 1755 1756 ////////////////////////////////////////////////////////////////// 1757 // Pseudo-ctors 1758 NewPPMonoidEv(const std::vector<symbol> & IndetNames,const PPOrdering & ord,PPExpSize ExpSize)1759 PPMonoid NewPPMonoidEv(const std::vector<symbol>& IndetNames, const PPOrdering& ord, PPExpSize ExpSize) 1760 { 1761 // Sanity check on the indet names given. 1762 const long nvars = NumIndets(ord); 1763 1764 if (len(IndetNames) != nvars) 1765 CoCoA_ERROR(ERR::BadNumIndets, "NewPPMonoidEv(IndetNames,ord)"); 1766 if (!AreDistinct(IndetNames)) 1767 CoCoA_ERROR(ERR::BadIndetNames, "NewPPMonoidEv(IndetNames,ord)"); 1768 if (!AreArityConsistent(IndetNames)) 1769 CoCoA_ERROR(ERR::BadIndetNames, "NewPPMonoidEv(IndetNames,ord)"); 1770 1771 if (ExpSize == SmallExps) 1772 return PPMonoid(new PPMonoidEvSmallExpImpl(IndetNames, ord)); 1773 return PPMonoid(new PPMonoidEvBigExpImpl(IndetNames, ord)); 1774 } 1775 NewPPMonoidEv(const std::vector<symbol> & IndetNames,const PPOrderingCtor & OrdCtor,PPExpSize ExpSize)1776 PPMonoid NewPPMonoidEv(const std::vector<symbol>& IndetNames, const PPOrderingCtor& OrdCtor, PPExpSize ExpSize) 1777 { 1778 return NewPPMonoidEv(IndetNames, OrdCtor(len(IndetNames)), ExpSize); 1779 } 1780 1781 1782 1783 } // end of namespace CoCoA 1784 1785 1786 // RCS header/log in the next few lines 1787 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/PPMonoidEv.C,v 1.50 2020/02/15 11:10:22 abbott Exp $ 1788 // $Log: PPMonoidEv.C,v $ 1789 // Revision 1.50 2020/02/15 11:10:22 abbott 1790 // Summary: IsIndetPosPower now gives false instead of error for input 1 1791 // 1792 // Revision 1.49 2020/02/11 16:56:41 abbott 1793 // Summary: Corrected last update (see redmine 969) 1794 // 1795 // Revision 1.48 2020/02/11 16:12:18 abbott 1796 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969 1797 // 1798 // Revision 1.47 2019/03/04 10:29:36 abbott 1799 // Summary: Changed auto_ptr into unqiue_ptr 1800 // 1801 // Revision 1.46 2018/05/18 12:15:04 bigatti 1802 // -- renamed IntOperations --> BigIntOps 1803 // 1804 // Revision 1.45 2017/04/18 12:50:06 abbott 1805 // Summary: Corrected ifdef use of CoCoA_THREADSAFE_HACK and CoCoA_DEBUG 1806 // 1807 // Revision 1.44 2016/11/03 12:25:25 abbott 1808 // Summary: Changed IsRadical (for PPMonoidElem) into IsSqFree 1809 // 1810 // Revision 1.43 2015/12/01 13:11:01 abbott 1811 // Summary: Changed mem fn PPOrderingCtor::myCtor into operator(); also for ModuleOrderingCtor; see issue 829 1812 // 1813 // Revision 1.42 2015/11/30 21:53:55 abbott 1814 // Summary: Major update to matrices for orderings (not yet complete, some tests fail) 1815 // 1816 // Revision 1.41 2015/06/30 12:54:07 abbott 1817 // Summary: Added new fn myIndetsIn 1818 // Author: JAA 1819 // 1820 // Revision 1.40 2015/04/16 20:19:39 abbott 1821 // Summary: Silly change to avoid a compiler warning about unused param 1822 // Author: JAA 1823 // 1824 // Revision 1.39 2015/04/16 16:36:33 abbott 1825 // Summary: Cleaned impls of myPowerOverflowCheck 1826 // Author: JAA 1827 // 1828 // Revision 1.38 2015/04/13 16:17:58 abbott 1829 // Summary: Corrected silly typo. 1830 // Author: JAA 1831 // 1832 // Revision 1.37 2015/04/13 14:42:07 abbott 1833 // Summary: Added myPowerOverflowCheck (1st version) 1834 // Author: JAA 1835 // 1836 // Revision 1.36 2014/07/31 13:10:45 bigatti 1837 // -- GetMatrix(PPO) --> OrdMat(PPO) 1838 // -- added OrdMat and GradingMat to PPOrdering, PPMonoid, SparsePolyRing 1839 // 1840 // Revision 1.35 2014/07/03 15:36:35 abbott 1841 // Summary: Cleaned up impl of PPMonoids: moved myIndetSymbols & myNumIndets to base class 1842 // Author: JAA 1843 // 1844 // Revision 1.34 2014/05/14 15:57:15 bigatti 1845 // -- added "using" for clang with superpedantic flag 1846 // 1847 // Revision 1.33 2014/01/28 09:59:10 abbott 1848 // Replaced two calls to IsInteger by calls to ConvertTo<BigInt>. 1849 // 1850 // Revision 1.32 2014/01/16 16:11:43 abbott 1851 // Added some missing const keywords (to local variables) 1852 // 1853 // Revision 1.31 2013/03/15 11:00:50 abbott 1854 // Added check for exponent overflow when powering a PP. 1855 // Merged PPMonoidEv and PPMonoidEvZZ implementations into a single file. 1856 // Implemented new interface for pseudo-ctors for PPMonoidEv which uses a "flag" 1857 // to say whether exponents are big or not. 1858 // 1859 // Revision 1.30 2012/05/28 09:18:21 abbott 1860 // Created IntOperations which gathers together all operations on 1861 // integers (both big and small). Many consequential changes. 1862 // 1863 // Revision 1.29 2012/02/10 17:04:23 abbott 1864 // Removed a commented out decl of a member fn: myNew(vector<BigInt>) 1865 // 1866 // Revision 1.28 2012/01/26 16:50:55 bigatti 1867 // -- changed back_inserter into insert 1868 // 1869 // Revision 1.27 2011/08/14 15:52:17 abbott 1870 // Changed ZZ into BigInt (phase 1: just the library sources). 1871 // 1872 // Revision 1.26 2011/05/03 12:13:12 abbott 1873 // Added static const data member ourMaxExp. 1874 // Code is more readable, and compiler doesn't grumble any more. 1875 // 1876 // Revision 1.25 2011/03/22 23:12:16 abbott 1877 // Removed some spurious junk at the start of the file. 1878 // Corrected copyright years. 1879 // 1880 // Revision 1.24 2011/03/22 22:38:15 abbott 1881 // Fixed some wrong static_casts inside some CoCoA_ASSERTs. 1882 // 1883 // Revision 1.23 2011/03/10 17:47:42 bigatti 1884 // -- fixed a CoCoA_ASSERT 1885 // 1886 // Revision 1.22 2011/03/10 17:26:19 bigatti 1887 // -- changed unsigned long into long in soe CoCoA_ASSERT 1888 // 1889 // Revision 1.21 2011/03/10 16:39:34 abbott 1890 // Replaced (very many) size_t by long in function interfaces (for rings, 1891 // PPMonoids and modules). Also replaced most size_t inside fn defns. 1892 // 1893 // Revision 1.20 2011/03/01 14:14:54 bigatti 1894 // -- made CmpBase dtor non-inline for problems with g++ on some ppc 1895 // 1896 // Revision 1.19 2010/12/17 16:09:51 abbott 1897 // Corrected used of myIndetSymbols in some assertions. 1898 // 1899 // Revision 1.18 2010/11/30 11:18:11 bigatti 1900 // -- renamed IndetName --> IndetSymbol 1901 // 1902 // Revision 1.17 2010/11/05 16:21:08 bigatti 1903 // -- added ZZExponents 1904 // 1905 // Revision 1.16 2010/10/06 14:10:24 abbott 1906 // Added increments to the ref count in ring and PPMonoid ctors to make 1907 // them exception safe. 1908 // 1909 // Revision 1.15 2010/02/03 16:13:52 abbott 1910 // Added new single word tags for specifying the ordering in PPMonoid 1911 // pseudo-ctors. 1912 // 1913 // Revision 1.14 2010/02/02 16:44:31 abbott 1914 // Added radical & IsRadical (via mem fns myRadical & myIsRadical) 1915 // for PPMonoidElems. 1916 // 1917 // Revision 1.13 2009/12/23 18:53:52 abbott 1918 // Major change to conversion functions: 1919 // convert(..) is now a procedure instead of a function 1920 // IsConvertible(..) replaces the former convert(..) function 1921 // Added new NumericCast conversion function (placeholder for BOOST feature) 1922 // Consequent changes in code which uses these features. 1923 // 1924 // Revision 1.12 2009/09/22 14:01:33 bigatti 1925 // -- added myCmpWDegPartial (ugly name, I know....) 1926 // -- cleaned up and realigned code in PPMonoid*.C files 1927 // 1928 // Revision 1.11 2009/07/02 16:34:18 abbott 1929 // Minor change to keep the compiler quiet. 1930 // 1931 // Revision 1.10 2008/03/26 16:52:04 abbott 1932 // Added exponent overflow checks (also for ordvs) when CoCoA_DEBUG is active. 1933 // 1934 // Revision 1.9 2007/12/05 11:06:24 bigatti 1935 // -- changed "size_t StdDeg/myStdDeg(f)" into "long" (and related functions) 1936 // -- changed "log/myLog(f, i)" into "MaxExponent/myMaxExponent(f, i)" 1937 // -- fixed bug in "IsOne(ideal)" in SparsePolyRing.C 1938 // 1939 // Revision 1.8 2007/12/04 14:27:07 bigatti 1940 // -- changed "log(pp, i)" into "exponent(pp, i)" 1941 // 1942 // Revision 1.7 2007/10/30 17:14:07 abbott 1943 // Changed licence from GPL-2 only to GPL-3 or later. 1944 // New version for such an important change. 1945 // 1946 // Revision 1.6 2007/09/25 16:32:30 abbott 1947 // Several minor changes to silence gcc-4.3: 1948 // more #includes, 1949 // and fixed a template problemm in RegisterServerOps.C 1950 // 1951 // Revision 1.5 2007/05/31 14:54:31 bigatti 1952 // -- now using AreDistinct and AreArityConsistent for sanity check on 1953 // indet names 1954 // 1955 // Revision 1.3 2007/05/03 10:35:23 abbott 1956 // Added new PPMonoidEvZZ with (virtually) unlimited exponents. 1957 // Modified test-PPMonoid1.C accordingly. 1958 // Added warning in doc about silent/unchecked exponent overflow in other 1959 // PPMonoids. 1960 // 1961 // Revision 1.2 2007/03/23 18:38:42 abbott 1962 // Separated the "convert" functions (and CheckedCast) into their own files. 1963 // Many consequential changes. Also corrected conversion to doubles. 1964 // 1965 // Revision 1.1.1.1 2007/03/09 15:16:11 abbott 1966 // Imported files 1967 // 1968 // Revision 1.15 2007/03/08 18:22:29 cocoa 1969 // Just whitespace cleaning. 1970 // 1971 // Revision 1.14 2007/03/08 17:43:11 cocoa 1972 // Swapped order of args to the NewPPMonoid pseudo ctors. 1973 // 1974 // Revision 1.13 2007/03/08 11:07:12 cocoa 1975 // Made pseudo ctors for polynomial rings more uniform. This allowed me to 1976 // remove an include of CoCoA/symbol.H from the RingDistrM*.H files, but then 1977 // I had to put the include in several .C files. 1978 // 1979 // Revision 1.12 2006/12/07 17:23:46 cocoa 1980 // -- for compilation with _Wextra: commented out names of unused arguments 1981 // 1982 // Revision 1.11 2006/12/06 17:35:58 cocoa 1983 // -- style: RawPtr args are now called "raw.." 1984 // 1985 // Revision 1.10 2006/11/27 13:06:23 cocoa 1986 // Anna and Michael made me check without writing a proper message. 1987 // 1988 // Revision 1.9 2006/11/24 17:04:32 cocoa 1989 // -- reorganized includes of header files 1990 // 1991 // Revision 1.8 2006/11/23 17:39:11 cocoa 1992 // -- added #include 1993 // 1994 // Revision 1.7 2006/11/16 11:27:20 cocoa 1995 // -- reinserted myRefCountZero(): sometimes really necessary, in general safe 1996 // 1997 // Revision 1.6 2006/11/14 17:29:20 cocoa 1998 // -- commented out myRefCountZero() (not necessary???) 1999 // 2000 // Revision 1.5 2006/10/16 23:18:59 cocoa 2001 // Corrected use of std::swap and various special swap functions. 2002 // Improved myApply memfn for homs of RingDistrMPolyInlPP. 2003 // 2004 // Revision 1.4 2006/10/06 14:04:14 cocoa 2005 // Corrected position of #ifndef in header files. 2006 // Separated CoCoA_ASSERT into assert.H from config.H; 2007 // many minor consequential changes (have to #include assert.H). 2008 // A little tidying of #include directives (esp. in Max's code). 2009 // 2010 // Revision 1.3 2006/08/07 21:23:25 cocoa 2011 // Removed almost all publicly visible references to SmallExponent_t; 2012 // changed to long in all PPMonoid functions and SparsePolyRing functions. 2013 // DivMask remains to sorted out. 2014 // 2015 // Revision 1.2 2006/06/21 17:07:10 cocoa 2016 // Fixed IsIndet bug -- why are there three almost identical copies of code? 2017 // 2018 // Revision 1.1.1.1 2006/05/30 11:39:37 cocoa 2019 // Imported files 2020 // 2021 // Revision 1.9 2006/04/27 13:45:30 cocoa 2022 // Changed name of NewIdentityRingHom to NewIdentityHom. 2023 // Changed name of member functions which print out their own object 2024 // into myOutputSelf (to distinguish from "transitive" myOutput fns). 2025 // 2026 // Revision 1.8 2006/03/27 12:21:25 cocoa 2027 // Minor silly changes to reduce number of complaints from some compiler or other. 2028 // 2029 // Revision 1.7 2006/03/15 18:09:31 cocoa 2030 // Changed names of member functions which print out their object 2031 // into myOutputSelf -- hope this will appease the Intel C++ compiler. 2032 // 2033 // Revision 1.6 2006/03/14 17:21:18 cocoa 2034 // Moved concrete PPMonoid impls entirely into their respective .C files. 2035 // Now the corresponding .H files are very compact. 2036 // 2037 // Revision 1.5 2006/03/12 21:28:33 cocoa 2038 // Major check in after many changes 2039 // 2040 // Revision 1.4 2006/02/20 22:41:20 cocoa 2041 // All forms of the log function for power products now return SmallExponent_t 2042 // (instead of int). exponents now resizes the vector rather than requiring 2043 // the user to pass in the correct size. 2044 // 2045 // Revision 1.3 2006/01/17 10:23:08 cocoa 2046 // Updated DivMask; many consequential changes. 2047 // A few other minor fixes. 2048 // 2049 // Revision 1.2 2005/11/17 13:25:13 cocoa 2050 // -- "unsigned int" --> "SmallExponent_t" in ctor PPMonoidEvImpl(o, IndetNames) 2051 // 2052 // Revision 1.1.1.1 2005/10/17 10:46:54 cocoa 2053 // Imported files 2054 // 2055 // Revision 1.9 2005/10/11 16:37:30 cocoa 2056 // Added new small prime finite field class (see RingFpDouble). 2057 // 2058 // Cleaned makefiles and configuration script. 2059 // 2060 // Tidied PPMonoid code (to eliminate compiler warnings). 2061 // 2062 // Fixed bug in RingFloat::myIsInteger. 2063 // 2064 // Revision 1.8 2005/08/08 16:36:32 cocoa 2065 // Just checking in before going on holiday. 2066 // Don't really recall what changes have been made. 2067 // Added IsIndet function for RingElem, PPMonoidElem, 2068 // and a member function of OrdvArith. 2069 // Improved the way failed assertions are handled. 2070 // 2071 // Revision 1.7 2005/07/19 15:30:20 cocoa 2072 // A first attempt at iterators over sparse polynomials. 2073 // Main additions are to SparsePolyRing, DistrMPoly*. 2074 // Some consequential changes to PPMonoid*. 2075 // 2076 // Revision 1.6 2005/07/08 15:09:28 cocoa 2077 // Added new symbol class (to represent names of indets). 2078 // Integrated the new class into concrete polynomial rings 2079 // and PPMonoid -- many consequential changes. 2080 // Change ctors for the "inline" sparse poly rings: they no 2081 // longer expect a PPMonoid, but build their own instead 2082 // (has to be a PPMonoidOv). 2083 // 2084 // Revision 1.5 2005/07/01 16:08:15 cocoa 2085 // Friday check-in. Major change to structure under PolyRing: 2086 // now SparsePolyRing and DUPolyRing are separated (in preparation 2087 // for implementing iterators). 2088 // 2089 // A number of other relatively minor changes had to be chased through 2090 // (e.g. IndetPower). 2091 // 2092 // Revision 1.4 2005/06/23 15:42:41 cocoa 2093 // Fixed typo in GNU fdl -- all doc/*.txt files affected. 2094 // Minor corrections to PPMonoid (discovered while writing doc). 2095 // 2096 // Revision 1.3 2005/06/22 14:47:56 cocoa 2097 // PPMonoids and PPMonoidElems updated to mirror the structure 2098 // used for rings and RingElems. Many consequential changes. 2099 // 2100 // Revision 1.2 2005/05/04 16:50:31 cocoa 2101 // -- new code for MatrixOrderingImpl 2102 // -- changed: CmpBase also requires GradingDim 2103 // 2104 // Revision 1.1.1.1 2005/05/03 15:47:31 cocoa 2105 // Imported files 2106 // 2107 // Revision 1.4 2005/04/29 15:42:02 cocoa 2108 // Improved documentation for GMPAllocator. 2109 // Added example program for GMPAllocator. 2110 // Added example program for simple ops on polynomials. 2111 // Added two new ctors for (principal) ideals (from long, and from ZZ). 2112 // Added (crude) printing for PPMonoids. 2113 // Updated library.H (#included GMPAllocator.H). 2114 // 2115 // Revision 1.3 2005/04/20 15:40:48 cocoa 2116 // Major change: modified the standard way errors are to be signalled 2117 // (now via a macro which records filename and line number). Updated 2118 // documentation in error.txt accordingly. 2119 // 2120 // Improved the documentation in matrix.txt (still more work to be done). 2121 // 2122 // Revision 1.2 2005/04/19 14:06:04 cocoa 2123 // Added GPL and GFDL licence stuff. 2124 // 2125 // Revision 1.1.1.1 2005/01/27 15:12:13 cocoa 2126 // Imported files 2127 // 2128 // Revision 1.3 2004/11/25 16:14:21 cocoa 2129 // (1) Fixed definition of specialization of std::swap template function 2130 // so that it compiles with gcc 3.4.3 2131 // (2) Implemented monomial function for polynomial rings. 2132 // (3) Added one(PPM) and PPM->myOne() functions. 2133 // 2134 // Revision 1.2 2004/11/12 15:49:29 cocoa 2135 // Tidying prior to 0.90 release. 2136 // (a) documentation improved (or marked as poor) 2137 // (b) sundry minor improvements to the code 2138 // 2139 // Revision 1.1 2004/11/11 13:45:22 cocoa 2140 // -- renamed: was PPMonoidSafe 2141 // 2142 // Revision 1.3 2004/11/03 17:52:05 cocoa 2143 // -- added just a warning to remind me to implement matrix ordering 2144 // 2145 // Revision 1.2 2004/11/02 14:56:33 cocoa 2146 // -- changed *Print* into *Output* (myPrint --> myOutput) 2147 // -- changed *Var* into *Indet* (myPrintVarName --> myOutputIndetName) 2148 // -- removed suffix "IgnoreDivMask" 2149 // -- added myComputeDivMask 2150 // -- improved storing of IndetNames 2151 // -- changed ExpvElem into SmallExponent_t 2152 // 2153 // Revision 1.1 2004/10/29 15:31:25 cocoa 2154 // -- new PPMonoid for compatibility with OrdvArith (without DivMask) 2155 // 2156