00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #if !defined(_XRB_BITARRAY_HPP_)
00012 #define _XRB_BITARRAY_HPP_
00013
00014 #include "xrb.hpp"
00015
00016 #include <stdio.h>
00017 #include <string.h>
00018
00019 namespace Xrb
00020 {
00021
00022 template <Uint32 bit_count>
00023 class BitArray
00024 {
00025 public:
00026
00027
00028
00029
00030 enum
00031 {
00032 BIT_COUNT = bit_count,
00033 HIGHEST_BIT_INDEX = bit_count - 1,
00034
00035 WORD_COUNT = (bit_count - 1) / 32 + 1,
00036 HIGHEST_WORD_INDEX = (bit_count - 1) / 32,
00037
00038
00039 WORD_SIZE_IN_BITS = sizeof(Uint32) * 8,
00040 WORD_SIZE_IN_BYTES = sizeof(Uint32),
00041 };
00042
00043
00044
00045
00046 enum BitValue
00047 {
00048 ZERO = 0,
00049 ONE = 1
00050 };
00051
00052
00053 static BitArray<bit_count> const ms_zero;
00054
00055 static BitArray<bit_count> const ms_one;
00056
00057 inline BitArray ()
00058 {
00059 ASSERT1(bit_count > 0);
00060 m_words[HIGHEST_WORD_INDEX] &= USED_BIT_MASK;
00061 ASSERT1(AreUnusedBitsZeroed());
00062 }
00063 inline BitArray (BitValue const fill_with)
00064 {
00065 ASSERT1(bit_count > 0);
00066 SetAllBits((fill_with == ONE) ? true : false);
00067 ASSERT1(AreUnusedBitsZeroed());
00068 }
00069 inline BitArray (Uint32 const assign_to_least_significant_word)
00070 {
00071 ASSERT1(bit_count > 0);
00072
00073 #if defined(XRB_BITARRAY_USES_MEMSET)
00074 if (WORD_COUNT > 1)
00075 memset(reinterpret_cast<Uint8 *>(m_words + 1),
00076 0x00,
00077 (WORD_COUNT - 1) * sizeof(Uint32));
00078 #else
00079 if (WORD_COUNT > 1)
00080 for (Uint32 i = 1; i < WORD_COUNT; ++i)
00081 m_words[i] = 0x00000000;
00082 #endif
00083
00084 m_words[0] = assign_to_least_significant_word;
00085 m_words[HIGHEST_WORD_INDEX] &= USED_BIT_MASK;
00086 ASSERT1(AreUnusedBitsZeroed());
00087 }
00088 inline BitArray (BitArray<bit_count> const &source)
00089 {
00090 ASSERT1(bit_count > 0);
00091 #if defined(XRB_BITARRAY_USES_MEMCPY)
00092 memcpy(reinterpret_cast<Uint8 *>(m_words),
00093 reinterpret_cast<Uint8 const *>(source.m_words),
00094 WORD_COUNT * sizeof(Uint32));
00095 #else
00096 for (Uint32 i = 0; i < WORD_COUNT; ++i)
00097 m_words[i] = source.m_words[i];
00098 #endif
00099 ASSERT1(AreUnusedBitsZeroed());
00100 }
00101 inline ~BitArray ()
00102 {
00103 ASSERT1(AreUnusedBitsZeroed());
00104 }
00105
00106 inline bool Bit (Uint32 const bit_index) const
00107 {
00108 ASSERT1(AreUnusedBitsZeroed());
00109 ASSERT1(bit_index < bit_count);
00110
00111 Uint32 major_index = bit_index >> 5;
00112 Uint32 minor_index = bit_index & 31;
00113
00114 Uint32 bit_mask = 1 << minor_index;
00115 return (m_words[major_index] & bit_mask) != 0;
00116 }
00117 inline Uint32 Word (Uint32 const word_index) const
00118 {
00119 ASSERT1(AreUnusedBitsZeroed());
00120 ASSERT1(word_index <= HIGHEST_WORD_INDEX);
00121 return m_words[word_index];
00122 }
00123
00124 inline void SetBit (Uint32 const bit_index, bool const value)
00125 {
00126 ASSERT1(bit_index < bit_count);
00127
00128 Uint32 major_index = bit_index >> 5;
00129 Uint32 minor_index = bit_index & 31;
00130
00131 Uint32 bit_mask = 1 << minor_index;
00132 m_words[major_index] ^= bit_mask;
00133 }
00134 inline void SetAllBits (bool const value)
00135 {
00136 if (value)
00137 {
00138 #if defined(XRB_BITARRAY_USES_MEMSET)
00139 memset(reinterpret_cast<Uint8 *>(m_words),
00140 0xFF,
00141 WORD_COUNT * sizeof(Uint32));
00142 #else
00143 for (Uint32 i = 0; i < WORD_COUNT; ++i)
00144 m_words[i] = 0xFFFFFFFF;
00145 #endif
00146 m_words[HIGHEST_WORD_INDEX] &= USED_BIT_MASK;
00147 }
00148 else
00149 {
00150 #if defined(XRB_BITARRAY_USES_MEMSET)
00151 memset(reinterpret_cast<Uint8 *>(m_words),
00152 0x00,
00153 WORD_COUNT * sizeof(Uint32));
00154 #else
00155 for (Uint32 i = 0; i < WORD_COUNT; ++i)
00156 m_words[i] = 0x00000000;
00157 #endif
00158 }
00159 ASSERT1(AreUnusedBitsZeroed());
00160 }
00161 inline void SetWord (Uint32 const word_index, Uint32 const value)
00162 {
00163 ASSERT1(word_index <= HIGHEST_WORD_INDEX);
00164 m_words[word_index] = value;
00165 m_words[HIGHEST_WORD_INDEX] &= USED_BIT_MASK;
00166 ASSERT1(AreUnusedBitsZeroed());
00167 }
00168
00169 inline void Negate ()
00170 {
00171 for (Uint32 i = 0; i < WORD_COUNT; ++i)
00172 m_words[i] = ~m_words[i];
00173 m_words[HIGHEST_WORD_INDEX] &= USED_BIT_MASK;
00174 ASSERT1(AreUnusedBitsZeroed());
00175 }
00176
00177
00178 inline void operator = (Uint32 const right_operand)
00179 {
00180
00181 #if defined(XRB_BITARRAY_USES_MEMSET)
00182 if (WORD_COUNT > 1)
00183 memset(reinterpret_cast<Uint8 *>(m_words + 1),
00184 0x00,
00185 (WORD_COUNT - 1) * sizeof(Uint32));
00186 #else
00187 if (WORD_COUNT > 1)
00188 for (Uint32 i = 1; i < WORD_COUNT; ++i)
00189 m_words[i] = 0x00000000;
00190 #endif
00191
00192 m_words[0] = right_operand;
00193 m_words[HIGHEST_WORD_INDEX] &= USED_BIT_MASK;
00194 ASSERT1(AreUnusedBitsZeroed());
00195 }
00196
00197 inline void operator = (BitArray<bit_count> const &right_operand)
00198 {
00199 #if defined(XRB_BITARRAY_USES_MEMCPY)
00200 memcpy(reinterpret_cast<Uint8 *>(m_words),
00201 reinterpret_cast<Uint8 const *>(right_operand.m_words),
00202 WORD_COUNT * sizeof(Uint32));
00203 #else
00204 for (Uint32 i = 0; i < WORD_COUNT; ++i)
00205 m_words[i] = right_operand.m_words[i];
00206 #endif
00207 ASSERT1(AreUnusedBitsZeroed());
00208 }
00209
00210
00211 inline bool operator == (BitArray const &right_operand) const
00212 {
00213 ASSERT1(AreUnusedBitsZeroed());
00214 ASSERT1(right_operand.AreUnusedBitsZeroed());
00215 #if defined(XRB_BITARRAY_USES_MEMCMP)
00216 return 0 == memcmp(reinterpret_cast<Uint8 const *>(m_words),
00217 reinterpret_cast<Uint8 const *>(right_operand.m_words),
00218 WORD_COUNT);
00219 #else
00220 for (Uint32 i = 0; i < WORD_COUNT; ++i)
00221 if (m_words[i] != right_operand.m_words[i])
00222 return false;
00223 return true;
00224 #endif
00225 }
00226
00227 inline bool operator != (BitArray const &right_operand) const
00228 {
00229 ASSERT1(AreUnusedBitsZeroed());
00230 ASSERT1(right_operand.AreUnusedBitsZeroed());
00231 #if defined(XRB_BITARRAY_USES_MEMCMP)
00232 return 0 != memcmp(reinterpret_cast<Uint8 const *>(m_words),
00233 reinterpret_cast<Uint8 const *>(right_operand.m_words),
00234 WORD_COUNT);
00235 #else
00236 for (Uint32 i = 0; i < WORD_COUNT; ++i)
00237 if (m_words[i] != right_operand.m_words[i])
00238 return true;
00239 return false;
00240 #endif
00241 }
00242
00243
00244 inline void operator |= (BitArray const &right_operand)
00245 {
00246 ASSERT1(AreUnusedBitsZeroed());
00247 ASSERT1(right_operand.AreUnusedBitsZeroed());
00248 for (Uint32 i = 0; i <= HIGHEST_WORD_INDEX; ++i)
00249 m_words[i] |= right_operand.m_words[i];
00250 ASSERT1(AreUnusedBitsZeroed());
00251 }
00252
00253 inline void operator &= (BitArray const &right_operand)
00254 {
00255 ASSERT1(AreUnusedBitsZeroed());
00256 ASSERT1(right_operand.AreUnusedBitsZeroed());
00257 for (Uint32 i = 0; i <= HIGHEST_WORD_INDEX; ++i)
00258 m_words[i] &= right_operand.m_words[i];
00259 ASSERT1(AreUnusedBitsZeroed());
00260 }
00261
00262 inline void operator ^= (BitArray const &right_operand)
00263 {
00264 ASSERT1(AreUnusedBitsZeroed());
00265 ASSERT1(right_operand.AreUnusedBitsZeroed());
00266 for (Uint32 i = 0; i <= HIGHEST_WORD_INDEX; ++i)
00267 m_words[i] ^= right_operand.m_words[i];
00268 ASSERT1(AreUnusedBitsZeroed());
00269 }
00270
00271
00272 inline void operator <<= (Uint32 const right_operand)
00273 {
00274 ASSERT1(AreUnusedBitsZeroed());
00275 if (right_operand == 0)
00276 return;
00277 Uint32 i;
00278 Uint32 word_delta = right_operand >> 5;
00279 Uint32 minor_shift = right_operand & 31;
00280 if (minor_shift == 0)
00281 {
00282 for (i = HIGHEST_WORD_INDEX; i >= word_delta; --i)
00283 m_words[i] = m_words[i-word_delta];
00284 for (i = word_delta - 1; i < HIGHEST_WORD_INDEX; --i)
00285 m_words[i] = 0;
00286 }
00287 else
00288 {
00289 for (i = HIGHEST_WORD_INDEX; i > word_delta; --i)
00290 m_words[i] = (m_words[i-word_delta] << minor_shift) |
00291 (m_words[i-1-word_delta] >> (32 - minor_shift));
00292 m_words[i] = m_words[i-word_delta] << minor_shift;
00293 for (i = word_delta - 1; i < HIGHEST_WORD_INDEX; --i)
00294 m_words[i] = 0;
00295 }
00296 m_words[HIGHEST_WORD_INDEX] &= USED_BIT_MASK;
00297 ASSERT1(AreUnusedBitsZeroed());
00298 }
00299
00300 inline void operator >>= (Uint32 const right_operand)
00301 {
00302 ASSERT1(AreUnusedBitsZeroed());
00303 if (right_operand == 0)
00304 return;
00305 Uint32 i;
00306 Uint32 word_delta = right_operand >> 5;
00307 Uint32 minor_shift = right_operand & 31;
00308 if (minor_shift == 0)
00309 {
00310 for (i = 0; i <= HIGHEST_WORD_INDEX - word_delta; ++i)
00311 m_words[i] = m_words[i+word_delta];
00312 for (i = HIGHEST_WORD_INDEX - word_delta + 1; i <= HIGHEST_WORD_INDEX; ++i)
00313 m_words[i] = 0;
00314 }
00315 else
00316 {
00317 for (i = 0; i < HIGHEST_WORD_INDEX - word_delta; ++i)
00318 m_words[i] = (m_words[i+1+word_delta] << (32 - minor_shift)) |
00319 (m_words[i+word_delta] >> minor_shift);
00320 m_words[i] = m_words[i+word_delta] >> minor_shift;
00321 for (i = HIGHEST_WORD_INDEX - word_delta + 1; i <= HIGHEST_WORD_INDEX; ++i)
00322 m_words[i] = 0;
00323 }
00324 ASSERT1(AreUnusedBitsZeroed());
00325 }
00326
00327 inline BitArray<bit_count> operator ~ ()
00328 {
00329 BitArray<bit_count> retval(*this);
00330 retval.Negate();
00331 return retval;
00332 }
00333
00334 void Fprint (FILE *fptr, Uint32 chunk_size = 8, bool add_newline = true) const;
00335 void FprintAsWords (FILE *fptr, bool add_newline = true) const;
00336
00337 private:
00338
00339 enum
00340 {
00341
00342
00343
00344 QUASI_HIGHEST_BIT_INDEX = ((HIGHEST_BIT_INDEX % 32) > 30) ? 30 : (HIGHEST_BIT_INDEX % 32),
00345
00346
00347 INTERMEDIATE_BIT_MASK = ((static_cast<Uint32>(1) << (QUASI_HIGHEST_BIT_INDEX + 1)) - 1),
00348
00349
00350
00351 USED_BIT_MASK = (bit_count % 32 == 0) ? 0xFFFFFFFF : INTERMEDIATE_BIT_MASK,
00352
00353
00354
00355 UNUSED_BIT_MASK = (bit_count % 32 == 0) ? 0x00000000 : ~INTERMEDIATE_BIT_MASK
00356 };
00357
00358
00359
00360
00361 inline bool AreUnusedBitsZeroed () const
00362 {
00363 return (m_words[HIGHEST_WORD_INDEX] & UNUSED_BIT_MASK) == 0;
00364 }
00365
00366
00367 Uint32 m_words[WORD_COUNT];
00368 };
00369
00370 template <Uint32 bit_count>
00371 BitArray<bit_count> const BitArray<bit_count>::ms_zero(ZERO);
00372
00373 template <Uint32 bit_count>
00374 BitArray<bit_count> const BitArray<bit_count>::ms_one(ONE);
00375
00376 template <Uint32 bit_count>
00377 void BitArray<bit_count>::Fprint (
00378 FILE *const fptr,
00379 Uint32 const chunk_size,
00380 bool const add_newline) const
00381 {
00382 fprintf(fptr, "BitArray (%u) = (", bit_count);
00383 for (Uint32 i = HIGHEST_BIT_INDEX; i <= HIGHEST_BIT_INDEX; --i)
00384 {
00385 fputc(Bit(i) ? '1' : '0', fptr);
00386 if (i != 0 &&
00387 chunk_size != 0 &&
00388 i % chunk_size == 0)
00389 {
00390 fputc(' ', fptr);
00391 }
00392 }
00393 fprintf(fptr, ")%c", add_newline ? '\n' : '\0');
00394 }
00395
00396 template <Uint32 bit_count>
00397 void BitArray<bit_count>::FprintAsWords (
00398 FILE *const fptr,
00399 bool const add_newline) const
00400 {
00401 fprintf(fptr, "BitArray (%u) words = (", bit_count);
00402 for (Uint32 i = HIGHEST_WORD_INDEX; i <= HIGHEST_WORD_INDEX; --i)
00403 {
00404 fprintf(fptr, "%08X", Word(i));
00405 if (i > 0)
00406 fputc(' ', fptr);
00407 }
00408 fprintf(fptr, ")%c", add_newline ? '\n' : '\0');
00409 }
00410
00411 template <Uint32 bit_count>
00412 inline BitArray<bit_count> operator | (
00413 BitArray<bit_count> const &left_operand,
00414 BitArray<bit_count> const &right_operand)
00415 {
00416 BitArray<bit_count> retval(left_operand);
00417 retval |= right_operand;
00418 return retval;
00419 }
00420
00421 template <Uint32 bit_count>
00422 inline BitArray<bit_count> operator & (
00423 BitArray<bit_count> const &left_operand,
00424 BitArray<bit_count> const &right_operand)
00425 {
00426 BitArray<bit_count> retval(left_operand);
00427 retval &= right_operand;
00428 return retval;
00429 }
00430
00431 template <Uint32 bit_count>
00432 inline BitArray<bit_count> operator ^ (
00433 BitArray<bit_count> const &left_operand,
00434 BitArray<bit_count> const &right_operand)
00435 {
00436 BitArray<bit_count> retval(left_operand);
00437 retval ^= right_operand;
00438 return retval;
00439 }
00440
00441 template <Uint32 bit_count>
00442 inline BitArray<bit_count> operator << (
00443 BitArray<bit_count> const &left_operand,
00444 Uint32 const right_operand)
00445 {
00446 BitArray<bit_count> retval(left_operand);
00447 retval <<= right_operand;
00448 return retval;
00449 }
00450
00451 template <Uint32 bit_count>
00452 inline BitArray<bit_count> operator >> (
00453 BitArray<bit_count> const &left_operand,
00454 Uint32 const right_operand)
00455 {
00456 BitArray<bit_count> retval(left_operand);
00457 retval >>= right_operand;
00458 return retval;
00459 }
00460
00461 }
00462
00463 #endif // !defined(_XRB_BITARRAY_HPP_)