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