Old snapshot `BigIntegerLibrary-2005.01.11'; see the ChangeLog file.
[bigint/bigint.git] / BigUnsigned.hh
1 /*
2 * Matt McCutchen's Big Integer Library
3 * http://mysite.verizon.net/mccutchen/bigint/
4 */
5
6 #ifndef BIGUNSIGNED
7 #define BIGUNSIGNED
8
9 #include "NumberlikeArray.hh"
10
11 /*
12 * A BigUnsigned object represents a nonnegative integer of size
13 * limited only by available memory.  A BigUnsigned can be
14 * created from and converted back to most integral types,
15 * and many math operations are defined on BigUnsigneds.
16 *
17 * The number is stored as a series of blocks in a
18 * dynamically allocated array.  It is as if the number
19 * were written digit by digit in base 2 ^ N, **where N is the
20 * number of bits in an unsigned long.**
21 *
22 * The memory-management details that used to be in here have
23 * been moved into NumberlikeArray, which BigUnsigned now derives from.
24 * `(NlA)' means that member(s) are declared identically in NumberlikeArray.
25 * Such members are either redeclared here to make them public or are
26 * here, commented out, for reference.
27 */
28
29 class BigUnsigned : protected NumberlikeArray<unsigned long> {
30         
31         // TYPES & CONSTANTS
32         public:
33         enum CmpRes { less = -1, equal = 0, greater = 1 }; // Enumeration for the result of a comparison
34         typedef unsigned long Blk; // The number block type that BigUnsigneds are built from
35         typedef NumberlikeArray<Blk>::Index Index; // (NlA) Type for the index of a block in the array
36         NumberlikeArray<Blk>::N; // Number of bits in a Blk
37         
38         /*
39         // FIELDS
40         protected:
41         Index cap; // (NlA) The current allocated capacity of this BigUnsigned (in blocks)
42         Index len; // (NlA) The actual length of the number stored in this BigUnsigned (in blocks)
43         Blk *blk; // (NlA) Dynamically allocated array of the number blocks
44         */
45         
46         // MANAGEMENT
47         protected:
48         // These members generally defer to those in NumberlikeArray, possibly with slight changes.
49         // It might be nice if one could request that constructors be inherited in C++.
50         
51         BigUnsigned(int, Index c) : NumberlikeArray<Blk>(0, c) {} // Creates a BigUnsigned with a capacity
52         
53         void zapLeadingZeros() { // Decreases len to eliminate leading zeros
54                 while (len > 0 && blk[len - 1] == 0)
55                         len--;
56         }
57         
58         //void allocate(Index c); // (NlA) Ensures the number array has at least the indicated capacity, maybe discarding contents
59         //void allocateAndCopy(Index c); // (NlA) Ensures the number array has at least the indicated capacity, preserving its contents
60         
61         public:
62         BigUnsigned() : NumberlikeArray<Blk>() {} // Default constructor (value is 0)
63         BigUnsigned(const BigUnsigned &x) : NumberlikeArray<Blk>(x) {} // Copy constructor
64         
65         void operator=(const BigUnsigned &x) { // Assignment operator
66                 NumberlikeArray<Blk>::operator =(x);
67         }
68         
69         BigUnsigned(const Blk *b, Index l) : NumberlikeArray<Blk>(b, l) { // Constructor from an array of blocks
70                 zapLeadingZeros();
71         }
72         
73         // Constructors from integral types
74         BigUnsigned(unsigned long  x);
75         BigUnsigned(         long  x);
76         BigUnsigned(unsigned int   x);
77         BigUnsigned(         int   x);
78         BigUnsigned(unsigned short x);
79         BigUnsigned(         short x);
80         ~BigUnsigned() {} // Destructor
81         
82         // CONVERTERS to integral types
83         public:
84         operator unsigned long () const;
85         operator          long () const;
86         operator unsigned int  () const;
87         operator          int  () const;
88         operator unsigned short() const;
89         operator          short() const;
90         
91         // PICKING APART
92         // These accessors can be used to get the pieces of the number
93         public:
94         NumberlikeArray<Blk>::getCapacity;
95         NumberlikeArray<Blk>::getLength;
96         // Note that getBlock returns 0 if the block index is beyond the length of the number.
97         // A routine that uses this accessor can safely assume a BigUnsigned has 0s infinitely to the left.
98         Blk getBlock(Index i) const { return i >= len ? 0 : blk[i]; }
99         // Note how we replace one level of abstraction with another.  Isn't that neat?
100         bool isZero() const { return NumberlikeArray<Blk>::isEmpty(); } // Often convenient for loops
101         
102         // COMPARISONS
103         public:
104         // Compares this to x like Perl's <=>
105         CmpRes compareTo(const BigUnsigned &x) const;
106         // Normal comparison operators
107         NumberlikeArray<Blk>::operator ==; // (NlA) The body used to be `{ return compareTo(x) == equal; }'.  For performance reasons we use NumberlikeArray code that only worries about (in)equality and doesn't waste time determining which is bigger
108         NumberlikeArray<Blk>::operator !=; // (NlA) Ditto.
109         bool operator < (const BigUnsigned &x) const { return compareTo(x) == less   ; }
110         bool operator <=(const BigUnsigned &x) const { return compareTo(x) != greater; }
111         bool operator >=(const BigUnsigned &x) const { return compareTo(x) != less   ; }
112         bool operator > (const BigUnsigned &x) const { return compareTo(x) == greater; }
113         
114         // PUT-HERE OPERATIONS
115         /* These store the result of the operation on the arguments into this.
116         * a.add(b, c) is equivalent to, but faster than, a = b + c.
117         * Calls like a.operation(a, b) are unsafe and not allowed. */
118         public:
119         // Easy 3
120         void add          (const BigUnsigned &a, const BigUnsigned &b); // Addition
121         void subtract     (const BigUnsigned &a, const BigUnsigned &b); // Subtraction
122         void multiply     (const BigUnsigned &a, const BigUnsigned &b); // Multiplication
123         /* Divisive stuff
124         * `a.divideWithRemainder(b, q)' is like `q = a / b, a %= b'.
125         * Semantics similar to Donald E. Knuth's are used for / and %,
126         * and these differ from the semantics of primitive-type
127         * / and % under division by zero.
128         * Look in `BigUnsigned.cc' for details.
129         */
130         void divideWithRemainder(const BigUnsigned &b, BigUnsigned &q);
131         void divide(const BigUnsigned &a, const BigUnsigned &b) {
132                 // Division, deprecated and provided for compatibility
133                 BigUnsigned a2(a);
134                 a2.divideWithRemainder(b, *this);
135                 // quotient now in *this
136                 // don't care about remainder left in a2
137         }
138         void modulo(const BigUnsigned &a, const BigUnsigned &b) {
139                 // Modular reduction, deprecated and provided for compatibility
140                 *this = a;
141                 BigUnsigned q;
142                 divideWithRemainder(b, q);
143                 // remainder now in *this
144                 // don't care about quotient left in q
145         }
146         // Bitwise
147         void bitAnd       (const BigUnsigned &a, const BigUnsigned &b); // Bitwise AND
148         void bitOr        (const BigUnsigned &a, const BigUnsigned &b); // Bitwise OR
149         void bitXor       (const BigUnsigned &a, const BigUnsigned &b); // Bitwise XOR
150         
151         // These functions are declared but not defined.  (Sorry.)
152         // Trying to call either will result in a link-time error.
153         void bitShiftLeft (const BigUnsigned &a, unsigned int b); // Bitwise left shift
154         void bitShiftRight(const BigUnsigned &a, unsigned int b); // Bitwise right shift
155         
156         // NORMAL OPERATORS
157         // These perform the operation on this (to the left of the operator)
158         // and x (to the right of the operator) and return a new BigUnsigned with the result.
159         public:
160         BigUnsigned operator +(const BigUnsigned &x) const; // Addition
161         BigUnsigned operator -(const BigUnsigned &x) const; // Subtraction
162         BigUnsigned operator *(const BigUnsigned &x) const; // Multiplication
163         BigUnsigned operator /(const BigUnsigned &x) const; // Division
164         BigUnsigned operator %(const BigUnsigned &x) const; // Modular reduction
165         BigUnsigned operator &(const BigUnsigned &x) const; // Bitwise AND
166         BigUnsigned operator |(const BigUnsigned &x) const; // Bitwise OR
167         BigUnsigned operator ^(const BigUnsigned &x) const; // Bitwise XOR
168         
169         // ASSIGNMENT OPERATORS
170         // These perform the operation on this and x, storing the result into this.
171         public:
172         void operator +=(const BigUnsigned &x); // Addition
173         void operator -=(const BigUnsigned &x); // Subtraction
174         void operator *=(const BigUnsigned &x); // Multiplication
175         void operator /=(const BigUnsigned &x); // Division
176         void operator %=(const BigUnsigned &x); // Modular reduction
177         void operator &=(const BigUnsigned &x); // Bitwise AND
178         void operator |=(const BigUnsigned &x); // Bitwise OR
179         void operator ^=(const BigUnsigned &x); // Bitwise XOR
180         
181         // INCREMENT/DECREMENT OPERATORS
182         // These increase or decrease the number by 1.  To discourage side effects,
183         // these do not return *this, so prefix and postfix behave the same.
184         public:
185         void operator ++(   ); // Prefix  increment
186         void operator ++(int); // Postfix decrement
187         void operator --(   ); // Prefix  increment
188         void operator --(int); // Postfix decrement
189         
190         // Helper function that needs access to BigUnsigned internals
191         friend Blk getShiftedBlock(const BigUnsigned &num, Index x, unsigned int y);
192 };
193
194 // NORMAL OPERATORS
195 /* These create an object to hold the result and invoke
196 * the appropriate put-here operation on it, passing
197 * this and x.  The new object is then returned. */
198 inline BigUnsigned BigUnsigned::operator +(const BigUnsigned &x) const {
199         BigUnsigned ans;
200         ans.add(*this, x);
201         return ans;
202 }
203 inline BigUnsigned BigUnsigned::operator -(const BigUnsigned &x) const {
204         BigUnsigned ans;
205         ans.subtract(*this, x);
206         return ans;
207 }
208 inline BigUnsigned BigUnsigned::operator *(const BigUnsigned &x) const {
209         BigUnsigned ans;
210         ans.multiply(*this, x);
211         return ans;
212 }
213 inline BigUnsigned BigUnsigned::operator /(const BigUnsigned &x) const {
214         BigUnsigned ans;
215         ans.divide(*this, x);
216         return ans;
217 }
218 inline BigUnsigned BigUnsigned::operator %(const BigUnsigned &x) const {
219         BigUnsigned ans;
220         ans.modulo(*this, x);
221         return ans;
222 }
223 inline BigUnsigned BigUnsigned::operator &(const BigUnsigned &x) const {
224         BigUnsigned ans;
225         ans.bitAnd(*this, x);
226         return ans;
227 }
228 inline BigUnsigned BigUnsigned::operator |(const BigUnsigned &x) const {
229         BigUnsigned ans;
230         ans.bitOr(*this, x);
231         return ans;
232 }
233 inline BigUnsigned BigUnsigned::operator ^(const BigUnsigned &x) const {
234         BigUnsigned ans;
235         ans.bitXor(*this, x);
236         return ans;
237 }
238
239 // ASSIGNMENT OPERATORS
240 // These create a copy of this, then invoke the appropriate
241 // put-here operation on this, passing the copy and x.
242 // Exception: those updated for divideWithRemainder.
243 inline void BigUnsigned::operator +=(const BigUnsigned &x) {
244         BigUnsigned thisCopy(*this);
245         add(thisCopy, x);
246 }
247 inline void BigUnsigned::operator -=(const BigUnsigned &x) {
248         BigUnsigned thisCopy(*this);
249         subtract(thisCopy, x);
250 }
251 inline void BigUnsigned::operator *=(const BigUnsigned &x) {
252         BigUnsigned thisCopy(*this);
253         multiply(thisCopy, x);
254 }
255 inline void BigUnsigned::operator /=(const BigUnsigned &x) {
256         // Updated for divideWithRemainder
257         BigUnsigned thisCopy(*this);
258         thisCopy.divideWithRemainder(x, *this);
259         // quotient left in *this
260         // don't care about remainder left in thisCopy
261 }
262 inline void BigUnsigned::operator %=(const BigUnsigned &x) {
263         // Shortcut (woohoo!)
264         BigUnsigned q;
265         divideWithRemainder(x, q);
266         // remainder left in *this
267         // don't care about quotient left in q
268 }
269 inline void BigUnsigned::operator &=(const BigUnsigned &x) {
270         BigUnsigned thisCopy(*this);
271         bitAnd(thisCopy, x);
272 }
273 inline void BigUnsigned::operator |=(const BigUnsigned &x) {
274         BigUnsigned thisCopy(*this);
275         bitOr(thisCopy, x);
276 }
277 inline void BigUnsigned::operator ^=(const BigUnsigned &x) {
278         BigUnsigned thisCopy(*this);
279         bitXor(thisCopy, x);
280 }
281
282 #endif