bitvect.cpp

/*  bitvect.cppa8
    Apr 19 2001
    Chris Lacher

    BitVector class implementation - array of unsigned char version

    01/13/07: style upgrade

    Copyright 2001 - 2007, R.C. Lacher
*/

#ifndef _BITVECT_CCP
#define _BITVECT_CCP

#include <iostream>
#include <stdlib.h>

#include <bitvect.h>

namespace fsu
{

  std::ostream& operator << (std::ostream& os, const BitVector& bv)
  // implementation by Spring 2004 Sec 51 and modified/simplified by Matt Porter
  {
    for (unsigned int i = 0; i < bv.Size(); ++i)
      os << bv.Test(i);
    return os;
  }

  //----------------------------------
  //     BitVector
  //----------------------------------

  // public methods

  BitVector::BitVector (unsigned int numbits) // constructor
  {
    byteArraySize_ = (numbits + 7)/8;
    byteArray_ = new unsigned char [byteArraySize_];
    if (byteArray_ == 0)
      {
        std::cerr << "** BitVector memory allocation failure -- terminating program.\n";
        exit (EXIT_FAILURE);
      }
    for (unsigned int i = 0; i < byteArraySize_; ++i)
      byteArray_[i] = 0x00;
  }

  BitVector::BitVector (const BitVector& bv)  // copy constructor      
  {
    byteArraySize_ = bv.byteArraySize_;
    byteArray_ = new unsigned char [byteArraySize_];
    if (byteArray_ == 0)
      {
        std::cerr << "** BitVector memory allocation failure -- terminating program.\n";
        exit (EXIT_FAILURE);
      }
    for (unsigned int i = 0; i < byteArraySize_; ++i)
      byteArray_[i] = bv.byteArray_[i];
  }

  BitVector::~BitVector ()  // destructor
  {
    delete [] byteArray_;
  }

  BitVector& BitVector::operator = (const BitVector& bv)  
  // assignment operator
  {
    if (this != &bv)
      {
        if (byteArraySize_ != bv.byteArraySize_)
          {
            delete [] byteArray_;
            byteArraySize_ = bv.byteArraySize_;
            byteArray_ = new unsigned char [byteArraySize_];
            if (byteArray_ == 0)
              {
                std::cerr << "** BitVector memory allocation failure -- terminating program.\n";
                exit (EXIT_FAILURE);
              }
          }
        for (unsigned int i = 0; i < byteArraySize_; ++i)
          byteArray_[i] = bv.byteArray_[i];
      }
    return *this;
  }

  unsigned int BitVector::Size() const      
  // return size of bitvector
  {
    return 8 * byteArraySize_;
  }

  void BitVector::Set ()  
  // make all bits = 1
  {
    for (unsigned int i = 0; i < byteArraySize_; ++i)
      byteArray_[i] = 0xFF;
  }

  void BitVector::Set (unsigned int index)  
  // make bit = 1: OR with mask
  {
    byteArray_[ByteNumber(index)] |= Mask(index);
  }

  void BitVector::Unset ()  
  // make all bits = 0
  {
    for (unsigned int i = 0; i < byteArraySize_; ++i)
      byteArray_[i] = 0x00;
  }

  void BitVector::Unset (unsigned int index)  
  // make bit = 0: AND with inverted mask
  {
    byteArray_[ByteNumber(index)] &= ~ Mask(index);
  }

  void BitVector::Flip ()  
  // change all bit values
  {
    for (unsigned int i = 0; i < byteArraySize_; ++i)
      byteArray_[i] ^= 0xFF;
  }

  void BitVector::Flip (unsigned int index)  
  // change bit value: XOR with mask
  {
    byteArray_[ByteNumber(index)] ^= Mask(index);
  }

  int BitVector::Test  (unsigned int index) const  
  // return bit value
  {
    return 0 != (byteArray_[ByteNumber(index)] & Mask(index));
  }
   
  // private methods

  size_t BitVector::ByteNumber (unsigned int index) const
  {
    // return index / 8
    // shift right 3 is equivalent to, and faster than, dividing by 8
    index = index >> 3;
    if (index >= byteArraySize_)
      {
        std::cerr << "** BitVector error: index out of range\n";
        exit (EXIT_FAILURE);
      } 
    return index;
  }

  unsigned char BitVector::Mask (unsigned int index)
  {
    // return mask for index % 8
    // the low order 3 bits is the remainder when dividing by 8
    unsigned int shiftamount = index & 0x07;  // low order 3 bits
    return 0x01 << shiftamount;
  }

} // namespace fsu

#endif