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