1 //   Copyright (c)  2005-2018,2020  John Abbott and Anna M. Bigatti
2 //   Authors:  2005-2018,2020  John Abbott and Anna M. Bigatti
3 
4 //   This file is part of the source of CoCoALib, the CoCoA Library.
5 
6 //   CoCoALib is free software: you can redistribute it and/or modify
7 //   it under the terms of the GNU General Public License as published by
8 //   the Free Software Foundation, either version 3 of the License, or
9 //   (at your option) any later version.
10 
11 //   CoCoALib is distributed in the hope that it will be useful,
12 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //   GNU General Public License for more details.
15 
16 //   You should have received a copy of the GNU General Public License
17 //   along with CoCoALib.  If not, see <http://www.gnu.org/licenses/>.
18 
19 
20 // Source code for fns related to homogeneity in SparsePolyRing
21 
22 #include "CoCoA/SparsePolyOps-RingElem.H"
23 
24 #include "CoCoA/SparsePolyRing.H"
25 #include "CoCoA/SparsePolyIter.H"
26 #include "CoCoA/degree.H"
27 #include "CoCoA/geobucket.H"
28 
29 
30 namespace CoCoA
31 {
32 
33   namespace // anonymous
34   {
35 
36     // These 2 are duplicates of fns in SparsePolyOps-RingElem.C
37 
CheckCompatible(ConstRefRingElem x,ConstRefRingElem y,const char * const FnName)38     inline void CheckCompatible(ConstRefRingElem x, ConstRefRingElem y, const char* const FnName)
39     {
40       if (owner(x) != owner(y))  CoCoA_ERROR(ERR::MixedRings, FnName);
41     }
42 
43 
CheckElemSparsePolyRing(ConstRefRingElem f,const char * const FnName)44     inline void CheckElemSparsePolyRing(ConstRefRingElem f, const char* const FnName)
45     {
46       if (!IsSparsePolyRing(owner(f))) CoCoA_ERROR(ERR::NotElemSparsePolyRing, FnName);
47     }
48 
49   } // end of namespace anonymous
50 
51 
wdeg(ConstRefRingElem f)52   degree wdeg(ConstRefRingElem f)
53   {
54     CheckElemSparsePolyRing(f, "wdeg(f)");
55     if (IsZero(f)) CoCoA_ERROR(ERR::ZeroRingElem, "wdeg(f)");
56     return wdeg(LPP(f)); // yes! see [KR] introduction Sec.4.3
57   }
58 
59 
CmpWDeg(ConstRefRingElem f1,ConstRefRingElem f2)60   int CmpWDeg(ConstRefRingElem f1, ConstRefRingElem f2)
61   {
62     CheckCompatible(f1, f2, "CmpWDeg(f1,f2)");
63     CheckElemSparsePolyRing(f1, "CmpWDeg(f1,f2)");
64     if (IsZero(f1) || IsZero(f2)) CoCoA_ERROR(ERR::ZeroRingElem, "CmpWDeg(f1,f2)");
65     // Now we know that both f1 and f2 are non-zero
66     //    return SparsePolyRingPtr(owner(f1))->myCmpWDeg(raw(f1), raw(f2));
67     return CmpWDeg(LPP(f1), LPP(f2));
68   }
69 
70 
CmpWDegPartial(ConstRefRingElem f1,ConstRefRingElem f2,long i)71   int CmpWDegPartial(ConstRefRingElem f1, ConstRefRingElem f2, long i)  // assumes 0 <= i
72   {
73     CheckCompatible(f1, f2, "CmpWDegPartial(f1,f2,i)");
74     CheckElemSparsePolyRing(f1, "CmpWDegPartial(f1,f2,i)");
75     if (IsZero(f1) || IsZero(f2)) CoCoA_ERROR(ERR::ZeroRingElem, "CmpWDegPartial(f1,f2,i)");
76     // Now we know that both f1 and f2 are non-zero
77     //    return SparsePolyRingPtr(owner(f1))->myCmpWDeg(raw(f1), raw(f2));
78     return CmpWDegPartial(LPP(f1), LPP(f2), i);
79   }
80 
81 
IsHomog(ConstRefRingElem f)82   bool IsHomog(ConstRefRingElem f)
83   {
84     CheckElemSparsePolyRing(f, "IsHomog(f)");
85     if (GradingDim(owner(f))==0)
86       CoCoA_ERROR(ERR::ZeroGradingDim, "IsHomog(RingElem)");
87     return SparsePolyRingPtr(owner(f))->myIsHomog(raw(f));
88   }
89 
90 
IsHomogPartial(ConstRefRingElem f,long n)91   bool IsHomogPartial(ConstRefRingElem f, long n)  // assumes n >= 0
92   {
93     CheckElemSparsePolyRing(f, "IsHomogPartial(f,n)");
94     return SparsePolyRingPtr(owner(f))->myIsHomogPartial(raw(f), n);
95   }
96 
97 
homog(ConstRefRingElem f,ConstRefRingElem h)98   RingElem homog(ConstRefRingElem f, ConstRefRingElem h)
99   {
100     const char* const FnName = "homog(RingElem, RingElem)";
101     CheckCompatible(f, h, FnName);
102     const SparsePolyRing P = owner(f);
103     if ( GradingDim(P)!=1 )
104       CoCoA_ERROR("GrDim must be 1", FnName);
105     if ( !IsIndet(h) )
106       CoCoA_ERROR("second arg must be an indeterminate", FnName);
107     if ( wdeg(h)[0]!=1 )
108       CoCoA_ERROR("degree of hom.indet must be 1", FnName);
109     RingElem fHom(P);
110     P->myHomog(raw(fHom), raw(f), raw(h));
111     return fHom;
112   }
113 
114 
LF(ConstRefRingElem f)115   RingElem LF(ConstRefRingElem f)
116   {
117     const char* const FnName = "LC(f)";
118     if (!IsSparsePolyRing(owner(f)))
119       CoCoA_ERROR(ERR::NotElemSparsePolyRing, FnName);
120     const SparsePolyRing& P = owner(f);
121     if (GradingDim(P) == 0)
122       CoCoA_ERROR("GradingDim must be non-0", FnName);
123     if (IsZero(f)) CoCoA_ERROR(ERR::ZeroRingElem, FnName);
124 
125     RingElem LeadingForm(P);
126     ConstRefPPMonoidElem LPPf(LPP(f));
127     for (SparsePolyIter it=BeginIter(f) ; !IsEnded(it) ; ++it )
128     {
129       if (CmpWDeg(PP(it), LPPf) != 0) break;
130       PushBack(LeadingForm, coeff(it), PP(it));
131     }
132     return LeadingForm;
133   }
134 
135 
CutLF(RingElem & f)136   RingElem CutLF(RingElem& f) // MODIFIES f
137   {
138     const char* const FnName = "CutLF(f)";
139     if (!IsSparsePolyRing(owner(f)))
140       CoCoA_ERROR(ERR::NotElemSparsePolyRing, FnName);
141     const SparsePolyRing& P = owner(f);
142     if (GradingDim(P) == 0)
143       CoCoA_ERROR("GradingDim must be non-0", FnName);
144     if (IsZero(f))
145       CoCoA_ERROR(ERR::ZeroRingElem, FnName);
146 
147     RingElem ans(P);
148     do
149     {
150       P->myMoveLMToBack(raw(ans), raw(f));
151     }
152     while (!IsZero(f) && (CmpWDeg(LPP(f), LPP(ans)) == 0));
153     return ans;
154   }
155 
156 
myIsHomogPartial(ConstRawPtr rawf,long n)157   bool SparsePolyRingBase::myIsHomogPartial(ConstRawPtr rawf, long n) const  // assumes 0 <= n <= GrDim
158   {
159     CoCoA_ASSERT(0 <= n && n <= myGradingDim());
160     if (myIsZero(rawf)) { return true; }
161     SparsePolyIter itf=myBeginIter(rawf);
162     const PPMonoidElem FirstPP=PP(itf);
163     for (++itf; !IsEnded(itf); ++itf)
164     {
165       CoCoA_ASSERT( cmp(FirstPP, PP(itf)) > 0 ); // assert f is correctly sorted
166       if ( CmpWDegPartial(FirstPP, PP(itf), n) != 0 )  return false;
167     }
168     return true;
169   }
170 
myIsHomog(ConstRawPtr rawf)171   bool SparsePolyRingBase::myIsHomog(ConstRawPtr rawf) const
172   {
173     if (myGradingDim()==0)
174       CoCoA_ERROR(ERR::ZeroGradingDim, "SparsePolyRingBase::myIsHomog");
175     if (myIsZero(rawf)) { return true; }
176     SparsePolyIter itf=myBeginIter(rawf);
177     const PPMonoidElem FirstPP=PP(itf);
178     for (++itf; !IsEnded(itf); ++itf)
179     {
180       CoCoA_ASSERT( cmp(FirstPP, PP(itf))>0 ); // assert f is correctly sorted
181       if ( CmpWDeg(FirstPP, PP(itf))!=0 )  return false;
182     }
183     return true;
184   }
185 
186 
myHomog(RawPtr rawfHom,ConstRawPtr rawf,ConstRawPtr rawh)187   void SparsePolyRingBase::myHomog(RawPtr rawfHom, ConstRawPtr rawf, ConstRawPtr rawh) const
188   {
189     const SparsePolyRing P(this);
190     RingElemAlias h(P,rawh);
191     CoCoA_ASSERT( myGradingDim()==1 );
192     CoCoA_ASSERT( IsIndet(h) );
193     CoCoA_ASSERT( IsOne(wdeg(h)[0]) );
194     geobucket gbk(P);  // accumulate result into a geobucket for speed
195     RingElemAlias f(P,rawf);
196     ConstRefPPMonoidElem PPh = LPP(h);
197     const BigInt d = wdeg(f)[0];
198     for (SparsePolyIter it=BeginIter(f) ; !IsEnded(it) ; ++it )
199     {
200       RingElem term = monomial(P, coeff(it),PP(it) * power(PPh,d-wdeg(PP(it))[0]));
201       gbk.myAddClear(term,1);
202     }
203     RingElem tmp(P);  // for exception safety
204     AddClear(tmp, gbk);
205     mySwap(rawfHom, raw(tmp));
206   }
207 
208 
HomogCompt(ConstRefRingElem f,long d)209   RingElem HomogCompt(ConstRefRingElem f, long d)
210   {
211     const ring& P = owner(f);
212     if (!IsSparsePolyRing(P)) CoCoA_ERROR(ERR::NotElemSparsePolyRing, "HomogCompt");
213     if (GradingDim(P) != 1) CoCoA_ERROR("GradingDim must be 1", "HomogCompt");
214     if (d < 0) CoCoA_ERROR(ERR::NotNonNegative, "HomogCompt");
215     RingElem form(P);
216     for (auto it=BeginIter(f); !IsEnded(it); ++it)
217     {
218       const long DegPP = ConvertTo<long>(wdeg(PP(it))[0]);
219 //      if (DegPP != d) continue; // ASSUME term-ord is wdeg compatible!!
220       if (DegPP > d) continue;
221       if (DegPP < d) break;
222       PushBack(form, coeff(it), PP(it));
223     }
224     return form;
225   }
226 
227 
228 } // end of namespace CoCoA
229 
230 // RCS header/log in the next few lines
231 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/SparsePolyOps-RingElem-homog.C,v 1.2 2020/03/11 17:06:55 abbott Exp $
232 // $Log: SparsePolyOps-RingElem-homog.C,v $
233 // Revision 1.2  2020/03/11 17:06:55  abbott
234 // Summary: Added check for GradingDim
235 //
236 // Revision 1.1  2020/03/11 17:00:27  abbott
237 // Summary: Added new fn HomogCompt; split of fns to do with homog polys into new file.  Cleaned includes.
238 //
239 //
240