#ifndef NUMBERLIKEARRAY_H #define NUMBERLIKEARRAY_H // Make sure we have NULL. #ifndef NULL #define NULL 0 #endif /* A NumberlikeArray 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 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 &x); // Assignment operator void operator=(const NumberlikeArray &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 &x) const; bool operator !=(const NumberlikeArray &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 const unsigned int NumberlikeArray::N = 8 * sizeof(Blk); template void NumberlikeArray::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 void NumberlikeArray::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 NumberlikeArray::NumberlikeArray(const NumberlikeArray &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 void NumberlikeArray::operator=(const NumberlikeArray &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 NumberlikeArray::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 bool NumberlikeArray::operator ==(const NumberlikeArray &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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172