1 // Copyright (c) 2005-2009,2015,2017 John Abbott, Anna M. Bigatti 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 // Source code for class DistMPoly 20 21 #include "CoCoA/DistrMPolyClean.H" 22 23 #include "CoCoA/BigIntOps.H" 24 #include "CoCoA/BigRatOps.H" 25 26 #include <algorithm> 27 //using std::swap; in ourSwap 28 #include <iostream> 29 //using << in output 30 //#include <vector> --- included in DistrMPolyClean.H 31 using std::vector; 32 33 34 namespace CoCoA 35 { 36 IsCompatible(const DistrMPolyClean & f,const DistrMPolyClean & g)37 bool IsCompatible(const DistrMPolyClean& f, const DistrMPolyClean& g) 38 { 39 return (f.myCoeffRing == g.myCoeffRing) && 40 (f.myPPM == g.myPPM) && 41 (&f.myMemMgr == &g.myMemMgr); 42 } 43 44 ourSwap(DistrMPolyClean & f,DistrMPolyClean & g)45 void DistrMPolyClean::ourSwap(DistrMPolyClean& f, DistrMPolyClean& g) 46 { 47 CoCoA_ASSERT(IsCompatible(f, g)); 48 std::swap(f.mySummands, g.mySummands); 49 std::swap(f.myEnd, g.myEnd); 50 if (f.mySummands == nullptr) f.myEnd = &f.mySummands; // CAREFUL if f or g is zero! 51 if (g.mySummands == nullptr) g.myEnd = &g.mySummands; // 52 } 53 54 55 // MemPool DistrMPolyClean::summand::ourMemMgr(sizeof(DistrMPolyClean::summand), 56 // "DistrMPolyClean::summand::ourMemMgr"); 57 58 ourDeleteSummands(DistrMPolyClean::summand * ptr,MemPool & MemMgr)59 void DistrMPolyClean::ourDeleteSummands(DistrMPolyClean::summand* ptr/*,const ring& R, const PPMonoid& M*/, MemPool& MemMgr) 60 { 61 while (ptr != nullptr) 62 { 63 DistrMPolyClean::summand* next = ptr->myNext; 64 ptr->~summand(); 65 MemMgr.free(ptr); 66 ptr = next; 67 } 68 } 69 70 DistrMPolyClean(const ring & R,const PPMonoid & PPM,MemPool & MemMgr)71 DistrMPolyClean::DistrMPolyClean(const ring& R, const PPMonoid& PPM, MemPool& MemMgr): 72 myCoeffRing(R), 73 myPPM(PPM), 74 myMemMgr(MemMgr) 75 { 76 mySummands = nullptr; 77 myEnd = &mySummands; 78 } 79 80 ~DistrMPolyClean()81 DistrMPolyClean::~DistrMPolyClean() 82 { 83 ourDeleteSummands(mySummands/*, myCoeffRing, myPPM*/, myMemMgr); 84 } 85 86 DistrMPolyClean(const DistrMPolyClean & copy)87 DistrMPolyClean::DistrMPolyClean(const DistrMPolyClean& copy): 88 myCoeffRing(copy.myCoeffRing), 89 myPPM(copy.myPPM), 90 myMemMgr(copy.myMemMgr) 91 { 92 mySummands = nullptr; 93 myEnd = &mySummands; 94 // !!! THIS LOOP IS NOT EXCEPTION CLEAN !!! 95 for (summand* it = copy.mySummands; it != nullptr; it = it->myNext) 96 myPushBack(myCopySummand(it)); 97 } 98 99 100 DistrMPolyClean& DistrMPolyClean::operator=(const DistrMPolyClean& rhs) 101 { 102 if (this == &rhs) return *this; 103 DistrMPolyClean copy(rhs); 104 ourSwap(*this, copy); 105 return *this; 106 } 107 108 109 DistrMPolyClean& DistrMPolyClean::operator=(const MachineInt& rhs) 110 { 111 myAssignZero(); 112 if (IsZero(rhs)) return *this; // to avoid needless alloc/free 113 NewSummandPtr t(*this); t.myRenew(); 114 myCoeffRing->myAssign(raw(t->myCoeff), rhs); 115 if (!IsZero(t->myCoeff)) 116 { 117 mySummands = t.relinquish(); 118 myEnd = &mySummands->myNext; 119 } 120 return *this; 121 } 122 123 124 DistrMPolyClean& DistrMPolyClean::operator=(const BigInt& rhs) 125 { 126 myAssignZero(); 127 if (IsZero(rhs)) return *this; // to avoid needless alloc/free 128 NewSummandPtr t(*this); t.myRenew(); 129 myCoeffRing->myAssign(raw(t->myCoeff), rhs); 130 if (!IsZero(t->myCoeff)) 131 { 132 mySummands = t.relinquish(); 133 myEnd = &mySummands->myNext; 134 } 135 return *this; 136 } 137 138 DistrMPolyClean& DistrMPolyClean::operator=(const BigRat& rhs) 139 { 140 myAssignZero(); 141 if (IsZero(rhs)) return *this; // to avoid needless alloc/free 142 NewSummandPtr t(*this); t.myRenew(); 143 myCoeffRing->myAssign(raw(t->myCoeff), rhs); 144 if (!IsZero(t->myCoeff)) 145 { 146 mySummands = t.relinquish(); 147 myEnd = &mySummands->myNext; 148 } 149 return *this; 150 } 151 152 153 //---------------------------------------------------------------------- 154 // operations on summands 155 156 myCopySummand(const summand * original)157 DistrMPolyClean::summand* DistrMPolyClean::myCopySummand(const summand* original) const 158 { 159 NewSummandPtr copy(*this); 160 copy.myRenew(); 161 162 // copy->myCoeff = original->myCoeff; 163 // copy->myPP = original->myPP; 164 myCoeffRing->myAssign(raw(copy->myCoeff), raw(original->myCoeff)); 165 myPPM->myAssign(raw(copy->myPP), raw(original->myPP)); 166 return copy.relinquish(); 167 } 168 169 myAssignZero()170 void DistrMPolyClean::myAssignZero() 171 { 172 ourDeleteSummands(mySummands/*, myCoeffRing, myPPM*/, myMemMgr); 173 mySummands = nullptr; 174 myEnd = &mySummands; 175 } 176 177 myIsEqual(const summand * const lhs,const summand * const rhs)178 bool DistrMPolyClean::myIsEqual(const summand* const lhs, const summand* const rhs) const 179 { 180 return (myPPM->myIsEqual(raw(lhs->myPP), raw(rhs->myPP)) && 181 myCoeffRing->myIsEqual(raw(lhs->myCoeff), raw(rhs->myCoeff))); 182 } 183 184 NumTerms(const DistrMPolyClean & f)185 long NumTerms(const DistrMPolyClean& f) 186 { 187 long nsummands = 0; 188 for (const DistrMPolyClean::summand* it = f.mySummands; it != nullptr; it = it->myNext) 189 ++nsummands; 190 return nsummands; 191 } 192 193 LC(const DistrMPolyClean & f)194 ConstRefRingElem LC(const DistrMPolyClean& f) 195 { 196 CoCoA_ASSERT(!IsZero(f)); 197 return f.mySummands->myCoeff; 198 } 199 200 MoveLMToFront(DistrMPolyClean & f,DistrMPolyClean & g)201 void MoveLMToFront(DistrMPolyClean& f, DistrMPolyClean& g) 202 { 203 CoCoA_ASSERT(!IsZero(g)); 204 205 DistrMPolyClean::summand* ltg = g.mySummands; 206 g.mySummands = g.mySummands->myNext; 207 if (g.mySummands == nullptr) g.myEnd = &(g.mySummands); 208 ltg->myNext = nullptr; 209 f.myPushFront(ltg); 210 } 211 212 MoveLMToBack(DistrMPolyClean & f,DistrMPolyClean & g)213 void MoveLMToBack(DistrMPolyClean& f, DistrMPolyClean& g) 214 { 215 CoCoA_ASSERT(!IsZero(g)); 216 217 DistrMPolyClean::summand* ltg = g.mySummands; 218 g.mySummands = g.mySummands->myNext; 219 if (g.mySummands == nullptr) g.myEnd = &(g.mySummands); 220 ltg->myNext = nullptr; 221 f.myPushBack(ltg); 222 } 223 224 myDeleteLM()225 void DistrMPolyClean::myDeleteLM() 226 { 227 CoCoA_ASSERT(!IsZero(*this)); 228 229 DistrMPolyClean::summand* old_lm = mySummands; 230 mySummands = old_lm->myNext; 231 if (mySummands == nullptr) myEnd = &mySummands; 232 old_lm->myNext = nullptr; 233 ourDeleteSummands(old_lm/*, myCoeffRing, myPPM*/, myMemMgr); 234 } 235 236 237 // void wdeg(degree& d, const DistrMPolyClean& f) 238 // { 239 // CoCoA_ASSERT(!IsZero(f)); 240 // f.myPPM->myWDeg(d, raw(f.mySummands->myPP)); 241 // } 242 243 244 // int CmpWDeg(const DistrMPolyClean& f, const DistrMPolyClean& g) 245 // { 246 // CoCoA_ASSERT(!IsZero(f)); 247 // CoCoA_ASSERT(!IsZero(g)); 248 // if (!DistrMPolyClean::compatible(f, g)) 249 // CoCoA_THROW_ERROR("Incompatible polynomials", "CmpDeg(DistrMPolyClean,DistrMPolyClean)"); 250 // return f.myPPM->myCmpWDeg(raw(f.mySummands->myPP), raw(g.mySummands->myPP)); 251 // } 252 253 254 // This fn offers only the weak exception guarantee!!! myAddMulSummand(const summand * s,const DistrMPolyClean & g,bool SkipLMg)255 void DistrMPolyClean::myAddMulSummand(const summand* s, const DistrMPolyClean& g, bool SkipLMg) // this += s*g 256 { 257 CoCoA_ASSERT(IsCompatible(*this, g)); 258 CoCoA_ASSERT(!IsZero(s->myCoeff)); 259 260 const ring& R = myCoeffRing; 261 262 const summand* g_smnd = g.mySummands; 263 if (SkipLMg) g_smnd = g_smnd->myNext; 264 summand** f_prev = &mySummands; 265 summand* f_smnd = *f_prev; 266 267 NewSummandPtr tmp_smnd(*this); tmp_smnd.myRenew(); 268 RingElem tmp(myCoeffRing); 269 270 int CMP = 0; 271 272 // bool qIsOne = IsOne(s->myPP); 273 bool qIsOne = false; 274 275 for (; f_smnd != nullptr && g_smnd != nullptr; g_smnd = g_smnd->myNext) 276 { 277 R->myMul(raw(tmp_smnd->myCoeff), raw(s->myCoeff), raw(g_smnd->myCoeff)); 278 if (R->myIsZero(raw(tmp_smnd->myCoeff))) 279 continue; // skip this g_smnd as coeff mults to 0 280 myPPM->myMul(raw(tmp_smnd->myPP), raw(s->myPP), raw(g_smnd->myPP)); 281 if (qIsOne) 282 { 283 while (f_smnd != nullptr && (CMP=myPPM->myCmp(raw(f_smnd->myPP), raw(g_smnd->myPP))) >0) 284 f_smnd = *(f_prev = &f_smnd->myNext); 285 myPPM->myAssign(raw(tmp_smnd->myPP), raw(g_smnd->myPP)); 286 } 287 else 288 { 289 // myPPM->myMul(raw(tmp_smnd->myPP), raw(s->myPP), raw(g_smnd->myPP)); 290 while (f_smnd != nullptr && (CMP=myPPM->myCmp(raw(f_smnd->myPP), raw(tmp_smnd->myPP))) >0) 291 f_smnd = *(f_prev = &f_smnd->myNext); 292 } 293 if (f_smnd == nullptr) 294 { 295 // R->myMul(raw(tmp_smnd->myCoeff), raw(s->myCoeff), raw(g_smnd->myCoeff)); 296 myPushBack(tmp_smnd.relinquish()); 297 tmp_smnd.myRenew(); 298 g_smnd = g_smnd->myNext; 299 break; 300 } 301 if (CMP == 0) 302 { 303 // if (R->myIsZeroAddMul(raw(f_smnd->myCoeff), raw(tmp), raw(s->myCoeff), raw(g_smnd->myCoeff))) 304 R->myAdd(raw(f_smnd->myCoeff), raw(f_smnd->myCoeff), raw(tmp_smnd->myCoeff)); 305 if (R->myIsZero(raw(f_smnd->myCoeff))) 306 myRemoveSummand(f_prev); // f_prev = f_prev; 307 else 308 f_prev = &f_smnd->myNext; 309 f_smnd = *f_prev; 310 } 311 else // (CMP < 0) 312 { 313 // R->myMul(raw(tmp_smnd->myCoeff), raw(s->myCoeff), raw(g_smnd->myCoeff)); 314 myInsertSummand(tmp_smnd.relinquish(), f_prev); 315 tmp_smnd.myRenew(); 316 f_prev = &(*f_prev)->myNext; 317 } 318 } 319 for (;g_smnd != nullptr; g_smnd = g_smnd->myNext) 320 { 321 R->myMul(raw(tmp_smnd->myCoeff), raw(s->myCoeff), raw(g_smnd->myCoeff)); 322 if (R->myIsZero(raw(tmp_smnd->myCoeff))) continue; 323 myPPM->myMul(raw(tmp_smnd->myPP), raw(s->myPP), raw(g_smnd->myPP)); 324 myPushBack(tmp_smnd.relinquish()); 325 tmp_smnd.myRenew(); 326 } 327 328 // clog << "AddMul: produced f=";output(clog,f);clog<<std::endl; 329 // clog << "------------------------------------------------------"<<std::endl; 330 331 } 332 333 myAddMulLM(const DistrMPolyClean & h,const DistrMPolyClean & g,bool SkipLMg)334 void DistrMPolyClean::myAddMulLM(const DistrMPolyClean& h, const DistrMPolyClean& g, bool SkipLMg) 335 { //??? 336 if (IsZero(h)) CoCoA_THROW_ERROR(ERR::NotNonZero, "DistrMPolyClean::myAddMul"); 337 myAddMulSummand(h.mySummands, g, SkipLMg); //??? 338 } //??? 339 340 341 // void DistrMPolyClean::myWeylAddMulSummand(const summand* s, const DistrMPolyClean& g, bool SkipLMg) 342 // { 343 // CoCoA_ASSERT(IsCompatible(*this, g)); 344 345 // // const PPOrdering& ord = ordering(myPPM); 346 // const ring& R = myCoeffRing; 347 // const size_t nvars = NumIndets(myPPM); 348 // //??? clog << "AddMul: Doing funny product of the following two polys" << std::endl; 349 // //??? output(clog, g); 350 // //??? CoCoA_ASSERT(myRefCount == 1); 351 // //??? MakeWritable(f); 352 353 // const summand* g_term = g.mySummands; 354 // if (SkipLMg) g_term = g_term->myNext; 355 // //??? summand** f_prev = &mySummands; 356 // //??? summand* f_term = *f_prev; 357 358 // DistrMPolyClean ppg = g; 359 // vector<long> expv(nvars); 360 // myPPM->myExponents(expv, raw(s->myPP)); 361 // //??? clog << "expv: "; for (int i=0; i<myNumIndets;++i) clog << expv[i] << " "; clog << std::endl; 362 // for (size_t indet = nvars/2; indet < nvars; ++indet) 363 // { 364 // long n = expv[indet]; 365 // if (n == 0) continue; 366 // //??? clog << "AddMul: doing D variable with index " << indet - myNumIndets/2 << std::endl; 367 // DistrMPolyClean der = ppg; 368 369 // //??? ppg *= IndetPower(myPPM, indet, n); 370 // ppg.myMulByPP(raw(IndetPower(myPPM, indet, n))); 371 // // mul(raw(ppg), raw(ppg), raw(IndetPower(indet, n))); 372 373 // for (long i=1; i <= n; ++i) 374 // { 375 // deriv(der, der, indet-nvars/2); 376 // //??? deriv(raw(der), raw(der), indet-nvars/2); 377 // //??? clog << "der(" << i << ")="; output(clog, raw(der)); clog << std::endl; 378 379 // // ppg += binomial(n, i)*der*IndetPower(myPPM, indet, n-i); // *IndetPower(myPPM, h, 2*i); // for homog case 380 // auto_ptr<summand> jaa(new summand(myCoeffRing, myPPM)); 381 // R->myAssign(raw(jaa->myCoeff), binomial(n, i)); 382 // myPPM->myMulIndetPower(raw(jaa->myPP), indet, n-i); 383 // // if (HOMOG_CASE) myPPM->mul(jaa->myPP, jaa->myPP, IndetPower(myPPM, h, 2*i)); 384 // ppg.myAddMulSummand(jaa.get(), der, false); 385 // } 386 // } 387 // { // f *= indet^deg(pp, indet); for the early vars 388 // for (size_t indet = nvars/2; indet < nvars; ++indet) 389 // expv[indet] = 0; 390 // auto_ptr<summand> jaa(new summand(myCoeffRing, myPPM)); 391 // R->myAssign(raw(jaa->myCoeff), raw(s->myCoeff)); 392 // myPPM->myAssign(raw(jaa->myPP), expv); 393 // myAddMulSummand(jaa.get(), ppg, false); 394 // } 395 // } 396 397 398 399 myReductionStep(const DistrMPolyClean & g)400 void DistrMPolyClean::myReductionStep(const DistrMPolyClean& g) 401 { 402 CoCoA_ASSERT(&g!=this); 403 CoCoA_ASSERT(mySummands != nullptr); 404 CoCoA_ASSERT(!IsZero(g)); 405 406 DistrMPolyClean tmp_poly(myCoeffRing, myPPM, myMemMgr); 407 408 DivLM(tmp_poly, *this, g); 409 tmp_poly.myNegate(); 410 myDeleteLM(); 411 myAddMulLM(tmp_poly, g, /*SkipLMg = */ true ); 412 } 413 414 ComputeFScaleAndGScale(ConstRefRingElem LCf,ConstRefRingElem LCg,RingElem & fscale,RingElem & gscale)415 static void ComputeFScaleAndGScale(ConstRefRingElem LCf, 416 ConstRefRingElem LCg, 417 RingElem& fscale, 418 RingElem& gscale) 419 { 420 //??? CoCoA_ASSERT(!R->myIsEqual(LCg,-1)); 421 const RingElem gcdLC = gcd(LCf, LCg); 422 gscale = -LCf/gcdLC; 423 if (LCg == gcdLC) 424 { 425 fscale = 1; 426 return; 427 } 428 fscale = LCg/gcdLC; 429 if (!IsInvertible(fscale)) return; 430 gscale /= fscale; 431 fscale = 1; 432 } 433 434 myReductionStepGCD(const DistrMPolyClean & g,RingElem & fscale)435 void DistrMPolyClean::myReductionStepGCD(const DistrMPolyClean& g, RingElem& fscale) 436 { 437 CoCoA_ASSERT(&g!=this); 438 CoCoA_ASSERT(!IsZero(g)); 439 440 DistrMPolyClean tmp_poly(myCoeffRing, myPPM, myMemMgr); 441 RingElem gscale(myCoeffRing); 442 443 ComputeFScaleAndGScale(LC(*this), LC(g), fscale, gscale); 444 445 if ( !IsOne(fscale) ) myMulByCoeff(raw(fscale)); 446 DivLM(tmp_poly, *this, g); 447 tmp_poly.myNegate(); 448 myDeleteLM(); 449 myAddMulLM(tmp_poly, g, /*SkipLMg = */ true); 450 } 451 452 myAddClear(DistrMPolyClean & g)453 void DistrMPolyClean::myAddClear(DistrMPolyClean& g) // sets g to 0 as a side-effect 454 { 455 const ring& R = myCoeffRing; 456 // const PPOrdering& ord = ordering(myPPM); 457 typedef DistrMPolyClean::summand summand; 458 459 summand* g_smnd = g.mySummands; 460 summand** f_prev = &mySummands; 461 summand* f_smnd = *f_prev; 462 int CMP=0; 463 //??? CoCoA_ASSERT(*(G.myEnd)==nullptr);//BUG HUNTING ??? 464 465 // clog << "input f = "; output(clog, *this) ;clog << std::endl; 466 while ( f_smnd!=nullptr && g_smnd!=nullptr ) 467 { 468 while (f_smnd!=nullptr && 469 (CMP = myPPM->myCmp(raw(f_smnd->myPP), raw(g_smnd->myPP))) >0) 470 f_smnd = *(f_prev = &f_smnd->myNext); 471 if (f_smnd == nullptr) break; 472 //clog << "(myAddClear error: should never happen for Basic Reduction)" << std::endl; 473 g.mySummands = g.mySummands->myNext; 474 g_smnd->myNext = nullptr; 475 if (CMP == 0) 476 { 477 R->myAdd(raw(f_smnd->myCoeff), raw(f_smnd->myCoeff), raw(g_smnd->myCoeff)); 478 if (IsZero(f_smnd->myCoeff)) 479 myRemoveSummand(f_prev); 480 ourDeleteSummands(g_smnd/*, myCoeffRing, myPPM*/, myMemMgr); 481 } 482 else // (CMP < 0) 483 { 484 myInsertSummand(g_smnd, f_prev); 485 f_prev = &(*f_prev)->myNext; 486 } 487 f_smnd = *f_prev; 488 g_smnd = g.mySummands; 489 } 490 if (g.mySummands != nullptr) 491 { 492 *myEnd = g.mySummands; 493 myEnd = g.myEnd; 494 g.mySummands = nullptr; 495 } 496 g.myEnd = &g.mySummands; 497 // if (rare) {clog << "f2 = "; output(clog, f) ;clog << std::endl;} 498 } 499 500 myAppendClear(DistrMPolyClean & g)501 void DistrMPolyClean::myAppendClear(DistrMPolyClean& g) // sets g to 0; no throw guarantee! 502 { 503 if (g.mySummands == nullptr) return; 504 *(myEnd) = g.mySummands; 505 myEnd = g.myEnd; 506 g.mySummands = nullptr; 507 g.myEnd = &g.mySummands; 508 } 509 510 LPP(const DistrMPolyClean & f)511 ConstRefPPMonoidElem LPP(const DistrMPolyClean& f) 512 { 513 CoCoA_ASSERT(!IsZero(f)); 514 return f.mySummands->myPP; 515 } 516 517 DivLM(DistrMPolyClean & lhs,const DistrMPolyClean & f,const DistrMPolyClean & g)518 void DivLM(DistrMPolyClean& lhs, const DistrMPolyClean& f, const DistrMPolyClean& g) // lhs = LM(f)/LM(g) 519 { 520 CoCoA_ASSERT(IsCompatible(f, g) && IsCompatible(lhs, f)); 521 CoCoA_ASSERT(!IsZero(f) && !IsZero(g)); 522 // clog << "DivLM" << std::endl; 523 const ring& R = f.myCoeffRing; // shorthand 524 typedef DistrMPolyClean::summand summand; // shorthand 525 const summand* const LMf = f.mySummands; // shorthand 526 const summand* const LMg = g.mySummands; // shorthand 527 528 DistrMPolyClean::NewSummandPtr SpareSummand(lhs); SpareSummand.myRenew(); 529 CoCoA_ASSERT( R->myIsDivisible(raw(SpareSummand->myCoeff), 530 raw(LMf->myCoeff), raw(LMg->myCoeff)) ); 531 R->myDiv(raw(SpareSummand->myCoeff), raw(LMf->myCoeff), raw(LMg->myCoeff)); 532 (f.myPPM)->myDiv(raw(SpareSummand->myPP), raw(LMf->myPP), raw(LMg->myPP)); 533 lhs.myAssignZero(); // CANNOT myAssignZero() EARLIER in case lhs aliases f or g. 534 lhs.myPushBack(SpareSummand.relinquish()); 535 } 536 537 538 539 // This is lengthier than you might expect because it is exception safe. 540 // It also works fine if c aliases a coefficient of the polynomial. myMulByCoeff(RingElemConstRawPtr rawc)541 void DistrMPolyClean::myMulByCoeff(RingElemConstRawPtr rawc) 542 { 543 CoCoA_ASSERT(!myCoeffRing->myIsZero(rawc)); 544 if (myCoeffRing->myIsOne(rawc)) return; 545 const long n = NumTerms(*this); 546 vector<RingElem> NewCoeffs(n, zero(myCoeffRing)); 547 long k=0; 548 for (summand* it = mySummands; it != nullptr; it = it->myNext) 549 { 550 myCoeffRing->myMul(raw(NewCoeffs[k]), raw(it->myCoeff), rawc); 551 ++k; 552 } 553 // The new coeffs are in NewCoeffs now swap them into the poly, 554 // but if a coeff is 0 (!zero-divisors!), delete the corresponding term. 555 summand** SummandPtr = &mySummands; 556 summand* it = mySummands; 557 for (long k=0; k < n; ++k) 558 { 559 CoCoA_ASSERT(it != nullptr); 560 CoCoA_ASSERT(*SummandPtr == it); 561 if (!IsZero(NewCoeffs[k])) 562 { 563 myCoeffRing->mySwap(raw(NewCoeffs[k]), raw(it->myCoeff)); 564 SummandPtr = &it->myNext; 565 it = it->myNext; 566 continue; 567 } 568 summand* next = it->myNext; 569 myRemoveSummand(SummandPtr); 570 it = next; 571 } 572 } 573 574 575 // This is lengthier than you might expect because it is exception safe. 576 // It also works fine if rawc aliases a coefficient of the polynomial. myDivByCoeff(RingElemConstRawPtr rawc)577 bool DistrMPolyClean::myDivByCoeff(RingElemConstRawPtr rawc) 578 { 579 CoCoA_ASSERT(!myCoeffRing->myIsZero(rawc)); 580 if (myCoeffRing->myIsOne(rawc)) return true; 581 vector<RingElem> NewCoeffs(NumTerms(*this), zero(myCoeffRing)); 582 long n=0; 583 for (summand* it = mySummands; it != nullptr; it = it->myNext) 584 { 585 if (!myCoeffRing->myIsDivisible(raw(NewCoeffs[n]), raw(it->myCoeff), rawc)) 586 return false; 587 ++n; 588 } 589 // The new coeffs are in NewCoeffs now swap them into the poly. 590 n = 0; 591 for (summand* it = mySummands; it != nullptr; it = it->myNext) 592 { 593 myCoeffRing->mySwap(raw(NewCoeffs[n]), raw(it->myCoeff)); 594 ++n; 595 } 596 return true; 597 } 598 599 600 // This would not be exception safe if PP multiplication might allocate memory. myMulByPP(PPMonoidElemConstRawPtr rawpp)601 void DistrMPolyClean::myMulByPP(PPMonoidElemConstRawPtr rawpp) 602 { 603 for (summand* f_smnd = mySummands; f_smnd != nullptr ; f_smnd = f_smnd->myNext) 604 myPPM->myMul(raw(f_smnd->myPP), raw(f_smnd->myPP), rawpp); 605 } 606 607 // ??? WANT DIVISION BY A PP TOO??? 608 609 610 // void DistrMPolyClean::myWeylMul(PPMonoidElemConstRawPtr rawpp) 611 // { 612 // for (summand* f_smnd = mySummands; f_smnd != nullptr ; f_smnd = f_smnd->myNext) 613 // myPPM->myMul(raw(f_smnd->myPP), raw(f_smnd->myPP), rawpp); 614 // } 615 616 myPushFront(RingElemConstRawPtr rawc,const std::vector<long> & expv)617 void DistrMPolyClean::myPushFront(RingElemConstRawPtr rawc, const std::vector<long>& expv) 618 { 619 if (myCoeffRing->myIsZero(rawc)) return; 620 621 NewSummandPtr tmp(*this); tmp.myRenew(); 622 myCoeffRing->myAssign(raw(tmp->myCoeff), rawc); 623 myPPM->myAssign(raw(tmp->myPP), expv); 624 myPushFront(tmp.relinquish()); 625 } 626 627 myPushBack(RingElemConstRawPtr rawc,const std::vector<long> & expv)628 void DistrMPolyClean::myPushBack(RingElemConstRawPtr rawc, const std::vector<long>& expv) 629 { 630 if (myCoeffRing->myIsZero(rawc)) return; 631 632 NewSummandPtr tmp(*this); tmp.myRenew(); 633 myCoeffRing->myAssign(raw(tmp->myCoeff), rawc); 634 myPPM->myAssign(raw(tmp->myPP), expv); 635 myPushBack(tmp.relinquish()); 636 } 637 638 myPushFront(RingElemConstRawPtr rawc,PPMonoidElemConstRawPtr rawpp)639 void DistrMPolyClean::myPushFront(RingElemConstRawPtr rawc, PPMonoidElemConstRawPtr rawpp) 640 { 641 if (myCoeffRing->myIsZero(rawc)) return; 642 643 NewSummandPtr tmp(*this); tmp.myRenew(); 644 myCoeffRing->myAssign(raw(tmp->myCoeff), rawc); 645 myPPM->myAssign(raw(tmp->myPP), rawpp); 646 myPushFront(tmp.relinquish()); 647 } 648 649 myPushBack(RingElemConstRawPtr rawc,PPMonoidElemConstRawPtr rawpp)650 void DistrMPolyClean::myPushBack(RingElemConstRawPtr rawc, PPMonoidElemConstRawPtr rawpp) 651 { 652 if (myCoeffRing->myIsZero(rawc)) return; 653 654 NewSummandPtr tmp(*this); tmp.myRenew(); 655 myCoeffRing->myAssign(raw(tmp->myCoeff), rawc); 656 myPPM->myAssign(raw(tmp->myPP), rawpp); 657 myPushBack(tmp.relinquish()); 658 } 659 660 myPushFront(summand * t)661 void DistrMPolyClean::myPushFront(summand* t) 662 { 663 CoCoA_ASSERT(t->myNext == nullptr); 664 CoCoA_ASSERT(IsZero(*this) || myPPM->myCmp(raw(t->myPP), raw(mySummands->myPP)) > 0); 665 t->myNext = mySummands; 666 mySummands = t; 667 if (myEnd == &mySummands) myEnd = &t->myNext; 668 } 669 670 myPushBack(summand * t)671 void DistrMPolyClean::myPushBack(summand* t) 672 { 673 CoCoA_ASSERT(t->myNext == nullptr); 674 // Cannot easily check that t really is smaller than smallest PP in the polynomial. 675 #ifdef CoCoA__DEBUG 676 // Costly check that t really is smaller than smallest PP in the DistrMPolyInlFpPP. 677 if (!IsZero(*this)) 678 { 679 summand* LastSummand = mySummands; 680 while (LastSummand->myNext != nullptr) 681 LastSummand = LastSummand->myNext; 682 CoCoA_ASSERT(cmp(t->myPP, LastSummand->myPP) < 0); 683 CoCoA_ASSERT(myPPM->myCmp(t->myPP, LastSummand->myPP) < 0); 684 } 685 #endif 686 *myEnd = t; 687 myEnd = &t->myNext; 688 } 689 690 myRemoveSummand(summand ** prev_link)691 void DistrMPolyClean::myRemoveSummand(summand** prev_link) 692 { 693 summand* DeleteMe = *prev_link; 694 CoCoA_ASSERT(DeleteMe != nullptr); 695 if (DeleteMe->myNext == nullptr) 696 myEnd = prev_link; 697 698 *prev_link = DeleteMe->myNext; 699 DeleteMe->myNext = nullptr; 700 ourDeleteSummands(DeleteMe/*, myCoeffRing, myPPM*/, myMemMgr); 701 } 702 703 myInsertSummand(summand * s,summand ** prev_link)704 void DistrMPolyClean::myInsertSummand(summand* s, summand** prev_link) 705 { 706 s->myNext = (*prev_link); 707 (*prev_link) = s; 708 if (myEnd == prev_link) myEnd = &(s->myNext); 709 } 710 711 IsZeroAddLCs(DistrMPolyClean & f,DistrMPolyClean & g)712 bool IsZeroAddLCs(DistrMPolyClean& f, DistrMPolyClean& g) 713 { 714 CoCoA_ASSERT(IsCompatible(f, g)); 715 CoCoA_ASSERT(!IsZero(f) && !IsZero(g)); 716 CoCoA_ASSERT( LPP(f)==LPP(g) ); 717 f.myCoeffRing->myAdd(raw(f.mySummands->myCoeff), raw(f.mySummands->myCoeff), raw(g.mySummands->myCoeff)); 718 g.myDeleteLM(); 719 if (!IsZero(f.mySummands->myCoeff)) return false; 720 f.myDeleteLM(); 721 return true; 722 } 723 724 myNegate()725 void DistrMPolyClean::myNegate() 726 { 727 for (summand* iter = mySummands; iter != nullptr; iter = iter->myNext) 728 myCoeffRing->myNegate(raw(iter->myCoeff), raw(iter->myCoeff)); // MIGHT THROW??? 729 } 730 731 add(DistrMPolyClean & lhs,const DistrMPolyClean & g,const DistrMPolyClean & h)732 void add(DistrMPolyClean& lhs, const DistrMPolyClean& g, const DistrMPolyClean& h) 733 { 734 CoCoA_ASSERT(IsCompatible(lhs, g) && IsCompatible(g, h)); 735 const ring& R = lhs.myCoeffRing; 736 DistrMPolyClean ans(lhs.myCoeffRing, lhs.myPPM, lhs.myMemMgr); 737 738 typedef DistrMPolyClean::summand summand; 739 const summand* gterm = g.mySummands; 740 const summand* hterm = h.mySummands; 741 742 if (&lhs==&g && IsMonomial(h)) 743 { 744 lhs.myAddMonomial(h); 745 return; 746 } 747 if (&lhs==&h && IsMonomial(g)) 748 { 749 lhs.myAddMonomial(g); 750 return; 751 } 752 753 DistrMPolyClean::NewSummandPtr SpareSummand(lhs); SpareSummand.myRenew(); 754 while (gterm != nullptr && hterm != nullptr) 755 { 756 int cmp = (lhs.myPPM)->myCmp(raw(gterm->myPP), raw(hterm->myPP)); 757 758 if (cmp < 0) 759 { 760 summand* hcopy = ans.myCopySummand(hterm); 761 ans.myPushBack(hcopy); 762 hterm = hterm->myNext; 763 continue; 764 } 765 766 if (cmp > 0) 767 { 768 summand* gcopy = ans.myCopySummand(gterm); 769 ans.myPushBack(gcopy); 770 gterm = gterm->myNext; 771 continue; 772 } 773 774 // Must have cmp == 0 here. 775 // The leading PPs are the same, so we sum the coeffs. 776 R->myAdd(raw(SpareSummand->myCoeff), raw(gterm->myCoeff), raw(hterm->myCoeff)); 777 if (!IsZero(SpareSummand->myCoeff)) 778 { 779 (lhs.myPPM)->myAssign(raw(SpareSummand->myPP), raw(gterm->myPP)); // set PP ordv 780 ans.myPushBack(SpareSummand.relinquish()); 781 SpareSummand.myRenew(); 782 } 783 gterm = gterm->myNext; 784 hterm = hterm->myNext; 785 } 786 while (gterm != nullptr) 787 { 788 summand* gcopy = ans.myCopySummand(gterm); 789 ans.myPushBack(gcopy); 790 gterm = gterm->myNext; 791 } 792 while (hterm != nullptr) 793 { 794 summand* hcopy = ans.myCopySummand(hterm); 795 ans.myPushBack(hcopy); 796 hterm = hterm->myNext; 797 } 798 799 swap(lhs, ans); // really an assignment 800 } 801 802 803 // EXEPTION SAFE myAddMonomial(const DistrMPolyClean & g)804 void DistrMPolyClean::myAddMonomial(const DistrMPolyClean& g) 805 { 806 CoCoA_ASSERT(IsCompatible(*this, g)); 807 CoCoA_ASSERT(NumTerms(g)==1); 808 809 typedef DistrMPolyClean::summand summand; 810 summand** f_prev = &mySummands; 811 summand* f_smnd = *f_prev; 812 NewSummandPtr s(*this); s.myRenew(); 813 s->myCoeff = g.mySummands->myCoeff; s->myPP = g.mySummands->myPP; 814 815 int CMP; 816 while (f_smnd!=nullptr && 817 (CMP = myPPM->myCmp(raw(f_smnd->myPP), raw(s->myPP))) >0) 818 f_smnd = *(f_prev = &f_smnd->myNext); 819 if (f_smnd == nullptr) { myPushBack(s.relinquish()); return; } 820 821 if (CMP < 0) 822 { 823 myInsertSummand(s.relinquish(), f_prev); 824 f_prev = &(*f_prev)->myNext; 825 return; 826 } 827 828 myCoeffRing->myAdd(raw(s->myCoeff), raw(f_smnd->myCoeff), raw(s->myCoeff)); 829 if (IsZero(s->myCoeff)) 830 myRemoveSummand(f_prev); 831 else 832 myCoeffRing->mySwap(raw(s->myCoeff), raw(f_smnd->myCoeff)); 833 } 834 835 sub(DistrMPolyClean & lhs,const DistrMPolyClean & g,const DistrMPolyClean & h)836 void sub(DistrMPolyClean& lhs, const DistrMPolyClean& g, const DistrMPolyClean& h) 837 { 838 // This code is almost a copy of add(...). 839 CoCoA_ASSERT(IsCompatible(lhs, g) && IsCompatible(g, h)); 840 const ring& R = lhs.myCoeffRing; 841 DistrMPolyClean ans(lhs.myCoeffRing, lhs.myPPM, lhs.myMemMgr); 842 843 typedef DistrMPolyClean::summand summand; 844 const summand* gterm = g.mySummands; 845 const summand* hterm = h.mySummands; 846 DistrMPolyClean::NewSummandPtr SpareSummand(lhs); SpareSummand.myRenew(); 847 while (gterm != nullptr && hterm != nullptr) 848 { 849 int ord = (lhs.myPPM)->myCmp(raw(gterm->myPP), raw(hterm->myPP)); 850 851 if (ord < 0) 852 { 853 summand* hcopy = ans.myCopySummand(hterm); 854 R->myNegate(raw(hcopy->myCoeff), raw(hcopy->myCoeff)); //??? can this throw? 855 ans.myPushBack(hcopy); 856 hterm = hterm->myNext; 857 continue; 858 } 859 860 if (ord > 0) 861 { 862 summand* gcopy = ans.myCopySummand(gterm); 863 ans.myPushBack(gcopy); 864 gterm = gterm->myNext; 865 continue; 866 } 867 868 // The leading PPs are the same, so we subtract the coeffs. 869 R->mySub(raw(SpareSummand->myCoeff), raw(gterm->myCoeff), raw(hterm->myCoeff)); 870 if (!IsZero(SpareSummand->myCoeff)) 871 { 872 (lhs.myPPM)->myAssign(raw(SpareSummand->myPP), raw(gterm->myPP)); // set PP ordv 873 ans.myPushBack(SpareSummand.relinquish()); 874 SpareSummand.myRenew(); 875 } 876 gterm = gterm->myNext; 877 hterm = hterm->myNext; 878 } 879 while (gterm != nullptr) 880 { 881 summand* gcopy = ans.myCopySummand(gterm); 882 ans.myPushBack(gcopy); 883 gterm = gterm->myNext; 884 } 885 while (hterm != nullptr) 886 { 887 summand* hcopy = ans.myCopySummand(hterm); 888 R->myNegate(raw(hcopy->myCoeff), raw(hcopy->myCoeff)); //??? can this throw? 889 ans.myPushBack(hcopy); 890 hterm = hterm->myNext; 891 } 892 893 swap(lhs, ans); // really an assignment 894 } 895 896 897 // bool div(DistrMPolyClean& lhs, const DistrMPolyClean& g, const DistrMPolyClean& h) // result is true iff quotient is exact. 898 // { 899 // if (IsZero(h)) return false; //???CoCoA_THROW_ERROR(ERR::DivByZero,"div(DMP,DMP,DMP)"); 900 // PPMonoid PPM = lhs.myPPM; 901 // // const PPOrdering ord = ordering(PPM); 902 // const ring& R = lhs.myCoeffRing; 903 // const DistrMPolyClean::summand* LMh = h.mySummands; 904 // const PPMonoidElem LPPden(LMh->myPP); 905 // DistrMPolyClean ans(lhs.myCoeffRing, lhs.myPPM, lhs.myMemMgr); 906 // DistrMPolyClean dividend(g); 907 // while (!IsZero(dividend)) 908 // { 909 // const DistrMPolyClean::summand* LMdividend = dividend.mySummands; 910 // auto_ptr<DistrMPolyClean::summand> qterm(new DistrMPolyClean::summand(R, lhs.myPPM)); 911 // if (!R->myIsDivisible(raw(qterm->myCoeff), raw(LMdividend->myCoeff), raw(LMh->myCoeff))) return false; 912 // { 913 // PPMonoidElem LPPnum(LMdividend->myPP); 914 // if (!IsDivisible(LPPnum, LPPden)) return false; 915 // } 916 // PPM->myDiv(raw(qterm->myPP), raw(LMdividend->myPP), raw(LMh->myPP)); //??? check whether this fails! 917 // R->myNegate(raw(qterm->myCoeff), raw(qterm->myCoeff)); 918 // dividend.myAddMulSummand(qterm.get(), h, false); 919 // R->myNegate(raw(qterm->myCoeff), raw(qterm->myCoeff)); 920 // ans.myPushBack(qterm.release()); 921 // } 922 // swap(lhs, ans); // really an assignment 923 // return true; 924 // } 925 926 output(std::ostream & out,const DistrMPolyClean & f)927 void output(std::ostream& out, const DistrMPolyClean& f) // for debugging only 928 { 929 if (!out) return; // short-cut for bad ostreams 930 if (IsZero(f)) { out << "0"; return; } 931 for (DistrMPolyClean::summand* it = f.mySummands; it != nullptr; it = it->myNext) 932 out << " +(" << it->myCoeff << ")*" << it->myPP; 933 } 934 935 936 // bool IsConstant(const DistrMPolyClean& f) 937 // { 938 // if (IsZero(f)) return true; 939 // if (!IsMonomial(f)) return false; 940 // return IsOne(LPP(f)); 941 // } 942 943 IsZero(const DistrMPolyClean & f)944 bool IsZero(const DistrMPolyClean& f) 945 { 946 return (f.mySummands == nullptr); 947 } 948 949 950 // bool IsOne(const DistrMPolyClean& f) 951 // { 952 // if (IsZero(f) || f.mySummands->myNext != nullptr) return false; 953 // if (!IsOne(f.mySummands->myPP)) return false; 954 // return IsOne(f.mySummands->myCoeff); 955 // } 956 957 958 // bool IsMinusOne(const DistrMPolyClean& f) 959 // { 960 // if (IsZero(f) || f.mySummands->myNext != nullptr) return false; 961 // if (!IsOne(f.mySummands->myPP)) return false; 962 // return IsMinusOne(f.mySummands->myCoeff); 963 // } 964 965 966 // bool IsConstant(const DistrMPolyClean& f) 967 // { 968 // if (IsZero(f)) return true; 969 // if (f.mySummands->myNext != nullptr) return false; // NULL ptr 970 // return IsOne(f.mySummands->myPP); 971 // } 972 973 974 // bool IsIndet(std::size_t& IndetIndex, const DistrMPolyClean& f) 975 // { 976 // if (IsZero(f)) return false; 977 // if (f.mySummands->myNext != nullptr) return false; // NULL ptr 978 // if (!IsOne(f.mySummands->myCoeff)) return false; 979 // return IsIndet(IndetIndex, f.mySummands->myPP); 980 // } 981 982 IsMonomial(const DistrMPolyClean & f)983 bool IsMonomial(const DistrMPolyClean& f) 984 { 985 if (IsZero(f) || f.mySummands->myNext != nullptr) return false; 986 return true; 987 } 988 989 IsEqual(const DistrMPolyClean & f,const DistrMPolyClean & g)990 bool IsEqual(const DistrMPolyClean& f, const DistrMPolyClean& g) 991 { 992 CoCoA_ASSERT(IsCompatible(f, g)); 993 if (&f == &g) return true; 994 const DistrMPolyClean::summand* fterm = f.mySummands; 995 const DistrMPolyClean::summand* gterm = g.mySummands; 996 while (fterm != nullptr && gterm != nullptr) 997 { 998 if (!f.myIsEqual(fterm, gterm)) return false; 999 fterm = fterm->myNext; 1000 gterm = gterm->myNext; 1001 } 1002 return fterm == gterm; // either both are nullptr (when the polys are equal), or only one is nullptr 1003 } 1004 1005 1006 // void WeylMul(DistrMPolyClean& lhs, const DistrMPolyClean& g, const DistrMPolyClean& h) 1007 // { 1008 1009 // } 1010 1011 1012 // void WeylDiv(DistrMPolyClean& lhs, const DistrMPolyClean& g, const DistrMPolyClean& h) 1013 // { 1014 // CoCoA_THROW_ERROR(ERR::NYI, "WeylDiv (DistrMPolyClean)"); 1015 // } 1016 1017 1018 // void deriv(DistrMPolyClean& lhs, const DistrMPolyClean& f, std::size_t IndetIndex) 1019 // { 1020 // deriv(lhs, f, indet(f.myPPM, IndetIndex)); 1021 // } 1022 1023 1024 // void deriv(DistrMPolyClean& lhs, const DistrMPolyClean& f, ConstRefPPMonoidElem x) 1025 // { 1026 // if (IsOne(x)) { lhs = f; return; } 1027 // const size_t nvars = NumIndets(owner(x)); 1028 // // const PPOrdering ord = ordering(owner(x)); 1029 // const PPMonoid PPM = owner(x); 1030 // const ring& R = f.myCoeffRing; 1031 // vector<long> expv(nvars); 1032 // exponents(expv, x); 1033 // // vector<PPOrderingBase::OrdvElem> ordvx(OrdvWords(ord)); 1034 // // PPM->myInit(&ordvx[0], &expv[0]); 1035 // //clog<<"differentiating wrt expv: [";for(size_t i=0;i<nvars;++i)clog<<expv[i]<<" ";clog<<"]"<<std::endl; 1036 // DistrMPolyClean ans(f.myCoeffRing, f.myPPM, f.myMemMgr); 1037 1038 // for (const DistrMPolyClean::summand* f_term = f.mySummands; f_term != nullptr; f_term = f_term->myNext) 1039 // { 1040 // //clog<<"LOOPHEAD\n"; 1041 // BigInt scale(1); 1042 // for (size_t indet=0; indet < nvars; ++indet) 1043 // { 1044 // if (expv[indet] == 0) continue; 1045 // long d = PPM->myExponent(raw(f_term->myPP), indet); 1046 // //clog<<"log is "<<d<<" wrt var "<<indet<<std::endl; 1047 // if (d < expv[indet]) { scale = 0; break; } 1048 // scale *= RangeFactorial(d-expv[indet]+1, d); 1049 // } 1050 // //if(IsZero(scale))clog<<"skipping term\n"; 1051 // if (IsZero(scale)) continue; 1052 // //clog<<"rescaling term by "<<scale<<std::endl; 1053 // auto_ptr<DistrMPolyClean::summand> tmp(new DistrMPolyClean::summand(R, PPM)); 1054 // R->myAssign(raw(tmp->myCoeff), scale); 1055 // R->myMul(raw(tmp->myCoeff), raw(tmp->myCoeff), raw(f_term->myCoeff)); 1056 // if (IsZero(tmp->myCoeff)) continue; 1057 // //clog<<"dividing ordv [";for(size_t i=0;i<2;++i)clog<<f_term->myPP[i]<<" ";clog<<"]\n"; 1058 // //clog<<"by ordv [";for(size_t i=0;i<2;++i)clog<<ordvx[i]<<" ";clog<<"]\n"; 1059 // PPM->myDiv(raw(tmp->myPP), raw(f_term->myPP), raw(x)); 1060 // //clog<<"Quotient is [";for(size_t i=0;i<2;++i)clog<<tmp->myPP[i]<<" ";clog<<"]\n"; 1061 // ans.myPushBack(tmp.release()); 1062 // } 1063 // swap(lhs, ans); // really an assignment 1064 // } 1065 1066 1067 1068 // //---------------------------------------------------------------------- 1069 1070 // PolyIter::PolyIter(const PolyRing& Rx, DistrMPolyClean::summand** ptrptr): 1071 // myPolyRing(Rx), 1072 // myPtrPtr(ptrptr), 1073 // myExpv(NumIndets(Rx)) 1074 // {} 1075 1076 1077 // PolyIter::PolyIter(const PolyIter& copy): 1078 // myPolyRing(copy.myPolyRing), 1079 // myPtrPtr(copy.myPtrPtr), 1080 // myExpv(NumIndets(myPolyRing)) 1081 // {} 1082 1083 1084 // PolyIter& PolyIter::operator=(const PolyIter& rhs) 1085 // { 1086 // CoCoA_ASSERT(&myPolyRing == &rhs.myPolyRing); 1087 // myPtrPtr = rhs.myPtrPtr; 1088 // return *this; 1089 // } 1090 1091 1092 // PolyIter& PolyIter::operator++() 1093 // { 1094 // CoCoA_ASSERT(*myPtrPtr != nullptr); 1095 // myPtrPtr = &((*myPtrPtr)->myNext); 1096 // return *this; 1097 // } 1098 1099 1100 // PolyIter PolyIter::operator++(int) 1101 // { 1102 // CoCoA_ASSERT(*myPtrPtr != nullptr); 1103 // PolyIter copy(*this); 1104 // myPtrPtr = &((*myPtrPtr)->myNext); 1105 // return copy; 1106 // } 1107 1108 1109 // bool operator==(const PolyIter& lhs, const PolyIter& rhs) 1110 // { 1111 // return lhs.myPtrPtr == rhs.myPtrPtr; 1112 // } 1113 1114 1115 // bool operator!=(const PolyIter& lhs, const PolyIter& rhs) 1116 // { 1117 // return lhs.myPtrPtr != rhs.myPtrPtr; 1118 // } 1119 1120 1121 // RingElemRawPtr RawCoeff(PolyIter& i) 1122 // { 1123 // CoCoA_ASSERT(*i.myPtrPtr != nullptr); 1124 // return (*i.myPtrPtr)->myCoeff; 1125 // } 1126 1127 1128 // const RingElem coeff(const PolyIter& i) 1129 // { 1130 // CoCoA_ASSERT(*i.myPtrPtr != nullptr); 1131 // return RingElem(CoeffRing(i.myPolyRing), (*i.myPtrPtr)->myCoeff); 1132 // } 1133 1134 1135 // PPMonoidElem pp(PolyIter& i) 1136 // { 1137 // CoCoA_ASSERT(*i.myPtrPtr != nullptr); 1138 // return PPMonoidElem(PPM(i.myPolyRing), PPMonoidElem::FromOrdv, (*i.myPtrPtr)->myPP); 1139 // } 1140 1141 1142 // PPOrdering::OrdvElem* ordv(PolyIter& i) 1143 // { 1144 // CoCoA_ASSERT(*i.myPtrPtr != nullptr); 1145 // return (*i.myPtrPtr)->myPP; 1146 // } 1147 1148 1149 1150 } // end of namespace CoCoA 1151 1152 1153 1154 // RCS header/log in the next few lines 1155 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/DistrMPolyClean.C,v 1.30 2020/06/17 15:49:22 abbott Exp $ 1156 // $Log: DistrMPolyClean.C,v $ 1157 // Revision 1.30 2020/06/17 15:49:22 abbott 1158 // Summary: Changed CoCoA_ERROR into CoCoA_THROW_ERROR 1159 // 1160 // Revision 1.29 2020/02/11 16:56:40 abbott 1161 // Summary: Corrected last update (see redmine 969) 1162 // 1163 // Revision 1.28 2020/02/11 16:12:17 abbott 1164 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969 1165 // 1166 // Revision 1.27 2019/10/15 11:54:08 abbott 1167 // Summary: Changed 0 into nullptr (where appropriate) 1168 // 1169 // Revision 1.26 2019/03/19 11:07:07 abbott 1170 // Summary: Replaced 0 by nullptr where appropriate 1171 // 1172 // Revision 1.25 2018/05/22 14:16:39 abbott 1173 // Summary: Split BigRat into BigRat (class defn + ctors) and BigRatOps 1174 // 1175 // Revision 1.24 2018/05/18 12:13:36 bigatti 1176 // -- renamed IntOperations --> BigIntOps 1177 // 1178 // Revision 1.23 2017/12/18 12:07:26 abbott 1179 // Summary: Correct handling for polys with coeffs in rings with zero-divisors 1180 // 1181 // Revision 1.22 2015/11/24 17:46:56 abbott 1182 // Summary: Corrected MoveLMToFront 1183 // 1184 // Revision 1.21 2015/11/04 10:42:05 abbott 1185 // Summary: Replaced auto_ptr<summand> with NewSummandPtr 1186 // 1187 // Revision 1.20 2015/04/27 10:30:51 bigatti 1188 // -- commented out excessive assert in myPushFront 1189 // 1190 // Revision 1.19 2015/04/27 10:06:04 bigatti 1191 // -- simplified myAppendClear 1192 // -- fixed myMoveLMToBack 1193 // -- added CoCoA_ASSERT to myMoveLMToBack and myMoveLMToFront 1194 // 1195 // Revision 1.18 2015/04/24 15:40:58 bigatti 1196 // -- renamed: myAddMul --> myAddMulLM 1197 // -- renamed: myMoveLM --> myMoveLMToFront 1198 // -- new myMoveLMToBack (used in ReductionCog --> bug in test-TmpMorseGraph??) 1199 // 1200 // Revision 1.17 2015/04/17 16:24:07 abbott 1201 // Summary: Added check that first arg is non-zero 1202 // Author: JAA 1203 // 1204 // Revision 1.16 2014/04/30 16:05:21 abbott 1205 // Summary: Replaced size_t by long 1206 // Author: JAA 1207 // 1208 // Revision 1.15 2014/01/28 10:57:24 bigatti 1209 // -- removed useless ==1 on boolean 1210 // 1211 // Revision 1.14 2012/10/24 12:13:34 abbott 1212 // Added keyword const to local variable in ComputeFScaleAndGScale. 1213 // 1214 // Revision 1.13 2012/10/16 10:27:34 abbott 1215 // Replaced RefRingElem by RingElem& 1216 // 1217 // Revision 1.12 2012/10/11 14:27:59 abbott 1218 // Removed "semantically risky" function RefLC/RawLC from DistrMPoly*. 1219 // Reimplemented myRecvTwinFloat in RingDistrMPoly* more cleanly (but 1220 // new impl does make a wasteful copy of the coeff). 1221 // 1222 // Revision 1.11 2012/10/05 15:33:28 bigatti 1223 // -- added myAddMonomial 1224 // 1225 // Revision 1.10 2012/05/28 09:18:21 abbott 1226 // Created IntOperations which gathers together all operations on 1227 // integers (both big and small). Many consequential changes. 1228 // 1229 // Revision 1.9 2012/01/25 13:43:45 bigatti 1230 // -- moved up: IsCompatible, ourSwap 1231 // 1232 // Revision 1.8 2011/11/09 14:03:59 bigatti 1233 // -- renamed MachineInteger --> MachineInt 1234 // 1235 // Revision 1.7 2011/08/24 10:25:53 bigatti 1236 // -- renamed QQ --> BigRat 1237 // -- sorted #include 1238 // 1239 // Revision 1.6 2011/08/14 15:52:17 abbott 1240 // Changed ZZ into BigInt (phase 1: just the library sources). 1241 // 1242 // Revision 1.5 2011/07/15 16:54:04 abbott 1243 // Minor correction to a comment. 1244 // 1245 // Revision 1.4 2011/06/23 16:04:47 abbott 1246 // Added IamExact mem fn for rings. 1247 // Added myRecvTwinFloat mem fn for rings. 1248 // Added first imple of RingHom from RingTwinFloat to other rings. 1249 // 1250 // Revision 1.3 2010/12/26 13:04:37 abbott 1251 // Changed "GlobalXXXput" into corresponding std C++ stream 1252 // (even in commented out code). 1253 // 1254 // Revision 1.2 2010/12/20 15:19:29 bigatti 1255 // -- modified IsZeroAddMul with temporary variable (slug found with cyclotomic) 1256 // 1257 // Revision 1.1 2010/10/08 08:05:28 bigatti 1258 // -- renamed (Ring)DistrMPoly --> (Ring)DistrMPolyClean 1259 // 1260 // Revision 1.12 2009/12/03 17:40:36 abbott 1261 // Added include directives for ZZ.H (as a consequence of removing 1262 // the directive from ring.H). 1263 // 1264 // Revision 1.11 2009/10/02 13:47:07 bigatti 1265 // -- myDivByCoeff now returns bool 1266 // -- unique implementation of myDiv in PolyRing.C 1267 // 1268 // Revision 1.10 2009/09/28 17:14:41 bigatti 1269 // -- commented out unused functions (div, deriv, *Weyl*) 1270 // 1271 // Revision 1.9 2008/12/17 12:11:52 abbott 1272 // Changed type from long to MachineInt in operations which use a machine integer 1273 // in place of a RingElem. The change is "superficial" but affects many files. 1274 // 1275 // Revision 1.8 2008/04/10 15:15:32 bigatti 1276 // -- added void myPushFront(rawc, rawpp) 1277 // 1278 // Revision 1.7 2007/12/05 12:11:07 bigatti 1279 // -- cleaning (mostly removing unused code) 1280 // 1281 // Revision 1.6 2007/12/04 14:27:07 bigatti 1282 // -- changed "log(pp, i)" into "exponent(pp, i)" 1283 // 1284 // Revision 1.5 2007/10/30 17:14:08 abbott 1285 // Changed licence from GPL-2 only to GPL-3 or later. 1286 // New version for such an important change. 1287 // 1288 // Revision 1.4 2007/05/22 22:45:14 abbott 1289 // Changed fn name IsUnit to IsInvertible. 1290 // 1291 // Revision 1.3 2007/05/21 14:50:56 bigatti 1292 // -- myPushFront and myPushBack now accept zero coefficient 1293 // 1294 // Revision 1.2 2007/03/12 16:00:29 bigatti 1295 // -- moved myLog(F, index) into unique implementation in SparsePolyRing 1296 // 1297 // Revision 1.1.1.1 2007/03/09 15:16:11 abbott 1298 // Imported files 1299 // 1300 // Revision 1.17 2007/03/08 18:22:30 cocoa 1301 // Just whitespace cleaning. 1302 // 1303 // Revision 1.16 2007/03/07 13:42:45 bigatti 1304 // -- removed useless argument and other minor changes 1305 // 1306 // Revision 1.15 2007/01/15 13:34:30 cocoa 1307 // -- added prefix "raw" to RawPtr arguments names 1308 // 1309 // Revision 1.14 2006/12/07 17:36:19 cocoa 1310 // -- migrated myRemoveBigContent myContent myPowerSmallExp into 1311 // single implementation in SparsePolyRing 1312 // -- removed content from DistrMPolyClean(..) 1313 // 1314 // Revision 1.13 2006/11/23 18:01:53 cocoa 1315 // -- moved printing functions in unified implementation in SparsePolyRing 1316 // -- simplified "output(f)" for debugging only 1317 // 1318 // Revision 1.12 2006/11/22 15:11:36 cocoa 1319 // -- added #include "CoCoA/symbol.H" 1320 // 1321 // Revision 1.11 2006/11/21 18:09:24 cocoa 1322 // -- added myIsMonomial 1323 // -- implemented myIsOne, myIsMinusOne, myIsConstant, myIsIndet in SparsePolyRing 1324 // -- removed the 4 functions from DistrMPolyClean(..) and RingDistrMPolyClean(..) 1325 // -- changed all names of RawPtr arguments into "raw(..)" 1326 // 1327 // Revision 1.10 2006/11/14 17:17:13 cocoa 1328 // -- fixed coding convention "our" 1329 // 1330 // Revision 1.9 2006/11/09 17:46:58 cocoa 1331 // -- version 0.9712: 1332 // -- IdealImpl moved to SparsePolyRing from concrete rings 1333 // -- PolyList in GTypes is now vector<RingElem> (was list) 1334 // -- "my" coding convention applied to DistrMPolyClean 1335 // 1336 // Revision 1.8 2006/11/02 13:25:44 cocoa 1337 // Simplification of header files: the OpenMath classes have been renamed. 1338 // Many minor consequential changes. 1339 // 1340 // Revision 1.7 2006/10/16 23:18:59 cocoa 1341 // Corrected use of std::swap and various special swap functions. 1342 // Improved myApply memfn for homs of RingDistrMPolyCleanInlPP. 1343 // 1344 // Revision 1.6 2006/10/06 10:01:21 cocoa 1345 // Consequential changes from the modifications to the header files. 1346 // 1347 // Revision 1.5 2006/08/07 21:23:25 cocoa 1348 // Removed almost all publicly visible references to SmallExponent_t; 1349 // changed to long in all PPMonoid functions and SparsePolyRing functions. 1350 // DivMask remains to sorted out. 1351 // 1352 // Revision 1.4 2006/07/20 17:06:08 cocoa 1353 // -- moved myStdDeg into SparsePolyRing 1354 // 1355 // Revision 1.3 2006/06/22 14:07:18 cocoa 1356 // Minor cleaning and elimination of useless #includes. 1357 // 1358 // Revision 1.2 2006/06/08 16:45:28 cocoa 1359 // -- RingDistrMPolyClean*.H have been "moved" into RingDistrMPolyClean*.C 1360 // -- some coding conventions fixed in DistrMPolyClean* 1361 // -- functions wdeg and CmpWDeg have a common implementation in SparsePolyRing 1362 // 1363 // Revision 1.1.1.1 2006/05/30 11:39:37 cocoa 1364 // Imported files 1365 // 1366 // Revision 1.11 2006/05/12 16:10:58 cocoa 1367 // Added OpenMathFwd.H, and tidied OpenMath.H. 1368 // Many consequential but trivial changes. 1369 // 1370 // Revision 1.10 2006/04/26 16:44:53 cocoa 1371 // -- myMul has now a single implementation in SparsePolyRing 1372 // -- myMul and mul in RingDistrMPolyClean* and DistrMPolyClean* have been disabled 1373 // 1374 // Revision 1.9 2006/03/27 12:21:25 cocoa 1375 // Minor silly changes to reduce number of complaints from some compiler or other. 1376 // 1377 // Revision 1.8 2006/03/17 18:08:51 cocoa 1378 // -- changed: mul --> myMulByPP 1379 // 1380 // Revision 1.7 2006/03/16 17:52:16 cocoa 1381 // -- changed: mul, div --> myMulByCoeff, myDivByCoeff 1382 // 1383 // Revision 1.6 2006/03/16 13:13:20 cocoa 1384 // -- added: CoCoA_ASSERT in DivLM 1385 // 1386 // Revision 1.5 2006/03/12 21:28:34 cocoa 1387 // Major check in after many changes 1388 // 1389 // Revision 1.4 2006/03/07 10:06:12 cocoa 1390 // -- fixed: PPMonoidElem LPP(f) now returns ConstRefPPMonoidElem 1391 // 1392 // Revision 1.3 2006/02/20 22:41:20 cocoa 1393 // All forms of the log function for power products now return SmallExponent_t 1394 // (instead of int). exponents now resizes the vector rather than requiring 1395 // the user to pass in the correct size. 1396 // 1397 // Revision 1.2 2006/02/13 13:17:40 cocoa 1398 // -- fixed: "const PPMonoidElem&" --> "ConstRefPPMonoidElem" 1399 // 1400 // Revision 1.1.1.1 2005/10/17 10:46:54 cocoa 1401 // Imported files 1402 // 1403 // Revision 1.6 2005/10/12 15:52:09 cocoa 1404 // Completed test-RingFp1 and corrected/cleaned the SmallFp* 1405 // and RingFp* files. 1406 // 1407 // Some minor tidying elsewhere. 1408 // 1409 // Revision 1.5 2005/08/08 16:36:32 cocoa 1410 // Just checking in before going on holiday. 1411 // Don't really recall what changes have been made. 1412 // Added IsIndet function for RingElem, PPMonoidElem, 1413 // and a member function of OrdvArith. 1414 // Improved the way failed assertions are handled. 1415 // 1416 // Revision 1.4 2005/07/08 15:09:29 cocoa 1417 // Added new symbol class (to represent names of indets). 1418 // Integrated the new class into concrete polynomial rings 1419 // and PPMonoid -- many consequential changes. 1420 // Change ctors for the "inline" sparse poly rings: they no 1421 // longer expect a PPMonoid, but build their own instead 1422 // (has to be a PPMonoidOv). 1423 // 1424 // Revision 1.3 2005/07/01 16:08:16 cocoa 1425 // Friday check-in. Major change to structure under PolyRing: 1426 // now SparsePolyRing and DUPolyRing are separated (in preparation 1427 // for implementing iterators). 1428 // 1429 // A number of other relatively minor changes had to be chased through 1430 // (e.g. IndetPower). 1431 // 1432 // Revision 1.2 2005/06/22 14:47:56 cocoa 1433 // PPMonoids and PPMonoidElems updated to mirror the structure 1434 // used for rings and RingElems. Many consequential changes. 1435 // 1436 // Revision 1.1.1.1 2005/05/03 15:47:31 cocoa 1437 // Imported files 1438 // 1439 // Revision 1.5 2005/04/20 15:40:48 cocoa 1440 // Major change: modified the standard way errors are to be signalled 1441 // (now via a macro which records filename and line number). Updated 1442 // documentation in error.txt accordingly. 1443 // 1444 // Improved the documentation in matrix.txt (still more work to be done). 1445 // 1446 // Revision 1.4 2005/04/19 14:06:04 cocoa 1447 // Added GPL and GFDL licence stuff. 1448 // 1449 // Revision 1.3 2005/02/11 16:45:24 cocoa 1450 // Removed the useless and misleading functions myInit and myKill 1451 // from the SmallFp*Impl classes; various consequential changes. 1452 // 1453 // Revision 1.2 2005/02/11 14:15:20 cocoa 1454 // New style ring elements and references to ring elements; 1455 // I hope I have finally got it right! 1456 // 1457 // Revision 1.1.1.1 2005/01/27 15:12:13 cocoa 1458 // Imported files 1459 // 1460 // Revision 1.13 2004/11/19 15:44:27 cocoa 1461 // Changed names of "casting" functions which convert a ring into 1462 // one with a more special structure (e.g. FractionField). These 1463 // functions now have names starting with "As". There were several 1464 // consequential changes. 1465 // 1466 // Revision 1.12 2004/11/12 16:25:57 cocoa 1467 // -- printing aligned with DistrMPolyCleanInlFpPP and DistrMPolyCleanInlPP 1468 // 1469 // Revision 1.11 2004/11/11 13:30:52 cocoa 1470 // -- minor changes for doxygen 1471 // -- changed: cout --> GlobalLogput() 1472 // 1473 // Revision 1.10 2004/11/11 11:56:09 cocoa 1474 // (1) Tidied makefiles, and introduced common.mki 1475 // (2) Improved several tests, and cleaned them so that they 1476 // handle sanely any otherwise unhandled exceptions. 1477 // 1478 // Revision 1.9 2004/11/08 13:56:02 cocoa 1479 // -- changed calls to ZZ (after changes to ZZ.H) 1480 // 1481 // Revision 1.8 2004/11/02 15:59:11 cocoa 1482 // -- fixed: memory leak on summand (auto_ptr) 1483 // 1484 // Revision 1.7 2004/10/28 16:02:08 cocoa 1485 // -- changed one last PPOrdering::ExpvElem into SmallExponent_t 1486 // 1487 // Revision 1.6 2004/10/21 17:16:37 cocoa 1488 // Fairly major change: new OrdvArith namspace with various members, 1489 // new global typedef SmallExponent_t (defined in config.H). 1490 // 1491 // Revision 1.5 2004/07/20 15:04:06 cocoa 1492 // The next step in the new "ring element" conversion process: 1493 // handling the case of creating a "const RefRingElem" object 1494 // (since C++ refuses to do this properly itself). 1495 // 1496 // Revision 1.4 2004/05/27 16:14:02 cocoa 1497 // Minor revision for new coding conventions. 1498 // 1499 // Revision 1.3 2004/05/24 15:52:14 cocoa 1500 // Major update: 1501 // new error mechanism 1502 // many fixes 1503 // RingHoms almost work now 1504 // RingFloat much improved 1505 // 1506 // Revision 1.2 2004/01/28 16:27:00 cocoa 1507 // Added the necessary for CmpDeg to work. 1508 // 1509 // Revision 1.1 2003/11/21 14:33:55 cocoa 1510 // -- First Import 1511 // 1512