historical/toontown-classic.git/panda/include/bitArray.I
2024-01-16 11:20:27 -06:00

374 lines
7.8 KiB
Text

/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file bitArray.I
* @author drose
* @date 2006-01-20
*/
/**
*
*/
INLINE BitArray::
BitArray() {
_highest_bits = 0;
}
/**
*
*/
INLINE BitArray::
BitArray(WordType init_value) {
if (init_value != 0) {
_array.push_back(MaskType(init_value));
}
_highest_bits = 0;
}
/**
* Returns a BitArray with an infinite array of bits, all on.
*/
INLINE BitArray BitArray::
all_on() {
BitArray result;
result._highest_bits = 1;
return result;
}
/**
* Returns a BitArray whose bits are all off.
*/
INLINE BitArray BitArray::
all_off() {
return BitArray();
}
/**
* Returns a BitArray whose lower on_bits bits are on.
*/
INLINE BitArray BitArray::
lower_on(int on_bits) {
BitArray result;
result.set_range(0, on_bits);
return result;
}
/**
* Returns a BitArray with only the indicated bit on.
*/
INLINE BitArray BitArray::
bit(int index) {
BitArray result;
result.set_bit(index);
return result;
}
/**
* Returns a BitArray whose size bits, beginning at low_bit, are on.
*/
INLINE BitArray BitArray::
range(int low_bit, int size) {
BitArray result;
result.set_range(low_bit, size);
return result;
}
/**
* Returns the current number of possibly different bits in this array. There
* are actually an infinite number of bits, but every bit higher than this bit
* will have the same value, either 0 or 1 (see get_highest_bits()).
*
* This number may grow and/or shrink automatically as needed.
*/
INLINE size_t BitArray::
get_num_bits() const {
return get_num_words() * (size_t)num_bits_per_word;
}
/**
* Returns true if the nth bit is set, false if it is cleared. It is valid
* for n to increase beyond get_num_bits(), but the return value
* get_num_bits() will always be the same.
*/
INLINE bool BitArray::
get_bit(int index) const {
nassertr(index >= 0, false);
int w = index / num_bits_per_word;
int b = index % num_bits_per_word;
if ((size_t)w >= get_num_words()) {
return get_highest_bits();
} else {
return (_array[w].get_bit(b));
}
}
/**
* Sets the nth bit on. If n >= get_num_bits(), this automatically extends
* the array.
*/
INLINE void BitArray::
set_bit(int index) {
nassertv(index >= 0);
int w = index / num_bits_per_word;
int b = index % num_bits_per_word;
if ((size_t)w >= get_num_words() && _highest_bits) {
// All the highest bits are already on.
return;
}
ensure_has_word(w);
_array[w].set_bit(b);
normalize();
}
/**
* Sets the nth bit off. If n >= get_num_bits(), this automatically extends
* the array.
*/
INLINE void BitArray::
clear_bit(int index) {
nassertv(index >= 0);
int w = index / num_bits_per_word;
int b = index % num_bits_per_word;
if ((size_t)w >= get_num_words() && !_highest_bits) {
// All the highest bits are already off.
return;
}
ensure_has_word(w);
_array[w].clear_bit(b);
normalize();
}
/**
* Sets the nth bit either on or off, according to the indicated bool value.
*/
INLINE void BitArray::
set_bit_to(int index, bool value) {
if (value) {
set_bit(index);
} else {
clear_bit(index);
}
}
/**
* Returns true if the infinite set of bits beyond get_num_bits() are all on,
* or false of they are all off.
*/
INLINE bool BitArray::
get_highest_bits() const {
return (_highest_bits != 0);
}
/**
* Returns a word that represents only the indicated range of bits within this
* BitArray, shifted to the least-significant position. size must be <=
* get_num_bits_per_word().
*/
INLINE BitArray::WordType BitArray::
extract(int low_bit, int size) const {
nassertr(size >= 0 && size <= num_bits_per_word, 0);
int w = low_bit / num_bits_per_word;
int b = low_bit % num_bits_per_word;
if (b + size < num_bits_per_word) {
// The whole thing fits within one word of the array.
return get_word(w).extract(b, size);
} else {
// We have to split it across two words.
int num_lower_bits = num_bits_per_word - b;
int num_higher_bits = size - num_lower_bits;
return get_word(w).extract(b, num_lower_bits) |
(get_word(w + 1).extract(0, num_higher_bits) << num_lower_bits);
}
}
/**
* Stores the indicated word into the indicated range of bits with this
* BitArray.
*/
INLINE void BitArray::
store(WordType value, int low_bit, int size) {
nassertv(size >= 0);
int w = low_bit / num_bits_per_word;
int b = low_bit % num_bits_per_word;
if (b + size < num_bits_per_word) {
// The whole thing fits within one word of the array.
ensure_has_word(w);
_array[w].store(value, b, size);
} else {
// We have to split it across two words.
int num_lower_bits = num_bits_per_word - b;
int num_higher_bits = size - num_lower_bits;
ensure_has_word(w + 1);
_array[w].store(value, b, num_lower_bits);
_array[w + 1].store(value >> num_lower_bits, 0, num_higher_bits);
}
normalize();
}
/**
* Sets the indicated range of bits to either on or off.
*/
INLINE void BitArray::
set_range_to(bool value, int low_bit, int size) {
if (value) {
set_range(low_bit, size);
} else {
clear_range(low_bit, size);
}
}
/**
* Returns the number of possibly-unique words stored in the array.
*/
INLINE size_t BitArray::
get_num_words() const {
return _array.size();
}
/**
* Returns the nth word in the array. It is valid for n to be greater than
* get_num_words(), but the return value beyond get_num_words() will always be
* the same.
*/
INLINE BitArray::MaskType BitArray::
get_word(size_t n) const {
nassertr(n >= 0, MaskType::all_off());
if (n < get_num_words()) {
return _array[n];
}
if (_highest_bits) {
return MaskType::all_on();
} else {
return MaskType::all_off();
}
}
/**
* Replaces the nth word in the array. If n >= get_num_words(), this
* automatically extends the array.
*/
INLINE void BitArray::
set_word(size_t n, WordType value) {
ensure_has_word(n);
_array[n] = value;
normalize();
}
/**
* Sets all the bits in the BitArray off.
*/
void BitArray::
clear() {
_array.clear();
_highest_bits = 0;
}
/**
*
*/
INLINE bool BitArray::
operator == (const BitArray &other) const {
return compare_to(other) == 0;
}
/**
*
*/
INLINE bool BitArray::
operator != (const BitArray &other) const {
return compare_to(other) != 0;
}
/**
* Returns true if the unsigned integer which is represented by this BitArray
* is less than that of the other one, false otherwise.
*/
INLINE bool BitArray::
operator < (const BitArray &other) const {
return compare_to(other) < 0;
}
/**
*
*/
INLINE BitArray BitArray::
operator & (const BitArray &other) const {
BitArray result(*this);
result &= other;
return result;
}
/**
*
*/
INLINE BitArray BitArray::
operator | (const BitArray &other) const {
BitArray result(*this);
result |= other;
return result;
}
/**
*
*/
INLINE BitArray BitArray::
operator ^ (const BitArray &other) const {
BitArray result(*this);
result ^= other;
return result;
}
/**
*
*/
INLINE BitArray BitArray::
operator ~ () const {
BitArray result(*this);
result.invert_in_place();
return result;
}
/**
*
*/
INLINE BitArray BitArray::
operator << (int shift) const {
BitArray result(*this);
result <<= shift;
return result;
}
/**
*
*/
INLINE BitArray BitArray::
operator >> (int shift) const {
BitArray result(*this);
result >>= shift;
return result;
}
/**
* Called internally just before writing to the _array member, this makes a
* new copy of _array if it appears to be shared with any other objects--thus
* achieving copy-on-write.
*/
INLINE void BitArray::
copy_on_write() {
if (_array.get_ref_count() > 1) {
PTA(MaskType) new_array;
new_array.v() = _array.v();
_array = new_array;
}
}