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