#ifndef bitvectorH
#define bitvectorH

#include <cstdlib>

#define DATATYPE unsigned				// size of a memory word - 32/64 bits
#define WORDLENGTH (sizeof(DATATYPE) * 8)
#define SHIFT ((sizeof(DATATYPE) == 8 ? 6 : 5) - 1)			// 64 = 2^6 or 32 = 2^5
#define MASK ((DATATYPE(WORDLENGTH - 1)) >> 1)								// for modulo
#define ALL_ONE ~(DATATYPE)0					// all-1 vector

struct position {
	unsigned int index;
	unsigned int bit;
};

enum Literal {
	ZERO = 0,
	ONE = 1,
	DC = 2,
	UNDEF = 3
};

#define ONEMASK (DATATYPE(0x5555555555555555ull))
#define DCMASK  (DATATYPE(0xAAAAAAAAAAAAAAAAull))


class bitvector
{
private:
	DATATYPE * data;
	unsigned int bitsize;		// size in bits

	inline void GetPosition( const unsigned int & pos, position & result ) const;

public:
	Literal operator[] ( const unsigned int pos ) const;
	bitvector & operator= ( const bitvector &_vector );
	bool operator== ( const bitvector &_vector ) const;
	bitvector operator& ( const bitvector &_vector ) const;		// AND
	void operator&= ( const bitvector &_vector );				// AND
	bitvector operator| ( const bitvector &_vector ) const;		// OR
	void operator|= ( const bitvector &_vector );				// AND
	bitvector operator^ ( const bitvector &_vector ) const;		// XOR
	void operator^= ( const bitvector &_vector );				// AND
	bitvector operator~ () const;								// bitwise NOT
	
	bitvector(const bitvector &_vector);
	bitvector(void);
	bitvector( const unsigned int _size );
	~bitvector(void);

	inline unsigned int size(void) const { return bitsize; }						// returns the size in bits
	inline unsigned int items(void) const { return bitsize ? ((bitsize-1) >> SHIFT)+1 : 0; }	// returns the size in datatype items
	void resize( const unsigned int _size );								// resizes the vector and fills new vector items with 0
	void resize( const unsigned int _size, const bool val );				// resizes the vector and assignes a value to new vector items
	void assign( const unsigned int _size, const Literal val );				// assignes a value to all vector items
	void push_back( const bool bit );
	void setbit( const unsigned int pos, const Literal val );
	void clear(void);
	bool empty(void) { return bitsize == 0; }
	bool contains( const bitvector &_vector ) const;		// returns true, if this contains _vector
	//bool contains2( const bitvector &_vector ) const;
	bool isNull(void) const;								// is the vector all-zero?
	bool isOne(void) const;									// is the vector all-one?
	DATATYPE GetWord( const unsigned int i ) const { return data[i]; }
	friend ostream& operator<<(ostream& o, const bitvector& bv);
};

#endif
