spot/lbtt/src/BitArray.cc
Alexandre Duret-Lutz ababb9ff93 Initial revision
2002-10-01 14:21:01 +00:00

457 lines
15 KiB
C++

/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#ifdef HAVE_SSTREAM
#include <sstream>
#else
#include <strstream>
#endif /* HAVE_SSTREAM */
#include "BitArray.h"
#include "Exception.h"
/******************************************************************************
*
* `bit_counts[i]' tells the number of 1-bits in the 8-bit integer `i'.
*
*****************************************************************************/
const unsigned char BitArray::bit_counts[] =
{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2,
3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3,
3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3,
4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,
3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5,
6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4,
4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5,
6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,
3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3,
4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6,
6, 7, 6, 7, 7, 8};
/******************************************************************************
*
* Function definitions for class BitArray.
*
*****************************************************************************/
/* ========================================================================= */
BitArray::BitArray(const unsigned long int size)
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class BitArray. Creates a bit array of a
* given size.
*
* Argument: size -- Number of bits to allocate.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
unsigned long int bsize = (size + 7) >> 3;
bits = new unsigned char[bsize];
}
/* ========================================================================= */
BitArray::~BitArray()
/* ----------------------------------------------------------------------------
*
* Description: Destructor for class BitArray. Deallocates the memory used by
* the bit array.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
delete[] bits;
}
/* ========================================================================= */
void BitArray::copy
(const BitArray& bitarray, const unsigned long int bit_count)
/* ----------------------------------------------------------------------------
*
* Description: Copy the first `bit_count' bits from `bitarray' to `this'
* BitArray object. (As a side effect, the capacity of `this'
* bit array is set to `bit_count'.)
*
* Argument: bitarray -- Reference to a constant bit array which should
* be copied.
* bit_count -- Number of bits to copy.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
if (this != &bitarray)
{
delete[] bits;
unsigned long int bsize = (bit_count + 7) >> 3;
bits = new unsigned char[bsize];
memcpy(static_cast<void*>(bits), static_cast<const void*>(bitarray.bits),
bsize);
}
}
/* ========================================================================= */
bool BitArray::equal
(const BitArray& bitarray, const unsigned long int bit_count) const
/* ----------------------------------------------------------------------------
*
* Description: Test whether the first `bit_count' bits of `this' BitArray
* are equal to the correspoding bits of `bitarray'.
*
* Argument: bitarray -- Target of the comparison.
* bit_count -- Number of bits to compare.
*
* Returns: `true' if the compared bits agree and `false' otherwise.
*
* ------------------------------------------------------------------------- */
{
if (bit_count > 0)
{
unsigned long int bsize = bit_count >> 3;
for (unsigned long int i = 0; i < bsize; ++i)
{
if (bits[i] != bitarray.bits[i])
return false;
}
if ((bit_count & 0x07) == 0)
return true;
unsigned char mask = (1 << (bit_count & 0x07)) - 1;
if (((bits[bsize] ^ bitarray.bits[bsize]) & mask) != 0)
return false;
}
return true;
}
/* ========================================================================= */
BitArray& BitArray::bitwiseOr
(const BitArray& bitarray, const unsigned long int bit_count)
/* ----------------------------------------------------------------------------
*
* Description: Compute the bitwise disjunction of the first `bit_count' bits
* of two BitArrays (storing the result in `this' BitArray).
*
* Arguments: bitarray -- A reference to a constant BitArray.
* bit_count -- Number of bits to include in the computation.
*
* Returns: A reference to `this' BitArray.
*
* ------------------------------------------------------------------------- */
{
unsigned long int bsize = bit_count >> 3;
for (unsigned long int i = 0; i < bsize; ++i)
bits[i] |= bitarray.bits[i];
if ((bit_count & 0x07) != 0)
bits[bsize] |= (bitarray.bits[bsize] & ((1 << (bit_count & 7)) - 1));
return *this;
}
/* ========================================================================= */
BitArray& BitArray::bitwiseAnd
(const BitArray& bitarray, const unsigned long int bit_count)
/* ----------------------------------------------------------------------------
*
* Description: Compute the bitwise conjunction of the first `bit_count' bits
* of two BitArrays (storing the result in `this' BitArray).
*
* Arguments: bitarray -- A reference to a constant BitArray.
* bit_count -- Number of bits to include in the computation.
*
* Returns: A reference to `this' BitArray.
*
* ------------------------------------------------------------------------- */
{
unsigned long int bsize = bit_count >> 3;
for (unsigned long int i = 0; i < bsize; ++i)
bits[i] &= bitarray.bits[i];
if ((bit_count & 0x07) != 0)
bits[bsize] &= (bitarray.bits[bsize] | ~((1 << (bit_count & 7)) - 1));
return *this;
}
/* ========================================================================= */
BitArray& BitArray::bitwiseXor
(const BitArray& bitarray, const unsigned long int bit_count)
/* ----------------------------------------------------------------------------
*
* Description: Compute the bitwise "exclusive or" of the first `bit_count'
* bits of two BitArrays (storing the result in `this'
* BitArray).
*
* Arguments: bitarray -- A reference to a constant BitArray.
* bit_count -- Number of bits to include in the computation.
*
* Returns: A reference to `this' BitArray.
*
* ------------------------------------------------------------------------- */
{
unsigned long int bsize = bit_count >> 3;
for (unsigned long int i = 0; i < bsize; ++i)
bits[i] ^= bitarray.bits[i];
if ((bit_count & 0x07) != 0)
bits[bsize] ^= (bitarray.bits[bsize] & ((1 << (bit_count & 7)) - 1));
return *this;
}
/* ========================================================================= */
bool BitArray::subset
(const BitArray& bitarray, const unsigned long int bit_count) const
/* ----------------------------------------------------------------------------
*
* Description: Tests whether the first `bit_count' bits of `this' BitArray
* are set also in `bitarray'.
*
* Argument bitarray -- Target of the comparison.
* bit_count -- Number of bits to test.
*
* Returns: Truth value depending on the result of the test.
*
* ------------------------------------------------------------------------- */
{
if (bit_count > 0)
{
unsigned long int bsize = bit_count >> 3;
for (unsigned long int i = 0; i < bsize; ++i)
{
if ((bits[i] & ~bitarray.bits[i]) != 0)
return false;
}
if ((bit_count & 0x07) == 0)
return true;
unsigned char mask = (1 << (bit_count & 7)) - 1;
if (((bits[bsize] & ~bitarray.bits[bsize]) & mask) != 0)
return false;
}
return true;
}
/* ========================================================================= */
unsigned long int BitArray::count(const unsigned long int bit_count) const
/* ----------------------------------------------------------------------------
*
* Description: Counts the number of 1-bits in the first `bit_count' bits of
* the BitArray.
*
* Arguments: bit_count -- Number of bits to include in the computation.
*
* Returns: Number of 1-bits in the first `bit_count' bits of the
* BitArray.
*
* ------------------------------------------------------------------------- */
{
if (bit_count == 0)
return 0;
unsigned long int bsize = bit_count >> 3;
unsigned long int result = 0;
for (unsigned long int i = 0; i < bsize; ++i)
result += bit_counts[bits[i]];
if ((bit_count & 0x07) == 0)
return result;
unsigned char mask = (1 << (bit_count & 7)) - 1;
result += bit_counts[bits[bsize] & mask];
return result;
}
/* ========================================================================= */
unsigned long int BitArray::hammingDistance
(const BitArray& bitarray, const unsigned long int bit_count) const
/* ----------------------------------------------------------------------------
*
* Description: Computes the Hamming distance (the number of bit positions in
* which two bit vectors differ) between two bit vectors
* comprising the first `bit_count' bits of two bit arrays.
*
* Argument: bitarray -- A reference to a constant BitArray.
* bit_count -- Number of bits to include in the computation.
*
* Returns: The Hamming distance between the leftmost `bit_count' bits of
* two BitArrays.
*
* ------------------------------------------------------------------------- */
{
unsigned long int result = 0;
unsigned long int bsize = bit_count >> 3;
for (unsigned long int i = 0; i < bsize; ++i)
result += bit_counts[bits[i] ^ bitarray.bits[i]];
if ((bit_count & 0x07) == 0)
return result;
unsigned char mask = (1 << (bit_count & 7)) - 1;
result += bit_counts[(bits[bsize] ^ bitarray.bits[bsize]) & mask];
return result;
}
/* ========================================================================= */
void BitArray::flip(const unsigned long int bit_count)
/* ----------------------------------------------------------------------------
*
* Description: Changes the state of the first `bit_count' bits in the
* bit array.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
unsigned long bsize = (bit_count + 7) >> 3;
for (unsigned long int i = 0; i < bsize; ++i)
bits[i] ^= 0xFF;
}
/* ========================================================================= */
unsigned long int BitArray::find(const unsigned long int max_count) const
/* ----------------------------------------------------------------------------
*
* Description: Finds the first 1-bit in the bit array with an index less
* than `max_count'.
*
* Arguments: max_count -- Upper bound for the bit index.
*
* Returns: Index of the first 1-bit with an index less than `max_count'
* or `max_count' if there are no 1-bits with such an index in
* the array.
*
* ------------------------------------------------------------------------- */
{
unsigned long int bsize = (max_count + 7) >> 3;
unsigned long int i;
for (i = 0; i < bsize && bits[i] == 0; ++i)
;
if (i == max_count)
return max_count;
unsigned char c = bits[i];
i <<= 3;
while ((c & 0x01) == 0 && i < max_count)
{
c >>= 1;
++i;
}
return i;
}
/* ========================================================================= */
string BitArray::toString(const unsigned long int bit_count) const
/* ----------------------------------------------------------------------------
*
* Description: Converts the first `bit_count' bits of the bit array to a
* string (a sequence of characters `0' and `1'). The leftmost
* bit in the string corresponds to the first bit in the array.
*
* Arguments: bit_count -- Number of bits to convert into a string.
*
* Returns: String representation of the first `bit_count' bits of the
* bit array.
*
* ------------------------------------------------------------------------- */
{
#ifdef HAVE_SSTREAM
ostringstream bitstring;
print(bit_count, bitstring);
return bitstring.str();
#else
ostrstream bitstring;
print(bit_count, bitstring);
bitstring << ends;
string result(bitstring.str());
bitstring.freeze(0);
return result;
#endif /* HAVE_SSTREAM */
}
/* ========================================================================= */
void BitArray::print(const unsigned long int bit_count, ostream& stream) const
/* ----------------------------------------------------------------------------
*
* Description: Prints the first `bit_count' bits of the bit array as a
* sequence of characters `0' and `1'. The bits are printed in
* the same order as they are in the array; thus, the first
* printed bit corresponds to the bit with the lowest index in
* the array.
*
* Arguments: bit_count -- Number of bits to print.
* stream -- A reference to the output stream.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
unsigned long int i, j, bsize = (bit_count + 7) >> 3;
unsigned short int maskbit;
Exceptional_ostream estream(&stream, ios::failbit | ios::badbit);
j = 0;
for (i = 0; i < bsize; ++i)
{
maskbit = 1;
while (j < bit_count && maskbit <= 0x80)
{
estream << ((bits[i] & maskbit) ? '1' : '0');
++j;
maskbit <<= 1;
}
}
}