#include "stdafx.h"

#pragma hdrstop

using namespace std;

#include "myExcept.h"

#include "bitvector.h"


bitvector::bitvector(void)
{
	bitsize = 0;
}

bitvector::bitvector( const unsigned int _size )
{
	if ( _size == 0 ) throw RuntimeException( "bitvector:: Zero vector size" );
	bitsize = _size;
	data.resize(items(), 0);
}

void bitvector::resize( const unsigned int _size )
{
	if ( _size == 0 ) throw RuntimeException( "bitvector:: Zero vector size" );
	bitsize = _size;
	data.resize(items(), 0);
}

void bitvector::resize( const unsigned int _size, const bool val )
{
	if ( _size == 0 ) throw RuntimeException( "bitvector:: Zero vector size" );
	bitsize = _size;
	data.resize(items(), val);
}

bitvector::~bitvector(void)
{
}

position bitvector::GetPosition( const unsigned int pos ) const
{
	position p;

	p.index = pos/WORDLENGTH;
	p.bit = pos % WORDLENGTH;
	return p;
}

void bitvector::push_back( const bool bit )
{
	position p;

	p = GetPosition( bitsize );
	if ( p.bit == 0 ) data.resize(data.size()+1, 0);
	bitsize++;
	if ( bit ) data[p.index] |= (1 << p.bit);
}

bool bitvector::operator[] ( const unsigned int pos ) const
{
	position p;

	if ( pos > bitsize-1 ) throw RuntimeException( "bitvector:: Referencing uninitialized item" );
	p = GetPosition(pos);
	return( (data[p.index] & (1 << p.bit)) != 0 );
}

/*
bool bitvector::operator= ( bitvector &_vector )
{
	this->data = _vector.data();
	this->bitsize = _vector.bitsize();
}
*/

bool bitvector::operator== ( const bitvector &_vector ) const
{
	unsigned int i;
	position p;
	DATATYPE mask;

	if ( this->bitsize != _vector.bitsize ) return false;
	else {
		for ( i = 0; i < this->items()-1; i++ )
			if ( this->data[i] != _vector.data[i] ) return false;
		p = GetPosition(bitsize-1);
		mask = ~((~0) << (p.bit+1));
		if ( (this->data[i] & mask) != (_vector.data[i] & mask) ) return false;
	}
	return true;
}

void bitvector::clear(void)
{
	data.clear();
	bitsize = 0;
}

void bitvector::setbit( const unsigned int pos, const bool val )
{
	position p;

	if ( pos > bitsize-1 ) throw RuntimeException( "bitvector:: Referencing uninitialized item" );
	p = GetPosition( pos );
	if ( !val ) data[p.index] &= ~(1 << p.bit);
	else data[p.index] |= (1 << p.bit);
}

bitvector bitvector::operator& ( const bitvector &_vector ) const
{
	bitvector vector;
	unsigned int i;

	if ( this->size() != _vector.size() ) throw RuntimeException( "bitvector:: & operator between vectors of different sizes" );
	vector.resize(this->size());
	for ( i = 0; i < this->items(); i++ ) vector.data[i] = this->data[i] & _vector.data[i];
	return vector;
}

bitvector bitvector::operator| ( const bitvector &_vector ) const
{
	bitvector vector;
	unsigned int i;

	if ( this->size() != _vector.size() ) throw RuntimeException( "bitvector:: & operator between vectors of different sizes" );
	vector.resize(this->size());
	for ( i = 0; i < this->items(); i++ ) vector.data[i] = this->data[i] | _vector.data[i];
	return vector;
}

bitvector bitvector::operator^ ( const bitvector &_vector ) const
{
	bitvector vector;
	unsigned int i;

	if ( this->size() != _vector.size() ) throw RuntimeException( "bitvector:: & operator between vectors of different sizes" );
	vector.resize(this->size());
	for ( i = 0; i < this->items(); i++ ) vector.data[i] = this->data[i] ^ _vector.data[i];
	return vector;
}

bitvector bitvector::operator~(void) const
{
	bitvector vector;
	unsigned int i;

	vector.resize(this->size());
	for ( i = 0; i < this->items(); i++ ) vector.data[i] = ~this->data[i];
	return vector;
}

bool bitvector::contains( const bitvector &_vector ) const
// returns true, if this contains _vector
// i.e., _vector does not have a true value, where this has
{
	unsigned int i;
	position p;
	DATATYPE mask;

	if ( this->size() != _vector.size() ) throw RuntimeException( "bitvector:: & operator between vectors of different sizes" );
	for ( i = 0; i < this->items()-1; i++ )
		if ( (this->data[i] | _vector.data[i]) != this->data[i] ) return false;
	p = GetPosition(bitsize-1);
	mask = ~((~0) << (p.bit+1));
	if ( ((this->data[i] & mask) | _vector.data[i]) != (this->data[i] & mask) ) return false;
	return true;
}
