1 //   Copyright (c)  2005-2007,2009  John Abbott
2 
3 //   This file is part of the source of CoCoALib, the CoCoA Library.
4 
5 //   CoCoALib is free software: you can redistribute it and/or modify
6 //   it under the terms of the GNU General Public License as published by
7 //   the Free Software Foundation, either version 3 of the License, or
8 //   (at your option) any later version.
9 
10 //   CoCoALib is distributed in the hope that it will be useful,
11 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //   GNU General Public License for more details.
14 
15 //   You should have received a copy of the GNU General Public License
16 //   along with CoCoALib.  If not, see <http://www.gnu.org/licenses/>.
17 
18 
19 #include "CoCoA/DivMask.H"
20 #include "CoCoA/assert.H"
21 
22 #include <iostream>
23 using std::ostream;
24 
25 namespace CoCoA
26 {
27 
28   namespace
29   {
30     // our own defn of min -- does not need addrs of its args
min(long a,long b)31     inline long min(long a, long b) { if (a < b) return a; else return b; }
32   }
33 
34 
35   std::ostream& operator<<(std::ostream& out, const DivMask& dm)
36   {
37     if (!out) return out;  // short-cut for bad ostreams
38     return out << "DivMask(" << bits(dm) << ")";
39   }
40 
41 
42   namespace DvMskRule
43   {
44 
45     // Next come the definitions of the various concrete DivMask rules: these are
46     // in the .C file rather than the .H because they do not need to be in the .H
47     // file, and it seems pointless cluttering the .H with unnecessary
48     // implementation details.
49 
50 
51     //-- class DivMaskNullImpl --------------------------------------------
52 
53     class NullImpl: public DivMaskRuleBase
54     {
55     public:
56       // Default ctor and dtor are fine; nobody uses copy ctor or assignment.
57       virtual void myAssignFromExpv(DivMask& dm, const SmallExponent_t* expv, long NumIndets) const;
58       virtual void myOutputSelf(std::ostream& out) const;
59     };
60 
61 
myAssignFromExpv(DivMask & dm,const SmallExponent_t *,long)62     void NullImpl::myAssignFromExpv(DivMask& dm, const SmallExponent_t* /*expv*/, long /*NumIndets*/) const
63     {
64       myBits(dm).reset();
65     }
66 
67 
myOutputSelf(std::ostream & out)68     void NullImpl::myOutputSelf(std::ostream& out) const
69     {
70       if (!out) return;  // short-cut for bad ostreams
71       out << "DivMaskNull";
72     }
73 
74 
75     //-- class SingleBitImpl -----------------------------------------
76 
77     class SingleBitImpl: public DivMaskRuleBase
78     {
79     public:
80       // Default ctor and dtor are fine; nobody uses copy ctor or assignment.
81       virtual void myAssignFromExpv(DivMask& dm, const SmallExponent_t* expv, long NumIndets) const;
82       virtual void myOutputSelf(std::ostream& out) const;
83     };
84 
85 
myAssignFromExpv(DivMask & dm,const SmallExponent_t * expv,long NumIndets)86     void SingleBitImpl::myAssignFromExpv(DivMask& dm, const SmallExponent_t* expv, long NumIndets) const
87     {
88       CoCoA_ASSERT(NumIndets > 0);
89       myBits(dm).reset();
90       const long imax = min(NumIndets, DivMask::ourMaskWidth);
91       for (long i=0; i < imax; ++i)
92         if (expv[i] > 0)
93           myBits(dm).set(i);
94     }
95 
96 
myOutputSelf(std::ostream & out)97     void SingleBitImpl::myOutputSelf(std::ostream& out) const
98     {
99       if (!out) return;  // short-cut for bad ostreams
100       out << "DivMaskSingleBit";
101     }
102 
103 
104     //-- class SingleBitWrapImpl -----------------------------------------
105 
106     class SingleBitWrapImpl: public DivMaskRuleBase
107     {
108     public:
109       // Default ctor and dtor are fine; nobody uses copy ctor or assignment.
110       virtual void myAssignFromExpv(DivMask& dm, const SmallExponent_t* expv, long NumIndets) const;
111       virtual void myOutputSelf(std::ostream& out) const;
112     };
113 
114 
myAssignFromExpv(DivMask & dm,const SmallExponent_t * expv,long NumIndets)115     void SingleBitWrapImpl::myAssignFromExpv(DivMask& dm, const SmallExponent_t* expv, long NumIndets) const
116     {
117       CoCoA_ASSERT(NumIndets > 0);
118       myBits(dm).reset();
119       for (long indet=0; indet < NumIndets; ++indet)
120       {
121         if (expv[indet] > 0)
122           // NB: i&(ourMaskWidth-1) = i%ourMaskWidth (which is a power of 2)
123           myBits(dm).set(indet&(DivMask::ourMaskWidth-1));
124       }
125     }
126 
127 
myOutputSelf(std::ostream & out)128     void SingleBitWrapImpl::myOutputSelf(std::ostream& out) const
129     {
130       if (!out) return;  // short-cut for bad ostreams
131       out << "DivMaskSingleBitWrap";
132     }
133 
134 
135     //-- class EvenPowersImpl -----------------------------------------
136 
137     class EvenPowersImpl: public DivMaskRuleBase
138     {
139     public:
140       // Default ctor and dtor are fine; nobody uses copy ctor or assignment.
141       virtual void myAssignFromExpv(DivMask& dm, const SmallExponent_t* expv, long NumIndets) const;
142       virtual void myOutputSelf(std::ostream& out) const;
143     };
144 
145 
myAssignFromExpv(DivMask & dm,const SmallExponent_t * expv,long NumIndets)146     void EvenPowersImpl::myAssignFromExpv(DivMask& dm, const SmallExponent_t* expv, long NumIndets) const
147     {
148       CoCoA_ASSERT(NumIndets > 0);
149       myBits(dm).reset();
150       const long NumBitsPerIndet = DivMask::ourMaskWidth/NumIndets;
151       if (NumBitsPerIndet<2)
152       {
153         for (long i = 0; i < NumIndets; ++i)
154           // NB: i&(ourMaskWidth-1) = i%ourMaskWidth (which is a power of 2)
155           if (expv[i]) myBits(dm).set(i&(DivMask::ourMaskWidth-1));
156         for (long i = NumIndets, indt = 0; i < DivMask::ourMaskWidth; ++i, ++indt )
157           if (expv[indt]>1)  myBits(dm).set(i);
158       }
159       else
160       {
161         long i = 0;
162         unsigned long b = 0;
163         for (long indt = 0; i < NumBitsPerIndet*NumIndets; ++i, ++indt)
164         {
165           if (indt==NumIndets) { indt=0; ++b;}
166           if (expv[indt]>2*b)  myBits(dm).set(i);
167         }
168         for (long indt = 0; i < DivMask::ourMaskWidth; ++i, ++indt)
169           if (expv[indt]>1)  myBits(dm).set(i);
170       }
171     }
172 
173 
myOutputSelf(std::ostream & out)174     void EvenPowersImpl::myOutputSelf(std::ostream& out) const
175     {
176       if (!out) return;  // short-cut for bad ostreams
177       out << "DivMaskEvenPowers";
178     }
179 
180 
181 
182     //-- class HashingImpl -----------------------------------------
183 
184     class HashingImpl: public DivMaskRuleBase
185     {
186     public:
187       // Default ctor and dtor are fine; nobody uses copy ctor or assignment.
188       virtual void myAssignFromExpv(DivMask& dm, const SmallExponent_t* expv, long NumIndets) const;
189       virtual void myOutputSelf(std::ostream& out) const;
190     private:
191       void myAdjoin(DivMask& dm, long var, SmallExponent_t exp) const;
192     };
193 
194 
195     // This impl prefers simplicity over speed.  Might get fixed later; might not.
myAssignFromExpv(DivMask & dm,const SmallExponent_t * expv,long NumIndets)196     void HashingImpl::myAssignFromExpv(DivMask& dm, const SmallExponent_t* expv, long NumIndets) const
197     {
198       CoCoA_ASSERT(NumIndets > 0);
199       myBits(dm).reset();
200       for (long indet=0; indet < NumIndets; ++indet)
201       {
202         if (expv[indet] > 0)
203           myAdjoin(dm, indet, expv[indet]);
204       }
205     }
206 
207 
myAdjoin(DivMask & dm,long indet,SmallExponent_t exp)208     void HashingImpl::myAdjoin(DivMask& dm, long indet, SmallExponent_t exp) const
209     {
210       CoCoA_ASSERT(indet >= 0);
211       CoCoA_ASSERT(exp > 0);
212       const unsigned long W = DivMask::ourMaskWidth; // W is just shorthand
213       unsigned long index = indet%W;
214       const long step = (24*(indet/W)+13)%W; // just a heuristic
215       for (unsigned long k=0; k < W && k*k < exp; ++k) // limit max value of k??
216       {
217         myBits(dm).set(index);
218         index += step;
219         if (index >= W) index -= W;
220       }
221     }
222 
223 
myOutputSelf(std::ostream & out)224     void HashingImpl::myOutputSelf(std::ostream& out) const
225     {
226       if (!out) return;  // short-cut for bad ostreams
227       out << "DivMaskHashing";
228     }
229 
230   }  // end of namespace DvMskRule
231 
232 
233   //----------------------------------------------------------------------
234 
235   // This simply prints out the name of the divmask rule.
236   std::ostream& operator<<(std::ostream& out, const DivMaskRule& DMR)
237   {
238     if (!out) return out;  // short-cut for bad ostreams
239     DMR->myOutputSelf(out);
240     return out;
241   }
242 
243 
244   //----------------------------------------------------------------------
245   // Here are the pseudo-constructors:
246 
NewDivMaskNull()247   DivMaskRule NewDivMaskNull()
248   {
249     return DivMaskRule(new DvMskRule::NullImpl());
250   }
251 
NewDivMaskSingleBit()252   DivMaskRule NewDivMaskSingleBit()
253   {
254     return DivMaskRule(new DvMskRule::SingleBitImpl());
255   }
256 
NewDivMaskSingleBitWrap()257   DivMaskRule NewDivMaskSingleBitWrap()
258   {
259     return DivMaskRule(new DvMskRule::SingleBitWrapImpl());
260   }
261 
NewDivMaskEvenPowers()262   DivMaskRule NewDivMaskEvenPowers()
263   {
264     return DivMaskRule(new DvMskRule::EvenPowersImpl());
265   }
266 
NewDivMaskHashing()267   DivMaskRule NewDivMaskHashing()
268   {
269     return DivMaskRule(new DvMskRule::HashingImpl());
270   }
271 
272 
273 } // end of namespace CoCoA
274 
275 
276 
277 // RCS header/log in the next few lines
278 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/DivMask.C,v 1.11 2020/02/11 16:56:40 abbott Exp $
279 // $Log: DivMask.C,v $
280 // Revision 1.11  2020/02/11 16:56:40  abbott
281 // Summary: Corrected last update (see redmine 969)
282 //
283 // Revision 1.10  2020/02/11 16:12:17  abbott
284 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969
285 //
286 // Revision 1.9  2016/11/11 14:15:32  abbott
287 // Summary: Added short-cut to operator<< when ostream is in bad state
288 //
289 // Revision 1.8  2012/04/03 15:14:53  abbott
290 // Removed defn of static DivMask::ourMaskWidth.
291 // Uses own defn of min -- std::min needs addrs of its args.
292 //
293 // Revision 1.7  2012/02/06 18:32:32  bigatti
294 // -- changed MaskWidth --> ourMaskWidth
295 // -- removed doxygen include
296 //
297 // Revision 1.6  2011/05/03 10:05:41  abbott
298 // Minor (invisible) change to avoid compiler warnings about comparison of signed & unsigned.
299 //
300 // Revision 1.5  2011/03/14 10:24:03  abbott
301 // Changed size_t into long.
302 //
303 // Revision 1.4  2010/02/01 22:44:22  abbott
304 // Changed hash functions used in hashing DivMask.
305 //
306 // Revision 1.3  2009/09/24 14:13:31  abbott
307 // Added some missing "std::" prefixes, and removed some unnecessary ones.
308 //
309 // Revision 1.2  2007/10/30 17:14:08  abbott
310 // Changed licence from GPL-2 only to GPL-3 or later.
311 // New version for such an important change.
312 //
313 // Revision 1.1.1.1  2007/03/09 15:16:11  abbott
314 // Imported files
315 //
316 // Revision 1.6  2007/03/08 18:22:29  cocoa
317 // Just whitespace cleaning.
318 //
319 // Revision 1.5  2007/03/07 13:43:35  bigatti
320 // -- minor cleanup for -Wextra
321 //
322 // Revision 1.4  2006/11/29 17:33:30  cocoa
323 // -- use of namespace DvMskRule (should we find a better name for
324 //    "hidden" namespaces?)
325 //
326 // Revision 1.3  2006/10/06 14:04:15  cocoa
327 // Corrected position of #ifndef in header files.
328 // Separated CoCoA_ASSERT into assert.H from config.H;
329 // many minor consequential changes (have to #include assert.H).
330 // A little tidying of #include directives (esp. in Max's code).
331 //
332 // Revision 1.2  2006/08/07 21:23:25  cocoa
333 // Removed almost all publicly visible references to SmallExponent_t;
334 // changed to long in all PPMonoid functions and SparsePolyRing functions.
335 // DivMask remains to sorted out.
336 //
337 // Revision 1.1.1.1  2006/05/30 11:39:37  cocoa
338 // Imported files
339 //
340 // Revision 1.6  2006/03/15 18:09:31  cocoa
341 // Changed names of member functions which print out their object
342 // into myOutputSelf -- hope this will appease the Intel C++ compiler.
343 //
344 // Revision 1.5  2006/03/12 21:28:34  cocoa
345 // Major check in after many changes
346 //
347 // Revision 1.4  2006/01/18 16:15:16  cocoa
348 // Cleaned up DivMask considerably; everything still works,
349 // so I'm checking in (and then going home).
350 //
351 // Revision 1.3  2006/01/17 18:08:01  cocoa
352 // Added new DivMask type: DivMaskHashingImpl.
353 // Updated DivMask documentation.
354 //
355