123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- #ifndef NUMBERLIKEARRAY_H
- #define NUMBERLIKEARRAY_H
- // Make sure we have NULL.
- #ifndef NULL
- #define NULL 0
- #endif
- /* A NumberlikeArray<Blk> object holds a heap-allocated array of Blk with a
- * length and a capacity and provides basic memory management features.
- * BigUnsigned and BigUnsignedInABase both subclass it.
- *
- * NumberlikeArray provides no information hiding. Subclasses should use
- * nonpublic inheritance and manually expose members as desired using
- * declarations like this:
- *
- * public:
- * NumberlikeArray< the-type-argument >::getLength;
- */
- template <class Blk>
- class NumberlikeArray {
- public:
- // Type for the index of a block in the array
- typedef unsigned int Index;
- // The number of bits in a block, defined below.
- static const unsigned int N;
- // The current allocated capacity of this NumberlikeArray (in blocks)
- Index cap;
- // The actual length of the value stored in this NumberlikeArray (in blocks)
- Index len;
- // Heap-allocated array of the blocks (can be NULL if len == 0)
- Blk *blk;
- // Constructs a ``zero'' NumberlikeArray with the given capacity.
- NumberlikeArray(Index c) : cap(c), len(0) {
- blk = (cap > 0) ? (new Blk[cap]) : NULL;
- }
- /* Constructs a zero NumberlikeArray without allocating a backing array.
- * A subclass that doesn't know the needed capacity at initialization
- * time can use this constructor and then overwrite blk without first
- * deleting it. */
- NumberlikeArray() : cap(0), len(0) {
- blk = NULL;
- }
- // Destructor. Note that `delete NULL' is a no-op.
- ~NumberlikeArray() {
- delete [] blk;
- }
- /* Ensures that the array has at least the requested capacity; may
- * destroy the contents. */
- void allocate(Index c);
- /* Ensures that the array has at least the requested capacity; does not
- * destroy the contents. */
- void allocateAndCopy(Index c);
- // Copy constructor
- NumberlikeArray(const NumberlikeArray<Blk> &x);
- // Assignment operator
- void operator=(const NumberlikeArray<Blk> &x);
- // Constructor that copies from a given array of blocks
- NumberlikeArray(const Blk *b, Index blen);
- // ACCESSORS
- Index getCapacity() const { return cap; }
- Index getLength() const { return len; }
- Blk getBlock(Index i) const { return blk[i]; }
- bool isEmpty() const { return len == 0; }
- /* Equality comparison: checks if both objects have the same length and
- * equal (==) array elements to that length. Subclasses may wish to
- * override. */
- bool operator ==(const NumberlikeArray<Blk> &x) const;
- bool operator !=(const NumberlikeArray<Blk> &x) const {
- return !operator ==(x);
- }
- };
- /* BEGIN TEMPLATE DEFINITIONS. They are present here so that source files that
- * include this header file can generate the necessary real definitions. */
- template <class Blk>
- const unsigned int NumberlikeArray<Blk>::N = 8 * sizeof(Blk);
- template <class Blk>
- void NumberlikeArray<Blk>::allocate(Index c) {
- // If the requested capacity is more than the current capacity...
- if (c > cap) {
- // Delete the old number array
- delete [] blk;
- // Allocate the new array
- cap = c;
- blk = new Blk[cap];
- }
- }
- template <class Blk>
- void NumberlikeArray<Blk>::allocateAndCopy(Index c) {
- // If the requested capacity is more than the current capacity...
- if (c > cap) {
- Blk *oldBlk = blk;
- // Allocate the new number array
- cap = c;
- blk = new Blk[cap];
- // Copy number blocks
- Index i;
- for (i = 0; i < len; i++)
- blk[i] = oldBlk[i];
- // Delete the old array
- delete [] oldBlk;
- }
- }
- template <class Blk>
- NumberlikeArray<Blk>::NumberlikeArray(const NumberlikeArray<Blk> &x)
- : len(x.len) {
- // Create array
- cap = len;
- blk = new Blk[cap];
- // Copy blocks
- Index i;
- for (i = 0; i < len; i++)
- blk[i] = x.blk[i];
- }
- template <class Blk>
- void NumberlikeArray<Blk>::operator=(const NumberlikeArray<Blk> &x) {
- /* Calls like a = a have no effect; catch them before the aliasing
- * causes a problem */
- if (this == &x)
- return;
- // Copy length
- len = x.len;
- // Expand array if necessary
- allocate(len);
- // Copy number blocks
- Index i;
- for (i = 0; i < len; i++)
- blk[i] = x.blk[i];
- }
- template <class Blk>
- NumberlikeArray<Blk>::NumberlikeArray(const Blk *b, Index blen)
- : cap(blen), len(blen) {
- // Create array
- blk = new Blk[cap];
- // Copy blocks
- Index i;
- for (i = 0; i < len; i++)
- blk[i] = b[i];
- }
- template <class Blk>
- bool NumberlikeArray<Blk>::operator ==(const NumberlikeArray<Blk> &x) const {
- if (len != x.len)
- // Definitely unequal.
- return false;
- else {
- // Compare corresponding blocks one by one.
- Index i;
- for (i = 0; i < len; i++)
- if (blk[i] != x.blk[i])
- return false;
- // No blocks differed, so the objects are equal.
- return true;
- }
- }
- #endif
|