00001 #ifndef CLASSLIB_BIT_OPS_H
00002 # define CLASSLIB_BIT_OPS_H
00003
00004
00005
00006 # include "classlib/utils/BitTraits.h"
00007 # include "classlib/utils/BitPattern.h"
00008 # include <algorithm>
00009
00010 namespace lat {
00011
00012
00013
00014
00015
00016
00017
00025 template <class T> class BitOps
00026 {
00027 public:
00028
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
00042
00043
00044
00045
00046
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
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
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
00111
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
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 }
00511 #endif // CLASSLIB_BIT_OPS_H