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