// Filename: bitArray.cxx
// Created by:  drose (20Jan06)
//
////////////////////////////////////////////////////////////////////
//
// 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."
//
////////////////////////////////////////////////////////////////////

#include "bitArray.h"
#include "sparseArray.h"

TypeHandle BitArray::_type_handle;

////////////////////////////////////////////////////////////////////
//     Function: BitArray::Constructor (from SparseArray)
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
BitArray::
BitArray(const SparseArray &from) {
  _highest_bits = 0;

  int num_subranges = from.get_num_subranges();
  for (int i = 0; i < num_subranges; ++i) {
    int begin = from.get_subrange_begin(i);
    int end = from.get_subrange_end(i);
    set_range(begin, end - begin);
  }

  if (from.is_inverse()) {
    invert_in_place();
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::is_zero
//       Access: Published
//  Description: Returns true if the entire bitmask is zero, false
//               otherwise.
////////////////////////////////////////////////////////////////////
bool BitArray::
is_zero() const {
  if (_highest_bits) {
    // If all the infinite highest bits are set, certainly the bitmask
    // is nonzero.
    return false;
  }

  // Start from the high end, since that's more likely to be nonzero.
  Array::reverse_iterator ai;
  for (ai = _array.rbegin(); ai != _array.rend(); ++ai) {
    if (!(*ai).is_zero()) {
      return false;
    }
  }
  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::is_all_on
//       Access: Published
//  Description: Returns true if the entire bitmask is one, false
//               otherwise.
////////////////////////////////////////////////////////////////////
bool BitArray::
is_all_on() const {
  if (!_highest_bits) {
    // If all the infinite highest bits are not set, certainly the
    // bitmask is not all on.
    return false;
  }

  Array::reverse_iterator ai;
  for (ai = _array.rbegin(); ai != _array.rend(); ++ai) {
    if (!(*ai).is_all_on()) {
      return false;
    }
  }
  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::has_any_of
//       Access: Published
//  Description: Returns true if any bit in the indicated range is
//               set, false otherwise.
////////////////////////////////////////////////////////////////////
bool BitArray::
has_any_of(int low_bit, int size) const {
  if ((low_bit + size - 1) / num_bits_per_word >= get_num_words()) {
    // This range touches the highest bits.
    if (_highest_bits) {
      return true;
    }
  }

  int w = low_bit / num_bits_per_word;
  int b = low_bit % num_bits_per_word;

  if (w >= get_num_words()) {
    // This range is entirely among the highest bits.
    return (_highest_bits != 0);
  }
  if (b + size <= num_bits_per_word) {
    // The whole thing fits within one word of the array.
    return get_word(w).has_any_of(b, size);
  }

  int num_high_bits = num_bits_per_word - b;
  if (_array[w].has_any_of(b, num_high_bits)) {
    return true;
  }
  size -= num_high_bits;
  ++w;

  while (size > 0) {
    if (size <= num_bits_per_word) {
      // The remainder fits within one word of the array.
      return _array[w].has_any_of(0, size);
    }

    // Keep going.
    if (!_array[w].is_zero()) {
      return true;
    }
    size -= num_bits_per_word;
    ++w;

    if (w >= get_num_words()) {
      // Now we're up to the highest bits.
      return (_highest_bits != 0);
    }
  }

  return false;
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::has_all_of
//       Access: Published
//  Description: Returns true if all bits in the indicated range are
//               set, false otherwise.
////////////////////////////////////////////////////////////////////
bool BitArray::
has_all_of(int low_bit, int size) const {
  if ((low_bit + size - 1) / num_bits_per_word >= get_num_words()) {
    // This range touches the highest bits.
    if (!_highest_bits) {
      return false;
    }
  }

  int w = low_bit / num_bits_per_word;
  int b = low_bit % num_bits_per_word;

  if (w >= get_num_words()) {
    // This range is entirely among the highest bits.
    return (_highest_bits != 0);
  }
  if (b + size <= num_bits_per_word) {
    // The whole thing fits within one word of the array.
    return get_word(w).has_all_of(b, size);
  }

  int num_high_bits = num_bits_per_word - b;
  if (!_array[w].has_all_of(b, num_high_bits)) {
    return false;
  }
  size -= num_high_bits;
  ++w;

  while (size > 0) {
    if (size <= num_bits_per_word) {
      // The remainder fits within one word of the array.
      return _array[w].has_all_of(0, size);
    }

    // Keep going.
    if (!_array[w].is_all_on()) {
      return false;
    }
    size -= num_bits_per_word;
    ++w;

    if (w >= get_num_words()) {
      // Now we're up to the highest bits.
      return (_highest_bits != 0);
    }
  }

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::set_range
//       Access: Published
//  Description: Sets the indicated range of bits on.
////////////////////////////////////////////////////////////////////
void BitArray::
set_range(int low_bit, int size) {
  int w = low_bit / num_bits_per_word;
  int b = low_bit % num_bits_per_word;

  if (w >= get_num_words() && _highest_bits) {
    // All the highest bits are already on.
    return;
  }
  if (b + size <= num_bits_per_word) {
    // The whole thing fits within one word of the array.
    ensure_has_word(w);
    _array[w].set_range(b, size);
    normalize();
    return;
  }

  ensure_has_word(w);
  int num_high_bits = num_bits_per_word - b;
  _array[w].set_range(b, num_high_bits);
  size -= num_high_bits;
  ++w;

  while (size > 0) {
    if (size <= num_bits_per_word) {
      // The remainder fits within one word of the array.
      ensure_has_word(w);
      _array[w].set_range(0, size);
      normalize();
      return;
    }

    // Keep going.
    ensure_has_word(w);
    _array[w] = MaskType::all_on();
    size -= num_bits_per_word;
    ++w;

    if (w >= get_num_words() && _highest_bits) {
      // All the highest bits are already on.
      normalize();
      return;
    }
  }
  normalize();
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::clear_range
//       Access: Published
//  Description: Sets the indicated range of bits off.
////////////////////////////////////////////////////////////////////
void BitArray::
clear_range(int low_bit, int size) {
  int w = low_bit / num_bits_per_word;
  int b = low_bit % num_bits_per_word;

  if (w >= get_num_words() && !_highest_bits) {
    // All the highest bits are already off.
    return;
  }
  if (b + size <= num_bits_per_word) {
    // The whole thing fits within one word of the array.
    ensure_has_word(w);
    _array[w].clear_range(b, size);
    normalize();
    return;
  }

  ensure_has_word(w);
  int num_high_bits = num_bits_per_word - b;
  _array[w].clear_range(b, num_high_bits);
  size -= num_high_bits;
  ++w;

  while (size > 0) {
    if (size <= num_bits_per_word) {
      // The remainder fits within one word of the array.
      ensure_has_word(w);
      _array[w].clear_range(0, size);
      normalize();
      return;
    }

    // Keep going.
    ensure_has_word(w);
    _array[w] = MaskType::all_off();
    size -= num_bits_per_word;
    ++w;

    if (w >= get_num_words() && !_highest_bits) {
      // All the highest bits are already off.
      normalize();
      return;
    }
  }
  normalize();
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::get_num_on_bits
//       Access: Published
//  Description: Returns the number of bits that are set to 1 in the
//               array.  Returns -1 if there are an infinite number of
//               1 bits.
////////////////////////////////////////////////////////////////////
int BitArray::
get_num_on_bits() const {
  if (_highest_bits) {
    return -1;
  }

  int result = 0;
  Array::const_iterator ai;
  for (ai = _array.begin(); ai != _array.end(); ++ai) {
    result += (*ai).get_num_on_bits();
  }
  return result;
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::get_num_off_bits
//       Access: Published
//  Description: Returns the number of bits that are set to 0 in the
//               array.  Returns -1 if there are an infinite number of
//               0 bits.
////////////////////////////////////////////////////////////////////
int BitArray::
get_num_off_bits() const {
  if (!_highest_bits) {
    return -1;
  }

  int result = 0;
  Array::const_iterator ai;
  for (ai = _array.begin(); ai != _array.end(); ++ai) {
    result += (*ai).get_num_off_bits();
  }
  return result;
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::get_lowest_on_bit
//       Access: Published
//  Description: Returns the index of the lowest 1 bit in the array.
//               Returns -1 if there are no 1 bits.
////////////////////////////////////////////////////////////////////
int BitArray::
get_lowest_on_bit() const {
  int num_words = get_num_words();
  for (int w = 0; w < num_words; ++w) {
    int b = _array[w].get_lowest_on_bit();
    if (b != -1) {
      return w * num_bits_per_word + b;
    }
  }
  if (_highest_bits) {
    return num_words * num_bits_per_word;
  } else {
    return -1;
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::get_lowest_off_bit
//       Access: Published
//  Description: Returns the index of the lowest 0 bit in the array.
//               Returns -1 if there are no 0 bits.
////////////////////////////////////////////////////////////////////
int BitArray::
get_lowest_off_bit() const {
  int num_words = get_num_words();
  for (int w = 0; w < num_words; ++w) {
    int b = _array[w].get_lowest_off_bit();
    if (b != -1) {
      return w * num_bits_per_word + b;
    }
  }
  if (!_highest_bits) {
    return num_words * num_bits_per_word;
  } else {
    return -1;
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::get_highest_on_bit
//       Access: Published
//  Description: Returns the index of the highest 1 bit in the array.
//               Returns -1 if there are no 1 bits or if there an
//               infinite number of 1 bits.
////////////////////////////////////////////////////////////////////
int BitArray::
get_highest_on_bit() const {
  if (_highest_bits) {
    return -1;
  }
  int num_words = get_num_words();
  for (int w = num_words - 1; w >= 0; --w) {
    int b = _array[w].get_highest_on_bit();
    if (b != -1) {
      return w * num_bits_per_word + b;
    }
  }
  return -1;
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::get_highest_off_bit
//       Access: Published
//  Description: Returns the index of the highest 0 bit in the array.
//               Returns -1 if there are no 0 bits or if there an
//               infinite number of 1 bits.
////////////////////////////////////////////////////////////////////
int BitArray::
get_highest_off_bit() const {
  if (!_highest_bits) {
    return -1;
  }
  int num_words = get_num_words();
  for (int w = num_words - 1; w >= 0; --w) {
    int b = _array[w].get_highest_off_bit();
    if (b != -1) {
      return w * num_bits_per_word + b;
    }
  }
  return -1;
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::get_next_higher_different_bit
//       Access: Published
//  Description: Returns the index of the next bit in the array, above
//               low_bit, whose value is different that the value of
//               low_bit.  Returns low_bit again if all bits higher
//               than low_bit have the same value.
//
//               This can be used to quickly iterate through all of
//               the bits in the array.
////////////////////////////////////////////////////////////////////
int BitArray::
get_next_higher_different_bit(int low_bit) const {
  int w = low_bit / num_bits_per_word;
  int b = low_bit % num_bits_per_word;
  int num_words = get_num_words();
  if (w >= num_words) {
    return low_bit;
  }
  int b2 = _array[w].get_next_higher_different_bit(b);
  if (b2 != b && b2 < num_bits_per_word) {
    // The next higher bit is within the same word.
    return w * num_bits_per_word + b2;
  }
  // Look for the next word with anything interesting.
  MaskType skip_next = (_array[w].get_bit(b)) ? MaskType::all_on() : MaskType::all_off();
  int w2 = w;
  ++w2;
  while (w2 < num_words && _array[w2] == skip_next) {
    ++w2;
  }
  if (w2 >= num_words) {
    // All bits higher are the same value.
    int is_on = _array[w].get_bit(b);
    return is_on ? (num_words * num_bits_per_word) : low_bit;
  }
  if (_array[w2].get_bit(0) != _array[w].get_bit(b)) {
    // The first bit of word w2 is different.
    return w2 * num_bits_per_word;
  }
  
  b2 = _array[w2].get_next_higher_different_bit(0);
  return w2 * num_bits_per_word + b2;
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::invert_in_place
//       Access: Published
//  Description: Inverts all the bits in the BitArray.  This is
//               equivalent to array = ~array.
////////////////////////////////////////////////////////////////////
void BitArray::
invert_in_place() {
  _highest_bits = !_highest_bits;
  copy_on_write();
  Array::iterator ai;
  for (ai = _array.begin(); ai != _array.end(); ++ai) {
    (*ai) = ~(*ai);
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::has_bits_in_common
//       Access: Published
//  Description: Returns true if this BitArray has any "one" bits in
//               common with the other one, false otherwise.
//
//               This is equivalent to (array & other) != 0, but may
//               be faster.
////////////////////////////////////////////////////////////////////
bool BitArray::
has_bits_in_common(const BitArray &other) const {
  if (_highest_bits && other._highest_bits) {
    // Yup, in fact we have an infinite number of bits in common.
    return true;
  }

  size_t num_common_words = min(_array.size(), other._array.size());

  // Consider the words that are on top of either array.
  if (other._array.size() < _array.size() && other._highest_bits) {
    // The other array has fewer actual words, and the top n words of
    // the other array are all ones.  We have bits in common if any of
    // our top n words are nonzero.
    Array::const_iterator ai;
    for (ai = _array.begin() + other._array.size();
         ai != _array.end();
         ++ai) {
      if (!(*ai).is_zero()) {
        return true;
      }
    }
    
  } else if (_array.size() < other._array.size() && _highest_bits) {
    // This array has fewer actual words, and the top n words of this
    // array are all ones.  We have bits in common if any of the the
    // other's top n words are nonzero.
    Array::const_iterator ai;
    for (ai = other._array.begin() + _array.size();
         ai != other._array.end();
         ++ai) {
      if (!(*ai).is_zero()) {
        return true;
      }
    }
  }

  // Consider the words that both arrays have in common.
  for (size_t i = 0; i < num_common_words; ++i) {
    if (!(_array[i] & other._array[i]).is_zero()) {
      return true;
    }
  }

  // Nope, nothing.
  return false;
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::output
//       Access: Published
//  Description: Writes the BitArray out as a hex number.  For a
//               BitArray, this is always the same as output_hex();
//               it's too confusing for the output format to change
//               back and forth at runtime.
////////////////////////////////////////////////////////////////////
void BitArray::
output(ostream &out) const {
  output_hex(out);
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::output_binary
//       Access: Published
//  Description: Writes the BitArray out as a binary number, with
//               spaces every four bits.
////////////////////////////////////////////////////////////////////
void BitArray::
output_binary(ostream &out, int spaces_every) const {
  if (_highest_bits) {
    out << "...1 ";
  }
  int num_bits = max(get_num_bits(), spaces_every);
  for (int i = num_bits - 1; i >= 0; i--) {
    if (spaces_every != 0 && ((i % spaces_every) == spaces_every - 1)) {
      out << ' ';
    }
    out << (get_bit(i) ? '1' : '0');
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::output_hex
//       Access: Published
//  Description: Writes the BitArray out as a hexadecimal number, with
//               spaces every four digits.
////////////////////////////////////////////////////////////////////
void BitArray::
output_hex(ostream &out, int spaces_every) const {
  int num_bits = get_num_bits();
  int num_digits = max((num_bits + 3) / 4, spaces_every);

  if (_highest_bits) {
    out << "...f ";
  }

  for (int i = num_digits - 1; i >= 0; i--) {
    WordType digit = extract(i * 4, 4);
    if (spaces_every != 0 && ((i % spaces_every) == spaces_every - 1)) {
      out << ' ';
    }
    if (digit > 9) {
      out << (char)(digit - 10 + 'a');
    } else {
      out << (char)(digit + '0');
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::write
//       Access: Published
//  Description: Writes the BitArray out as a binary or a hex number,
//               according to the number of bits.
////////////////////////////////////////////////////////////////////
void BitArray::
write(ostream &out, int indent_level) const {
  indent(out, indent_level) << *this << "\n";
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::compare_to
//       Access: Published
//  Description: Returns a number less than zero if this BitArray sorts
//               before the indicated other BitArray, greater than zero
//               if it sorts after, or 0 if they are equivalent.  This
//               is based on the same ordering defined by operator <.
////////////////////////////////////////////////////////////////////
int BitArray::
compare_to(const BitArray &other) const {
  if (_highest_bits != other._highest_bits) {
    return _highest_bits ? 1 : -1;
  }

  int num_words = max(get_num_words(), other.get_num_words());

  // Compare from highest-order to lowest-order word.
  for (int i = num_words - 1; i >= 0; --i) {
    int compare = get_word(i).compare_to(other.get_word(i));
    if (compare != 0) {
      return compare;
    }
  }

  return 0;
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::operator &=
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BitArray::
operator &= (const BitArray &other) {
  size_t num_common_words = min(_array.size(), other._array.size());

  copy_on_write();

  // Consider the words that are on top of either array.
  if (other._array.size() < _array.size() && !other._highest_bits) {
    // The other array has fewer actual words, and the top n words of
    // the other array are all zeroes.  "mask off" the top n words of
    // this array.
    _array.erase(_array.begin() + other._array.size(), _array.end());

  } else if (_array.size() < other._array.size() && _highest_bits) {
    // This array has fewer actual words, and the top n words of this
    // array are all ones.  "mask on" the top n words of the other
    // array.
    Array::const_iterator ai;
    for (ai = other._array.begin() + _array.size();
         ai != other._array.end();
         ++ai) {
      _array.push_back(*ai);
    }
  }

  // Consider the words that both arrays have in common.
  for (size_t i = 0; i < num_common_words; ++i) {
    _array[i] &= other._array[i];
  }

  _highest_bits &= other._highest_bits;
  normalize();
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::operator |=
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BitArray::
operator |= (const BitArray &other) {
  size_t num_common_words = min(_array.size(), other._array.size());

  copy_on_write();

  // Consider the words that are on top of either array.
  if (other._array.size() < _array.size() && other._highest_bits) {
    // The other array has fewer actual words, and the top n words of
    // the other array are all ones.  The top n words of this array
    // become ones too (which means we can drop them out).
    _array.erase(_array.begin() + other._array.size(), _array.end());

  } else if (_array.size() < other._array.size() && !_highest_bits) {
    // This array has fewer actual words, and the top n words of this
    // array are all zeros.  Copy in the top n words of the other
    // array.
    Array::const_iterator ai;
    for (ai = other._array.begin() + _array.size();
         ai != other._array.end();
         ++ai) {
      _array.push_back(*ai);
    }
  }

  // Consider the words that both arrays have in common.
  for (size_t i = 0; i < num_common_words; ++i) {
    _array[i] |= other._array[i];
  }

  _highest_bits |= other._highest_bits;
  normalize();
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::operator ^=
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BitArray::
operator ^= (const BitArray &other) {
  size_t num_common_words = min(_array.size(), other._array.size());

  copy_on_write();

  // Consider the words that are on top of either array.
  if (other._array.size() < _array.size() && other._highest_bits) {
    // The other array has fewer actual words, and the top n words of
    // the other array are all ones.  The top n words of this array
    // get inverted.
    Array::iterator ai;
    for (ai = _array.begin() + other._array.size();
         ai != _array.end();
         ++ai) {
      (*ai).invert_in_place();
    }

  } else if (_array.size() < other._array.size()) {
    if (!_highest_bits) {
      // This array has fewer actual words, and the top n words of this
      // array are all zeros.  Copy in the top n words of the other
      // array.
      Array::const_iterator ai;
      for (ai = other._array.begin() + _array.size();
           ai != other._array.end();
           ++ai) {
        _array.push_back(*ai);
      }
    } else {
      // This array has fewer actual words, and the top n words of this
      // array are all ones.  Copy in the top n words of the other
      // array, inverted.
      Array::const_iterator ai;
      for (ai = other._array.begin() + _array.size();
           ai != other._array.end();
           ++ai) {
        _array.push_back(~(*ai));
      }
    }
  }

  // Consider the words that both arrays have in common.
  for (size_t i = 0; i < num_common_words; ++i) {
    _array[i] ^= other._array[i];
  }

  _highest_bits ^= other._highest_bits;
  normalize();
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::operator <<=
//       Access: Published
//  Description: Logical left shift.  The rightmost bits are filled in
//               with zeroes.  Since this is an infinite bit array,
//               none of the bits on the left are lost.
////////////////////////////////////////////////////////////////////
void BitArray::
operator <<= (int shift) {
  if (shift == 0 || _array.empty()) {
    return;
  }
  if (shift < 0) {
    operator >>= (-shift);
    return;
  }

  int w = shift / num_bits_per_word;
  int b = shift % num_bits_per_word;

  if (b == 0) {
    // Easy case--word-at-a-time.
    Array new_array;
    new_array.reserve(_array.size() + w);
    for (int i = 0; i < w; ++i) {
      new_array.push_back(MaskType::all_off());
    }
    Array::const_iterator ai;
    for (ai = _array.begin(); ai != _array.end(); ++ai) {
      new_array.push_back(*ai);
    }
    _array = new_array;

  } else {
    // Harder case--we have to shuffle bits between words.
    Array new_array;
    new_array.reserve(_array.size() + w + 1);
    for (int i = 0; i < w; ++i) {
      new_array.push_back(MaskType::all_off());
    }

    int downshift_count = num_bits_per_word - b;
    MaskType lower_mask = MaskType::lower_on(downshift_count);
    MaskType upper_mask = ~lower_mask;

    Array::const_iterator ai = _array.begin();
    nassertv(ai != _array.end());
    MaskType next_bits = ((*ai) & upper_mask) >> downshift_count;
    new_array.push_back(((*ai) & lower_mask) << b);
    ++ai;
    while (ai != _array.end()) {
      new_array.push_back((((*ai) & lower_mask) << b) | next_bits);
      next_bits = ((*ai) & upper_mask) >> downshift_count;
      ++ai;
    }

    // Finally, the top n bits.
    if (_highest_bits) {
      next_bits |= ~MaskType::lower_on(b);
    }
    new_array.push_back(next_bits);
    _array = new_array;
  }

  normalize();
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::operator >>=
//       Access: Published
//  Description: Logical right shift.  The rightmost bits are lost.
//               Since this is an infinite bit array, there is no
//               question of sign extension; there is no need to
//               synthesize bits on the left.
////////////////////////////////////////////////////////////////////
void BitArray::
operator >>= (int shift) {
  if (shift == 0 || _array.empty()) {
    return;
  }
  if (shift < 0) {
    operator <<= (-shift);
    return;
  }

  int w = shift / num_bits_per_word;
  int b = shift % num_bits_per_word;

  if (w >= (int)_array.size()) {
    // Trivial case--shift to nothing.
    _array.clear();
    return;
  }

  if (b == 0) {
    // Easy case--word-at-a-time.
    Array new_array;
    new_array.reserve(_array.size() - w);
    Array::const_iterator ai;
    for (ai = _array.begin() + w; ai != _array.end(); ++ai) {
      new_array.push_back(*ai);
    }
    _array = new_array;

  } else {
    // Harder case--we have to shuffle bits between words.
    Array new_array;
    new_array.reserve(_array.size() - w);

    int upshift_count = num_bits_per_word - b;
    MaskType lower_mask = MaskType::lower_on(b);
    MaskType upper_mask = ~lower_mask;

    Array::const_iterator ai = _array.begin() + w;
    nassertv(ai < _array.end());
    MaskType next_bits = ((*ai) & upper_mask) >> b;
    
    ++ai;
    while (ai != _array.end()) {
      new_array.push_back((((*ai) & lower_mask) << upshift_count) | next_bits);
      next_bits = ((*ai) & upper_mask) >> b;
      ++ai;
    }

    // Finally, the top n bits.
    if (_highest_bits) {
      next_bits |= ~MaskType::lower_on(upshift_count);
    }
    new_array.push_back(next_bits);
    _array = new_array;
  }

  normalize();
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::generate_hash
//       Access: Public
//  Description: Adds the bitmask to the indicated hash generator.
////////////////////////////////////////////////////////////////////
void BitArray::
generate_hash(ChecksumHashGenerator &hashgen) const {
  hashgen.add_int(_highest_bits);
  Array::const_iterator ai;
  for (ai = _array.begin(); ai != _array.end(); ++ai) {
    hashgen.add_int((*ai).get_word());
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::ensure_has_word
//       Access: Private
//  Description: Ensures that at least word n has been allocated into
//               the array.
////////////////////////////////////////////////////////////////////
void BitArray::
ensure_has_word(int n) {
  copy_on_write();

  if (_highest_bits) {
    while (n >= (int)_array.size()) {
      _array.push_back(MaskType::all_on());
    }
  } else {
    while (n >= (int)_array.size()) {
      _array.push_back(MaskType::all_off());
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::normalize
//       Access: Private
//  Description: Ensures that the array is the smallest array that
//               represents this same value, by removing the topmost
//               words that are all bits off (or on).
////////////////////////////////////////////////////////////////////
void BitArray::
normalize() {
  if (_highest_bits) {
    if (!_array.empty() && _array.back() == MaskType::all_on()) {
      copy_on_write();
      _array.pop_back();
      while (!_array.empty() && _array.back() == MaskType::all_on()) {
        _array.pop_back();
      }
    }
  } else {
    if (!_array.empty() && _array.back().is_zero()) {
      copy_on_write();
      _array.pop_back();
      while (!_array.empty() && _array.back().is_zero()) {
        _array.pop_back();
      }
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::write_datagram
//       Access: Public
//  Description: Writes the contents of this object to the datagram
//               for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void BitArray::
write_datagram(BamWriter *manager, Datagram &dg) const {
  dg.add_uint32(_array.size());
  Array::const_iterator ai;
  for (ai = _array.begin(); ai != _array.end(); ++ai) {
    dg.add_uint32((*ai).get_word());
  }
  dg.add_uint8(_highest_bits);
}

////////////////////////////////////////////////////////////////////
//     Function: BitArray::read_datagram
//       Access: Public
//  Description: Reads the object that was previously written to a Bam
//               file.
////////////////////////////////////////////////////////////////////
void BitArray::
read_datagram(DatagramIterator &scan, BamReader *manager) {
  size_t num_words = scan.get_uint32();
  _array = Array::empty_array(num_words);
  for (size_t i = 0; i < num_words; ++i) {
    _array[i] = WordType(scan.get_uint32());
  }
  _highest_bits = scan.get_uint8();
}
