home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1997 May
/
Pcwk0597.iso
/
borland
/
cb
/
setup
/
cbuilder
/
data.z
/
BITSET.H
< prev
next >
Wrap
C/C++ Source or Header
|
1997-02-28
|
18KB
|
629 lines
#ifndef __STD_BITS
#define __STD_BITS
/* $Revision: 8.1 $ */
/***************************************************************************
*
* bitset - class bitset declaration
*
* $Id: bitset,v 1.55 1995/09/29 23:52:59 smithey Exp $
*
***************************************************************************
*
* (c) Copyright 1994, 1995 Rogue Wave Software, Inc.
* ALL RIGHTS RESERVED
*
* The software and information contained herein are proprietary to, and
* comprise valuable trade secrets of, Rogue Wave Software, Inc., which
* intends to preserve as trade secrets such software and information.
* This software is furnished pursuant to a written license agreement and
* may be used, copied, transmitted, and stored only in accordance with
* the terms of such license and with the inclusion of the above copyright
* notice. This software and information or any other copies thereof may
* not be provided or otherwise made available to any other person.
*
* Notwithstanding any other lease or license that may pertain to, or
* accompany the delivery of, this computer software and information, the
* rights of the Government regarding its use, reproduction and disclosure
* are as set forth in Section 52.227-19 of the FARS Computer
* Software-Restricted Rights clause.
*
* Use, duplication, or disclosure by the Government is subject to
* restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
* Technical Data and Computer Software clause at DFARS 252.227-7013.
* Contractor/Manufacturer is Rogue Wave Software, Inc.,
* P.O. Box 2328, Corvallis, Oregon 97339.
*
* This computer software and information is distributed with "restricted
* rights." Use, duplication or disclosure is subject to restrictions as
* set forth in NASA FAR SUP 18-52.227-79 (April 1985) "Commercial
* Computer Software-Restricted Rights (April 1985)." If the Clause at
* 18-52.227-74 "Rights in Data General" is specified in the contract,
* then the "Alternate III" clause applies.
*
**************************************************************************/
#include <stdcomp.h>
#include <stddefs.h>
#ifndef RWSTD_NO_NEW_HEADER
#include <climits>
#include <cstddef>
#else
#include <limits.h>
#include <stddef.h>
#endif
#ifdef RW_STD_IOSTREAM
#include <iosfwd>
#else
class ostream;
class istream;
#endif
#ifndef RWSTD_NO_EXCEPTIONS
#ifdef RW_STD_EXCEPT
#include <stdexcept>
#endif
#endif
#include <string>
#ifndef RWSTD_NO_NAMESPACE
namespace std {
#endif
//
// Exception error messages.
//
extern char RWSTDExport __rw_bitset_InvalidPosition[];
extern char RWSTDExport __rw_bitset_InvalidCtorArgument[];
extern char RWSTDExport __rw_bitset_ConversionOverflow[];
template <size_t N>
class bitset
{
private:
//
// The type of array in which we store the bits.
//
typedef unsigned int VectorType;
//
// Number of bits in an array element.
//
enum { BitsPerChunk = CHAR_BIT*sizeof(unsigned int) };
//
// Number of array elements.
//
#ifndef RWSTD_BC5_ENUM_BUG
enum { NumOfElems = N == 0 ? 1 : 1 + ((N - 1) / BitsPerChunk) };
#define NELEMENTS NumOfElems
#else
int NumOfElems () const
{
return N == 0 ? 1 : 1 + ((N - 1) / BitsPerChunk);
}
#define NELEMENTS NumOfElems()
#endif /*RWSTD_BC5_ENUM_BUG*/
//
// Number of bits in an unsigned long.
//
enum { BitsInUnsignedLong = CHAR_BIT*sizeof(unsigned long) };
//
// The array of bits.
//
#ifndef RWSTD_BC5_ENUM_BUG
VectorType bits[NELEMENTS];
#else
VectorType* bits;
#endif /*RWSTD_BC5_ENUM_BUG*/
protected:
//
// Is pos a valid bitset position?
//
bool valid_position (size_t pos) const RWSTD_THROW_SPEC_NULL
{
return N > pos ? true : false;
}
//
// Given a bit position `pos', returns the index into the appropriate
// chunk in bits[] such that 0 <= index < BitsPerChunk.
//
size_t index (size_t pos) const RWSTD_THROW_SPEC_NULL
{
#if UINT_MAX == 256
return 7 & pos;
#elif UINT_MAX == 65535
return 15 & pos;
#elif UINT_MAX == 4294967295
return 31 & pos;
#elif UINT_MAX == 18446744073709551616
return 63 & pos;
#else
return pos % BitsPerChunk;
#endif
}
public:
//
// bit reference
//
class reference
{
friend class bitset<N>;
private:
bitset<N>& ref;
size_t pos;
reference (bitset<N>& r, size_t p) RWSTD_THROW_SPEC_NULL
: ref(r), pos(p) {}
public:
~reference() RWSTD_THROW_SPEC_NULL {}
//
// for b[i] = x;
//
reference& operator= (bool val) RWSTD_THROW_SPEC_NULL
{
ref.set(pos, val); return *this;
}
//
// for b[i] = b[j];
//
reference& operator= (const reference& rhs) RWSTD_THROW_SPEC_NULL
{
ref.set(pos, rhs.ref.test(rhs.pos)); return *this;
}
//
// for x = ~b[i];
//
bool operator~ () const RWSTD_THROW_SPEC_NULL { return !ref.test(pos);}
//
// for x = b[i];
//
operator bool () const RWSTD_THROW_SPEC_NULL { return ref.test(pos); }
//
// flips the bit
//
reference& flip() RWSTD_THROW_SPEC_NULL { ref.flip(pos); return *this;}
};
//
// constructors
//
bitset () RWSTD_THROW_SPEC_NULL
{
#ifndef RWSTD_BC5_ENUM_BUG
memset(bits, 0, sizeof(bits));
#else
bits = new VectorType[NELEMENTS];
//
// TODO -- check for bits == 0 here?
//
memset(bits, 0, NELEMENTS*sizeof(VectorType));
#endif /*RWSTD_BC5_ENUM_BUG*/
}
bitset (unsigned long val) RWSTD_THROW_SPEC_NULL
{
//
// Initialize first M bit positions to the corresponding
// bit values in val. M is the smaller of N and the value
// CHAR_BIT * sizeof(unsigned long).
//
#ifndef RWSTD_BC5_ENUM_BUG
memset(bits, 0, sizeof(bits));
#else
bits = new VectorType[NELEMENTS];
//
// TODO -- check for bits == 0 here?
//
memset(bits, 0, NELEMENTS*sizeof(VectorType));
#endif /*RWSTD_BC5_ENUM_BUG*/
size_t M = N < BitsInUnsignedLong ? N : BitsInUnsignedLong;
for (size_t i = 0; i < M; i++)
if (val & (1 << i))
set(i);
}
explicit bitset (const string& str,
size_t pos = 0,
size_t n = (size_t) -1)
RWSTD_THROW_SPEC((out_of_range, invalid_argument));
//
// We explicitly defined the copy constructor, though
// WP 17.2.2.2 allows us to use the default generated one.
//
bitset (const bitset<N>& rhs) RWSTD_THROW_SPEC_NULL
{
#ifndef RWSTD_BC5_ENUM_BUG
memcpy(bits, rhs.bits, sizeof(bits));
#else
bits = new VectorType[NELEMENTS];
//
// TODO -- check for bits == 0 here?
//
memcpy(bits, rhs.bits, NELEMENTS*sizeof(VectorType));
#endif /*RWSTD_BC5_ENUM_BUG*/
}
//
// We explicitly defined the assignment, though
// WP 17.2.2.2 allows us to use the default generated one.
//
bitset<N>& operator= (const bitset<N>& rhs) RWSTD_THROW_SPEC_NULL
{
if (!(this == &rhs))
#ifndef RWSTD_BC5_ENUM_BUG
memcpy(bits, rhs.bits, sizeof(bits));
#else
memcpy(bits, rhs.bits, NELEMENTS*sizeof(VectorType));
#endif /*RWSTD_BC5_ENUM_BUG*/
return *this;
}
#ifdef RWSTD_BC5_ENUM_BUG
~bitset () RWSTD_THROW_SPEC_NULL { delete [] bits; }
#endif
//
// bitset operations
//
bitset<N>& operator&= (const bitset<N>& rhs) RWSTD_THROW_SPEC_NULL
{
for (size_t i = 0; i < NELEMENTS; i++)
bits[i] &= rhs.bits[i];
return *this;
}
bitset<N>& operator|= (const bitset<N>& rhs) RWSTD_THROW_SPEC_NULL
{
for (size_t i = 0; i < NELEMENTS; i++)
bits[i] |= rhs.bits[i];
return *this;
}
bitset<N>& operator^= (const bitset<N>& rhs) RWSTD_THROW_SPEC_NULL
{
for (size_t i = 0; i < NELEMENTS; i++)
bits[i] ^= rhs.bits[i];
return *this;
}
//
// Replaces bit at position I with a value determined as follows:
//
// If (I < pos) the new value is 0
// If (I >= pos) the new value is the previous value at position I - pos
//
bitset<N>& operator<<= (size_t pos) RWSTD_THROW_SPEC_NULL
{
if (pos)
for (long i = N - 1; i >= 0 ; --i)
set(i, i < pos || test(i - pos) == 0 ? 0 : 1);
return *this;
}
//
// Replaces bit at position I with a value determined as follows:
//
// If (pos >= N-i) the new value is zero
// If (pos < N-i) the new value is the previous value at position I + pos
//
bitset<N>& operator>>= (size_t pos) RWSTD_THROW_SPEC_NULL
{
if (pos)
for (size_t i = 0; i < N; i++)
set(i, pos >= N - i || test(i + pos) == 0 ? 0 : 1);
return *this;
}
bitset<N>& set () RWSTD_THROW_SPEC_NULL
{
for (size_t i = 0; i < NELEMENTS; i++)
bits[i] = ~0;
return *this;
}
bitset<N>& set (size_t pos, int val = 1) RWSTD_THROW_SPEC((out_of_range))
{
RWSTD_THROW(!valid_position(pos),
out_of_range,
__rw_bitset_InvalidPosition);
if (val)
bits[pos / BitsPerChunk] |= (1 << index(pos));
else
bits[pos / BitsPerChunk] &= ~(1 << index(pos));
return *this;
}
bitset<N>& reset () RWSTD_THROW_SPEC_NULL
{
memset(bits, 0, sizeof(bits)); return *this;
}
bitset<N>& reset (size_t pos) RWSTD_THROW_SPEC((out_of_range))
{
return set(pos, 0);
}
bitset<N> operator~ () RWSTD_THROW_SPEC_NULL
{
bitset<N> tmp(*this); return tmp.flip();
}
bitset<N>& flip () RWSTD_THROW_SPEC_NULL
{
for (size_t i = 0; i < NELEMENTS; i++)
bits[i] = ~bits[i];
return *this;
}
bitset<N>& flip (size_t pos) RWSTD_THROW_SPEC((out_of_range))
{
RWSTD_THROW(!valid_position(pos),
out_of_range,
__rw_bitset_InvalidPosition);
bits[pos / BitsPerChunk] ^= (1 << index(pos));
return *this;
}
//
// element access
//
reference operator[] (size_t pos) RWSTD_THROW_SPEC((out_of_range))
{
//
// We check that pos is valid here so that NONE of the reference
// member functions need check. This way ALL the reference member
// functions can have empty throw specifications.
//
RWSTD_THROW(!valid_position(pos),
out_of_range,
__rw_bitset_InvalidPosition);
reference r(*this, pos); return r;
}
//
// conversion functions
//
unsigned long to_ulong () const RWSTD_THROW_SPEC((overflow_error));
string to_string () const;
//
// miscellaneous member functions
//
size_t count () const RWSTD_THROW_SPEC_NULL;
size_t size () const RWSTD_THROW_SPEC_NULL { return N; }
bool operator== (const bitset<N>& rhs) const RWSTD_THROW_SPEC_NULL
{
bool flag = true;
for (size_t i = 0; i < NELEMENTS && flag; i++)
if (!(bits[i] == rhs.bits[i]))
flag = false;
return flag;
}
bool operator!= (const bitset<N>& rhs) const RWSTD_THROW_SPEC_NULL
{
return !(*this == rhs);
}
bool test (size_t pos) const RWSTD_THROW_SPEC((out_of_range))
{
RWSTD_THROW(!valid_position(pos),
out_of_range,
__rw_bitset_InvalidPosition);
return (bits[pos / BitsPerChunk] & (1 << index(pos))) != 0;
}
bool any () const RWSTD_THROW_SPEC_NULL
{
bool flag = false;
for (size_t i = 0; i < NELEMENTS && !flag; i++)
if (bits[i])
flag = true;
return flag;
}
bool none () const RWSTD_THROW_SPEC_NULL
{
bool flag = true;
for (size_t i = 0; i < NELEMENTS && flag; i++)
if (bits[i])
flag = false;
return flag;
}
bitset<N> operator<< (size_t pos) const RWSTD_THROW_SPEC_NULL
{
bitset<N> tmp(*this); tmp <<= pos; return tmp;
}
bitset<N> operator>> (size_t pos) const RWSTD_THROW_SPEC_NULL
{
bitset<N> tmp(*this); tmp >>= pos; return tmp;
}
};
template <size_t N>
bitset<N>::bitset (const string& str,
size_t pos,
size_t n) RWSTD_THROW_SPEC((out_of_range, invalid_argument))
{
size_t slen = str.size();
RWSTD_THROW(pos > slen,
out_of_range,
__rw_bitset_InvalidPosition);
size_t rlen = n < (slen - pos) ? n : slen - pos;
size_t M = N >= rlen ? rlen : N;
#ifndef RWSTD_BC5_ENUM_BUG
memset(bits, 0, sizeof(bits));
#else
bits = new VectorType[NELEMENTS];
//
// TODO -- check for bits == 0 here?
//
memset(bits, 0, NELEMENTS*sizeof(VectorType));
#endif /*RWSTD_BC5_ENUM_BUG*/
for (size_t i = pos; i < M + pos; i++)
{
char c = str[slen - i - 1];
RWSTD_THROW(!(c == '0' || c == '1'),
invalid_argument,
__rw_bitset_InvalidCtorArgument);
if (c == '1') set(i - pos);
}
}
//
// Constructs an object of type string and initializes it
// to a string of length N characters. Each character is
// determined by the value of its corresponding bit position
// in *this. Character position N-1 corresponds to bit
// position zero. Subsequent decreasing character positions
// correspond to increasing bit positions. Bit value zero becomes
// the character 0, bit value one becomes the character 1.
//
template <size_t N>
string
bitset<N>::to_string () const
{
string s;
if (N)
for (long i = N - 1; i >= 0; --i)
s.append(1, test(i) ? '1' : '0');
return s;
}
//
// If the integral value x corresponding to the bitset in *this
// cannot be represented as type unsigned long, throws overflow_error.
//
template <size_t N>
unsigned long
bitset<N>::to_ulong () const RWSTD_THROW_SPEC((overflow_error))
{
const size_t size_long = sizeof(unsigned long);
for (size_t i = NELEMENTS-1; size_long/sizeof(VectorType) <= i; --i)
RWSTD_THROW(bits[i],
overflow_error,
__rw_bitset_ConversionOverflow);
unsigned long result = 0;
for (size_t pos = 0; pos < N; pos++)
if (test(pos))
result |= 1 << pos;
return result;
}
//
// Returns the count of the number of set bits.
//
template <size_t N>
size_t
bitset<N>::count () const RWSTD_THROW_SPEC_NULL
{
size_t sum = 0;
#if UINT_MAX <= 4294967295
//
// A sophisticated implementaton that works if BitsPerChunk < 63
//
for (size_t i = 0; i < NELEMENTS; i++)
{
unsigned long n = bits[i];
unsigned long t = n - ((n>>1) & 033333333333) - ((n>>2) & 011111111111);
t = ((t + (t >> 3)) & 030707070707);
unsigned long x = t & 07700770077;
unsigned long y = (t >> 6) & 07700770077;
t = x + y;
t = ((t >> 12) + (t >> 24) + t) & 0777;
t = (t >> 6) + (t & 077);
t = t + 1;
sum += (t >> 6) + (t & 077) - 1;
}
#else
//
// The more naive implementation that always works.
//
for (size_t i = 0; i < NELEMENTS; i++)
{
unsigned long n = bits[i];
while (n)
{
n &= n-1;
sum++;
}
}
#endif
return sum;
}
#ifndef RWSTD_NO_NONTYPE_ARGS
template<size_t N>
bitset<N> operator& (const bitset<N>& lhs,
const bitset<N>& rhs) RWSTD_THROW_SPEC_NULL
{
bitset<N> tmp(lhs); tmp &= rhs; return tmp;
}
template<size_t N>
bitset<N> operator| (const bitset<N>& lhs,
const bitset<N>& rhs) RWSTD_THROW_SPEC_NULL
{
bitset<N> tmp(lhs); tmp |= rhs; return tmp;
}
template<size_t N>
bitset<N> operator^ (const bitset<N>& lhs,
const bitset<N>& rhs) RWSTD_THROW_SPEC_NULL
{
bitset<N> tmp(lhs); tmp ^= rhs; return tmp;
}
template<size_t N> ostream& operator<< (ostream& os, const bitset<N>& x)
{
return os << x.to_string();
}
template <size_t N>
istream&
operator>> (istream& is, bitset<N>& x)
{
string str(N, '0');
for (size_t count = 0; count < N && !is.eof(); )
{
char c = 0;
is >> c;
if (c == '1' || c == '0')
{
str.append(1, c);
count++;
}
else
{
is.putback(c);
break;
}
}
if (str.size() == 0)
#ifdef RW_STD_IOSTREAM
is.setstate(ios::failbit);
#else
is.clear(ios::failbit);
#endif
x = bitset<N>(str);
return is;
}
#endif /*RWSTD_NO_NONTYPE_ARGS*/
#if defined(RWSTD_NO_DESTROY_BUILTIN) || defined(RWSTD_NO_DESTROY_NONBUILTIN)
#ifndef RWSTD_NO_NONTYPE_ARGS
//
// Specializations of STL destroy for bitset.
//
template <size_t N> inline void destroy (bitset<N>**) {;}
template <size_t N> inline void destroy (bitset<N>***) {;}
template <size_t N> inline void destroy (bitset<N>****) {;}
#endif
#endif
#undef NELEMENTS
#ifndef RWSTD_NO_NAMESPACE
}
#endif
#endif /*__STD_BITS*/