CMS 3D CMS Logo

BitOps.h

Go to the documentation of this file.
00001 #ifndef CLASSLIB_BIT_OPS_H
00002 # define CLASSLIB_BIT_OPS_H
00003 
00004 //<<<<<< INCLUDES                                                       >>>>>>
00005 
00006 # include "classlib/utils/BitTraits.h"
00007 # include "classlib/utils/BitPattern.h"
00008 # include <algorithm>
00009 
00010 namespace lat {
00011 //<<<<<< PUBLIC DEFINES                                                 >>>>>>
00012 //<<<<<< PUBLIC CONSTANTS                                               >>>>>>
00013 //<<<<<< PUBLIC TYPES                                                   >>>>>>
00014 //<<<<<< PUBLIC VARIABLES                                               >>>>>>
00015 //<<<<<< PUBLIC FUNCTIONS                                               >>>>>>
00016 //<<<<<< CLASS DECLARATIONS                                             >>>>>>
00017 
00025 template <class T> class BitOps
00026 {
00027 public:
00028     // Various math ops
00029 
00030     static T            count (T n);
00031     static T            reverse (T n);
00032     static T            rzero (T n);
00033     static T            log2 (T n);
00034     static bool         islog2 (T n);
00035     static T            ceil2 (T n);
00036     static bool         parity (T n);
00037     static T            mortonInterleave (T x, T y);
00038     static void         mortonSplit (T n, T &x, T &y);
00039     static void         swap (T &x, T &y);
00040 
00041     // Bit extraction from a bit array of words T; requested bits may
00042     // (4, 5) or may not (2, 3) straddle `T' word boundaries; `count'
00043     // must be less than BitTraits<T>::Bits; bounded versions return 0
00044     // if `from > maxbit'; otherwise `from+count' must be less than or
00045     // equal to `maxbit'.  No attention is paid to word byte order.
00046     // See also BitIterator.
00047     static T            extract                 (T n, unsigned int from,
00048                                                  unsigned int count);
00049 
00050     static T            extractSafe             (const T *restrict p,
00051                                                  unsigned int from,
00052                                                  unsigned int count);
00053     static T            extractUnstraddled      (const T *restrict p,
00054                                                  unsigned int maxbit,
00055                                                  unsigned int from,
00056                                                  unsigned int count);
00057     // may straddle, except for the last array element
00058     static T            extractStraddledSafe    (const T *restrict p,
00059                                                  unsigned int from,
00060                                                  unsigned int count);
00061     static T            extract                 (const T *restrict p,
00062                                                  unsigned int maxbit,
00063                                                  unsigned int from,
00064                                                  unsigned int count);
00065 };
00066 
00068 
00094 template <unsigned int B> struct BitOpsMagic {
00095     template <class T> struct Type {
00096         // the binary magic number bit patterns
00097         enum { Pattern    = BitPattern<T,BitPattern<T,1,1,B>::Pattern,B*2,
00098                                        BitTraits<T>::Bits/(B*2)>::Pattern };
00099         enum { RevPattern = ~ Pattern };
00100     };
00101 };
00102 
00103 template <> struct BitOpsMagic<1> {
00104     template <class T> struct Type {
00105         enum { Pattern    = BitPattern<T,1,2,BitTraits<T>::Bits/2>::Pattern };
00106         enum { RevPattern = ~ Pattern };
00107     };
00108 };
00109 
00110 //<<<<<< INLINE PUBLIC FUNCTIONS                                        >>>>>>
00111 //<<<<<< INLINE MEMBER FUNCTIONS                                        >>>>>>
00112 
00116 
00117 template <class T> inline void
00118 BitOps<T>::swap (T &x, T &y)
00119 { x ^= y; y ^= x; x ^= y; }
00120 
00124 
00128 template <unsigned int B> struct BitOpsCount {
00129     template <class T> struct Op : BitOpsMagic<B>::template Type<T> {
00130         enum { Pattern = BitOpsMagic<B>::template Type<T>::Pattern };
00131         static T compute (T n) {
00132             n = BitOpsCount<B/2>::template Op<T>::compute (n);
00133             return ((n >> B) & Pattern) + (n & Pattern);
00134         }
00135     };
00136 };
00137 
00138 template <> struct BitOpsCount<1> {
00139     template <class T> struct Op : BitOpsMagic<1>::template Type<T> {
00140         enum { Pattern = BitOpsMagic<1>::template Type<T>::Pattern };
00141         static T compute (T n)
00142         { return ((n >> 1) & Pattern) + (n & Pattern); }
00143     };
00144 };
00145 
00147 template <class T> inline T
00148 BitOps<T>::count (T n)
00149 { return BitOpsCount<BitTraits<T>::Bits/2>::template Op<T>::compute (n); }
00150 
00154 
00158 template <unsigned int B> struct BitOpsReverse {
00159     template <class T> struct Op : BitOpsMagic<B>::template Type<T> {
00160         enum { Pattern = BitOpsMagic<B>::template Type<T>::Pattern };
00161         enum { RevPattern = BitOpsMagic<B>::template Type<T>::RevPattern };
00162         static T compute (T n) {
00163             n = BitOpsReverse<B/2>::template Op<T>::compute (n);
00164             n = ((n >> B) & Pattern) | ((n << B) & RevPattern);
00165             return n;
00166         }
00167     };
00168 };
00169 
00170 template <> struct BitOpsReverse<1> {
00171     template <class T> struct Op : BitOpsMagic<1>::template Type<T> {
00172         enum { Pattern = BitOpsMagic<1>::template Type<T>::Pattern };
00173         enum { RevPattern = BitOpsMagic<1>::template Type<T>::RevPattern };
00174         static T compute (T n)
00175         { return ((n >> 1) & Pattern) | ((n << 1) & RevPattern); }
00176     };
00177 };
00178 
00181 template <class T> inline T
00182 BitOps<T>::reverse (T n)
00183 { return BitOpsReverse<BitTraits<T>::Bits/2>::template Op<T>::compute (n); }
00184 
00188 
00192 template <unsigned int B> struct BitOpsRZero {
00193     template <class T> struct Op : BitOpsMagic<B>::template Type<T> {
00194         enum { Pattern = BitOpsMagic<B>::template Type<T>::Pattern };
00195         static T compute (T n, unsigned int c) {
00196             return n & Pattern
00197                 ? BitOpsRZero<B/2>::template Op<T>::compute (n << B, c - B)
00198                 : BitOpsRZero<B/2>::template Op<T>::compute (n, c);
00199         }
00200     };
00201 };
00202 
00203 template <> struct BitOpsRZero<1> {
00204     template <class T> struct Op : BitOpsMagic<1>::template Type<T> {
00205         enum { Pattern = BitOpsMagic<1>::template Type<T>::Pattern };
00206         static T compute (T n, unsigned int c) {
00207             if (n & Pattern)
00208             {
00209                 n <<= 1;
00210                 c--;
00211             }
00212             return n ? c-1 : c;
00213         }
00214     };
00215 };
00216 
00219 template <class T> inline T
00220 BitOps<T>::rzero (T n)
00221 { return BitOpsRZero<BitTraits<T>::Bits/2>::template Op<T>::compute
00222       (n, BitTraits<T>::Bits); }
00223 
00227 
00231 template <unsigned int B> struct BitOpsLog2 {
00232     template <class T> struct Op : BitOpsMagic<B>::template Type<T> {
00233         enum { RevPattern = BitOpsMagic<B>::template Type<T>::RevPattern };
00234         static T compute (T n, unsigned int c) {
00235             return n & RevPattern
00236                 ? BitOpsLog2<B/2>::template Op<T>::compute (n >> B, c | B)
00237                 : BitOpsLog2<B/2>::template Op<T>::compute (n, c);
00238         }
00239     };
00240 };
00241 
00242 template <> struct BitOpsLog2<1> {
00243     template <class T> struct Op : BitOpsMagic<1>::template Type<T> {
00244         enum { RevPattern = BitOpsMagic<1>::template Type<T>::RevPattern };
00245         static T compute (T n, unsigned int c)
00246         { return c | (n & RevPattern ? 1 : 0); }
00247     };
00248 };
00249 
00252 template <class T> inline T
00253 BitOps<T>::log2 (T n)
00254 { return BitOpsLog2<BitTraits<T>::Bits/2>::template Op<T>::compute (n, 0); }
00255 
00259 
00261 template <class T> inline bool
00262 BitOps<T>::islog2 (T n)
00263 { return (n & (n - 1)) == 0; }
00264 
00268 
00269 template <unsigned int B> struct BitOpsCeil2 {
00270     template <class T> struct Op : BitOpsMagic<B>::template Type<T> {
00271         static T compute (T n)
00272         { n = BitOpsCeil2<B/2>::template Op<T>::compute (n); return n | (n >> B); }
00273     };
00274 };
00275 
00276 template <> struct BitOpsCeil2<1> {
00277     template <class T> struct Op : BitOpsMagic<1>::template Type<T> {
00278         static T compute (T n)
00279         { return n | (n >> 1); }
00280     };
00281 };
00282 
00284 template <class T> inline T
00285 BitOps<T>::ceil2 (T n)
00286 { return BitOpsCeil2<BitTraits<T>::Bits/2>::template Op<T>::compute (n-1)+1; }
00287 
00291 
00292 template <unsigned int B> struct BitOpsParity {
00293     template <class T> struct Op : BitOpsMagic<B>::template Type<T> {
00294         /* n ^= n >> 16; n ^= n >> 8; n ^= n >> 4; n ^= n >> 2; n ^= n >> 1; */
00295         static T compute (T n)
00296         { return BitOpsParity<B/2>::template Op<T>::compute (n ^ (n >> B)); }
00297     };
00298 };
00299 
00300 template <> struct BitOpsParity<1> {
00301     template <class T> struct Op : BitOpsMagic<1>::template Type<T> {
00302         static T compute (T n)
00303         { return n ^ (n >> 1); }
00304     };
00305 };
00306 
00309 template <class T> inline bool
00310 BitOps<T>::parity (T n)
00311 { return BitOpsParity<BitTraits<T>::Bits/2>::template Op<T>::compute (n) & 1; }
00312 
00316 
00330 template <unsigned int B> struct BitOpsMortonInterleave {
00331     template <class T> struct Op : BitOpsMagic<B>::template Type<T> {
00332         enum { Pattern = BitOpsMagic<B>::template Type<T>::Pattern };
00333         static T compute (T n)
00334         { return BitOpsMortonInterleave<B/2>::template Op<T>::compute ((n | (n << B)) & Pattern); }
00335     };
00336 };
00337 
00338 template <> struct BitOpsMortonInterleave<1> {
00339     template <class T> struct Op : BitOpsMagic<1>::template Type<T> {
00340         enum { Pattern = BitOpsMagic<1>::template Type<T>::Pattern };
00341         static T compute (T n)
00342         { return (n | (n << 1)) & Pattern; }
00343     };
00344 };
00345 
00358 template <unsigned int B> struct BitOpsMortonExtract {
00359     template <class T> struct Op : BitOpsMagic<B>::template Type<T> {
00360         enum { Pattern = BitOpsMagic<B>::template Type<T>::Pattern };
00361         static T compute (T n) {
00362             n = BitOpsMortonExtract<B/2>::template Op<T>::compute (n) & Pattern;
00363             return n | (n >> B);
00364         }
00365     };
00366 };
00367 
00368 template <> struct BitOpsMortonExtract<1> {
00369     template <class T> struct Op : BitOpsMagic<1>::template Type<T> {
00370         enum { Pattern = BitOpsMagic<1>::template Type<T>::Pattern };
00371         static T compute (T n)
00372         { n &= Pattern; return n | (n >> 1); }
00373     };
00374 };
00375 
00387 template <class T> inline T
00388 BitOps<T>::mortonInterleave (T x, T y)
00389 { return BitOpsMortonInterleave<BitTraits<T>::Bits/4>::template Op<T>::compute (x)
00390       | (BitOpsMortonInterleave<BitTraits<T>::Bits/4>::template Op<T>::compute (y) << 1); }
00391 
00395 template <class T> inline void
00396 BitOps<T>::mortonSplit (T n, T &x, T &y)
00397 {
00398     x = BitOpsMortonExtract<BitTraits<T>::Bits/4>::template Op<T>::compute (n);
00399     y = BitOpsMortonExtract<BitTraits<T>::Bits/4>::template Op<T>::compute (n >> 1);
00400 }
00401 
00405 
00408 template <class T> inline T
00409 BitOps<T>::extract (T n, unsigned int from, unsigned int count)
00410 {
00411     enum { AllOnes = BitPattern<T,0xff,8,BitTraits<T>::Bytes>::Pattern };
00412     return (n >> (BitTraits<T>::Bits - from - count)) & ~(AllOnes << count);
00413 }
00414 
00429 template <class T> inline T
00430 BitOps<T>::extractSafe (const T *restrict p, unsigned int from,
00431                          unsigned int count)
00432 {
00433     return extract (* (p + from/BitTraits<T>::Bits),
00434                     from % BitTraits<T>::Bits,
00435                     count);
00436 }
00437 
00453 template <class T> inline T
00454 BitOps<T>::extractUnstraddled (const T *restrict p, unsigned int maxbit,
00455                                unsigned int from, unsigned int count)
00456 { return from > maxbit ? 0 : extractSafe (p, from, count); }
00457 
00475 template <class T> inline T
00476 BitOps<T>::extractStraddledSafe (const T *restrict p, unsigned int from,
00477                                  unsigned int count)
00478 {
00479     unsigned int count_word_1 = std::min(count,
00480                                          BitTraits<T>::Bits
00481                                          - from % BitTraits<T>::Bits);
00482     unsigned int count_word_2 = count - count_word_1;
00483 
00484     return (extractSafe (p, from, count_word_1) << count_word_2
00485             | extractSafe (p, from+count_word_1, count_word_2));
00486 }
00487 
00505 template <class T> inline T
00506 BitOps<T>::extract (const T *restrict p, unsigned int maxbit,
00507                     unsigned int from, unsigned int count)
00508 { return from > maxbit ? 0 : extractStraddledSafe (p, from, count); }
00509 
00510 } // namespace lat
00511 #endif // CLASSLIB_BIT_OPS_H

Generated on Tue Jun 9 17:38:54 2009 for CMSSW by  doxygen 1.5.4