/*ident	"@(#)cls4:src/Bits.h	1.1" */
/*******************************************************************************
 
C++ source for the C++ Language System, Release 3.0.  This product
is a new release of the original cfront developed in the computer
science research center of AT&T Bell Laboratories.

Copyright (c) 1991 AT&T and UNIX System Laboratories, Inc.
Copyright (c) 1984, 1989, 1990 AT&T.  All Rights Reserved.

THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX System
Laboratories, Inc.  The copyright notice above does not evidence
any actual or intended publication of such source code.

*******************************************************************************/
#ifndef _BITS_H
#define _BITS_H

#include "Block.h"

typedef unsigned long Bits_chunk;
static const int Bits_shift_ATTLC = 5;
static const int Bits_len_ATTLC = 1 << Bits_shift_ATTLC;
static const int Bits_mask_ATTLC = Bits_len_ATTLC - 1;

Blockdeclare(Bits_chunk)

class Bits {
private:
	Block(Bits_chunk) b;
	unsigned n;

	// the chunk number that contains bit n
	unsigned chunk(unsigned n) const {
		return n >> Bits_shift_ATTLC;
	}

	// the number of chunks needed to contain an n-bit string
	unsigned bound(unsigned n) const {
		return (n + Bits_len_ATTLC - 1) >> Bits_shift_ATTLC;
	}

	// a pointer to the (non-existent) chunk immediately
	// after the last one in this Bits
	Bits_chunk* limit() {
		return (Bits_chunk*)b + bound(n);
	}
	const Bits_chunk* limit() const {
		return (const Bits_chunk*)b + bound(n);
	}

	// turn off unused high-order bits in the high-order chunk
	void normalize() {
		register int ct = n & Bits_mask_ATTLC;
		if (ct)
			b[chunk(n)] &= ~(~Bits_chunk(0) << ct);
	}

	int compare(const Bits&) const;
	int equal(const Bits&) const;

public:
	Bits() { n = 0; }
	Bits(Bits_chunk, unsigned = 1);
	unsigned size() const { return n; }
	unsigned size(unsigned);
	friend Bits operator& (const Bits&, const Bits&);
	friend Bits operator| (const Bits&, const Bits&);
	friend Bits operator^ (const Bits&, const Bits&);
	friend Bits operator~ (const Bits&);
	friend Bits operator<< (const Bits&, int);
	friend Bits operator>> (const Bits&, int);
	friend int operator< (const Bits&, const Bits&);
	friend int operator> (const Bits&, const Bits&);
	friend int operator<= (const Bits&, const Bits&);
	friend int operator>= (const Bits&, const Bits&);
	friend int operator== (const Bits&, const Bits&);
	friend int operator!= (const Bits&, const Bits&);
	Bits& operator&= (const Bits&);
	Bits& operator|= (const Bits&);
	Bits& operator^= (const Bits&);
	Bits& operator<<= (int);
	Bits& operator>>= (int);
	Bits& compl();
	Bits& concat(const Bits&);
	Bits& set(unsigned i) {
		if (i < n)
			b[chunk(i)] |= Bits_chunk(1) << (i&Bits_mask_ATTLC);
		return *this;
	}
	Bits& set(unsigned i, unsigned long x) {
		if (i < n) {
			register Bits_chunk* p = &b[chunk(i)];
			register Bits_chunk mask = Bits_chunk(1) << (i&Bits_mask_ATTLC);
			if (x)
				*p |= mask;
			else
				*p &= ~mask;
		}
		return *this;
	}
	Bits& reset(unsigned i) {
		if (i < n)
			b[chunk(i)] &= ~(Bits_chunk(1) << (i&Bits_mask_ATTLC));
		return *this;
	}
	Bits& compl(unsigned i) {
		if (i < n)
			b[chunk(i)] ^= Bits_chunk(1) << (i&Bits_mask_ATTLC);
		return *this;
	}
	unsigned count() const;
	operator Bits_chunk() const;
	int operator[] (unsigned i) const {
		if (i >= n)
			return 0;
		else
			return (b[chunk(i)] >> (i&Bits_mask_ATTLC)) & 1;
	}
	unsigned signif() const;
	unsigned trim() { return size(signif()); }
};

inline int
operator< (const Bits& a, const Bits& b)
{
	return a.compare(b) < 0;
}

inline int
operator> (const Bits& a, const Bits& b)
{
	return a.compare(b) > 0;
}

inline int
operator<= (const Bits& a, const Bits& b)
{
	return a.compare(b) <= 0;
}

inline int
operator>= (const Bits& a, const Bits& b)
{
	return a.compare(b) >= 0;
}

inline int
operator== (const Bits& a, const Bits& b)
{
	return a.equal(b);
}

inline int
operator!= (const Bits& a, const Bits& b)
{
	return !a.equal(b);
}

Bits concat(const Bits&, const Bits&);

#endif
