1 #include "BigInteger.hh"
3 void BigInteger::operator =(const BigInteger &x) {
4         // Calls like a = a have no effect
5         if (this == &x)
6                 return;
7         // Copy sign
8         sign = x.sign;
9         // Copy the rest
10         mag = x.mag;
11 }
13 BigInteger::BigInteger(const Blk *b, Index blen, Sign s) : mag(b, blen) {
14         switch (s) {
15         case zero:
16                 if (!mag.isZero())
17                         throw "BigInteger::BigInteger(const Blk *, Index, Sign): Cannot use a sign of zero with a nonzero magnitude";
18                 sign = zero;
19                 break;
20         case positive:
21         case negative:
22                 // If the magnitude is zero, force the sign to zero.
23                 sign = mag.isZero() ? zero : s;
24                 break;
25         default:
26                 /* g++ seems to be optimizing out this case on the assumption
27                  * that the sign is a valid member of the enumeration.  Oh well. */
28                 throw "BigInteger::BigInteger(const Blk *, Index, Sign): Invalid sign";
29         }
30 }
32 BigInteger::BigInteger(const BigUnsigned &x, Sign s) : mag(x) {
33         switch (s) {
34         case zero:
35                 if (!mag.isZero())
36                         throw "BigInteger::BigInteger(const BigUnsigned &, Sign): Cannot use a sign of zero with a nonzero magnitude";
37                 sign = zero;
38                 break;
39         case positive:
40         case negative:
41                 // If the magnitude is zero, force the sign to zero.
42                 sign = mag.isZero() ? zero : s;
43                 break;
44         default:
45                 /* g++ seems to be optimizing out this case on the assumption
46                  * that the sign is a valid member of the enumeration.  Oh well. */
47                 throw "BigInteger::BigInteger(const BigUnsigned &, Sign): Invalid sign";
48         }
49 }
51 /* CONSTRUCTION FROM PRIMITIVE INTEGERS
52  * Same idea as in BigUnsigned.cc, except that negative input results in a
53  * negative BigInteger instead of an exception. */
55 // Done longhand to let us use initialization.
56 BigInteger::BigInteger(unsigned long  x) : mag(x) { sign = mag.isZero() ? zero : positive; }
57 BigInteger::BigInteger(unsigned int   x) : mag(x) { sign = mag.isZero() ? zero : positive; }
58 BigInteger::BigInteger(unsigned short x) : mag(x) { sign = mag.isZero() ? zero : positive; }
60 // For signed input, determine the desired magnitude and sign separately.
62 namespace {
63         template <class X, class UX>
64         BigInteger::Blk magOf(X x) {
65                 /* UX(...) cast needed to stop short(-2^15), which negates to
66                  * itself, from sign-extending in the conversion to Blk. */
67                 return BigInteger::Blk(x < 0 ? UX(-x) : x);
68         }
69         template <class X>
70         BigInteger::Sign signOf(X x) {
71                 return (x == 0) ? BigInteger::zero
72                         : (x > 0) ? BigInteger::positive
73                         : BigInteger::negative;
74         }
75 }
77 BigInteger::BigInteger(long  x) : sign(signOf(x)), mag(magOf<long , unsigned long >(x)) {}
78 BigInteger::BigInteger(int   x) : sign(signOf(x)), mag(magOf<int  , unsigned int  >(x)) {}
79 BigInteger::BigInteger(short x) : sign(signOf(x)), mag(magOf<short, unsigned short>(x)) {}
81 // CONVERSION TO PRIMITIVE INTEGERS
83 /* Reuse BigUnsigned's conversion to an unsigned primitive integer.
84  * The friend is a separate function rather than
85  * BigInteger::convertToUnsignedPrimitive to avoid requiring BigUnsigned to
86  * declare BigInteger. */
87 template <class X>
88 inline X convertBigUnsignedToPrimitiveAccess(const BigUnsigned &a) {
89         return a.convertToPrimitive<X>();
90 }
92 template <class X>
93 X BigInteger::convertToUnsignedPrimitive() const {
94         if (sign == negative)
95                 throw "BigInteger::to<Primitive>: "
96                         "Cannot convert a negative integer to an unsigned type";
97         else
98                 return convertBigUnsignedToPrimitiveAccess<X>(mag);
99 }
101 /* Similar to BigUnsigned::convertToPrimitive, but split into two cases for
102  * nonnegative and negative numbers. */
103 template <class X, class UX>
104 X BigInteger::convertToSignedPrimitive() const {
105         if (sign == zero)
106                 return 0;
107         else if (mag.getLength() == 1) {
108                 // The single block might fit in an X.  Try the conversion.
109                 Blk b = mag.getBlock(0);
110                 if (sign == positive) {
111                         X x = X(b);
112                         if (x >= 0 && Blk(x) == b)
113                                 return x;
114                 } else {
115                         X x = -X(b);
116                         /* UX(...) needed to avoid rejecting conversion of
117                          * -2^15 to a short. */
118                         if (x < 0 && Blk(UX(-x)) == b)
119                                 return x;
120                 }
121                 // Otherwise fall through.
122         }
123         throw "BigInteger::to<Primitive>: "
124                 "Value is too big to fit in the requested type";
125 }
127 unsigned long  BigInteger::toUnsignedLong () const { return convertToUnsignedPrimitive<unsigned long >       (); }
128 unsigned int   BigInteger::toUnsignedInt  () const { return convertToUnsignedPrimitive<unsigned int  >       (); }
129 unsigned short BigInteger::toUnsignedShort() const { return convertToUnsignedPrimitive<unsigned short>       (); }
130 long           BigInteger::toLong         () const { return convertToSignedPrimitive  <long , unsigned long> (); }
131 int            BigInteger::toInt          () const { return convertToSignedPrimitive  <int  , unsigned int>  (); }
132 short          BigInteger::toShort        () const { return convertToSignedPrimitive  <short, unsigned short>(); }
134 // COMPARISON
135 BigInteger::CmpRes BigInteger::compareTo(const BigInteger &x) const {
136         // A greater sign implies a greater number
137         if (sign < x.sign)
138                 return less;
139         else if (sign > x.sign)
140                 return greater;
141         else switch (sign) {
142                 // If the signs are the same...
143         case zero:
144                 return equal; // Two zeros are equal
145         case positive:
146                 // Compare the magnitudes
147                 return mag.compareTo(x.mag);
148         case negative:
149                 // Compare the magnitudes, but return the opposite result
150                 return CmpRes(-mag.compareTo(x.mag));
151         default:
152                 throw "BigInteger internal error";
153         }
154 }
156 /* COPY-LESS OPERATIONS
157  * These do some messing around to determine the sign of the result,
158  * then call one of BigUnsigned's copy-less operations. */
160 // See remarks about aliased calls in BigUnsigned.cc .
161 #define DTRT_ALIASED(cond, op) \
162         if (cond) { \
163                 BigInteger tmpThis; \
164                 tmpThis.op; \
165                 *this = tmpThis; \
166                 return; \
167         }
169 void BigInteger::add(const BigInteger &a, const BigInteger &b) {
170         DTRT_ALIASED(this == &a || this == &b, add(a, b));
171         // If one argument is zero, copy the other.
172         if (a.sign == zero)
173                 operator =(b);
174         else if (b.sign == zero)
175                 operator =(a);
176         // If the arguments have the same sign, take the
177         // common sign and add their magnitudes.
178         else if (a.sign == b.sign) {
179                 sign = a.sign;
181         } else {
182                 // Otherwise, their magnitudes must be compared.
183                 switch (a.mag.compareTo(b.mag)) {
184                 case equal:
185                         // If their magnitudes are the same, copy zero.
186                         mag = 0;
187                         sign = zero;
188                         break;
189                         // Otherwise, take the sign of the greater, and subtract
190                         // the lesser magnitude from the greater magnitude.
191                 case greater:
192                         sign = a.sign;
193                         mag.subtract(a.mag, b.mag);
194                         break;
195                 case less:
196                         sign = b.sign;
197                         mag.subtract(b.mag, a.mag);
198                         break;
199                 }
200         }
201 }
203 void BigInteger::subtract(const BigInteger &a, const BigInteger &b) {
204         // Notice that this routine is identical to BigInteger::add,
205         // if one replaces b.sign by its opposite.
206         DTRT_ALIASED(this == &a || this == &b, subtract(a, b));
207         // If a is zero, copy b and flip its sign.  If b is zero, copy a.
208         if (a.sign == zero) {
209                 mag = b.mag;
210                 // Take the negative of _b_'s, sign, not ours.
211                 // Bug pointed out by Sam Larkin on 2005.03.30.
212                 sign = Sign(-b.sign);
213         } else if (b.sign == zero)
214                 operator =(a);
215         // If their signs differ, take a.sign and add the magnitudes.
216         else if (a.sign != b.sign) {
217                 sign = a.sign;
219         } else {
220                 // Otherwise, their magnitudes must be compared.
221                 switch (a.mag.compareTo(b.mag)) {
222                         // If their magnitudes are the same, copy zero.
223                 case equal:
224                         mag = 0;
225                         sign = zero;
226                         break;
227                         // If a's magnitude is greater, take a.sign and
228                         // subtract a from b.
229                 case greater:
230                         sign = a.sign;
231                         mag.subtract(a.mag, b.mag);
232                         break;
233                         // If b's magnitude is greater, take the opposite
234                         // of b.sign and subtract b from a.
235                 case less:
236                         sign = Sign(-b.sign);
237                         mag.subtract(b.mag, a.mag);
238                         break;
239                 }
240         }
241 }
243 void BigInteger::multiply(const BigInteger &a, const BigInteger &b) {
244         DTRT_ALIASED(this == &a || this == &b, multiply(a, b));
245         // If one object is zero, copy zero and return.
246         if (a.sign == zero || b.sign == zero) {
247                 sign = zero;
248                 mag = 0;
249                 return;
250         }
251         // If the signs of the arguments are the same, the result
252         // is positive, otherwise it is negative.
253         sign = (a.sign == b.sign) ? positive : negative;
254         // Multiply the magnitudes.
255         mag.multiply(a.mag, b.mag);
256 }
258 /*
259  * DIVISION WITH REMAINDER
261  * `BigUnsigned::divideWithRemainder' in `BigUnsigned.cc' for lots of
262  * information you should know before reading this function.
263  *
264  * Following Knuth, I decree that x / y is to be
265  * 0 if y==0 and floor(real-number x / y) if y!=0.
266  * Then x % y shall be x - y*(integer x / y).
267  *
268  * Note that x = y * (x / y) + (x % y) always holds.
269  * In addition, (x % y) is from 0 to y - 1 if y > 0,
270  * and from -(|y| - 1) to 0 if y < 0.  (x % y) = x if y = 0.
271  *
272  * Examples: (q = a / b, r = a % b)
273  *      a       b       q       r
274  *      ===     ===     ===     ===
275  *      4       3       1       1
276  *      -4      3       -2      2
277  *      4       -3      -2      -2
278  *      -4      -3      1       -1
279  */
280 void BigInteger::divideWithRemainder(const BigInteger &b, BigInteger &q) {
281         // Defend against aliased calls;
282         // same idea as in BigUnsigned::divideWithRemainder .
283         if (this == &q)
284                 throw "BigInteger::divideWithRemainder: Cannot write quotient and remainder into the same variable";
285         if (this == &b || &q == &b) {
286                 BigInteger tmpB(b);
287                 divideWithRemainder(tmpB, q);
288                 return;
289         }
291         // Division by zero gives quotient 0 and remainder *this
292         if (b.sign == zero) {
293                 q.mag = 0;
294                 q.sign = zero;
295                 return;
296         }
297         // 0 / b gives quotient 0 and remainder 0
298         if (sign == zero) {
299                 q.mag = 0;
300                 q.sign = zero;
301                 return;
302         }
304         // Here *this != 0, b != 0.
306         // Do the operands have the same sign?
307         if (sign == b.sign) {
308                 // Yes: easy case.  Quotient is zero or positive.
309                 q.sign = positive;
310         } else {
311                 // No: harder case.  Quotient is negative.
312                 q.sign = negative;
313                 // Decrease the magnitude of the dividend by one.
314                 mag--;
315                 /*
316                  * We tinker with the dividend before and with the
317                  * quotient and remainder after so that the result
318                  * comes out right.  To see why it works, consider the following
319                  * list of examples, where A is the magnitude-decreased
320                  * a, Q and R are the results of BigUnsigned division
321                  * with remainder on A and |b|, and q and r are the
322                  * final results we want:
323                  *
324                  *      a       A       b       Q       R       q       r
325                  *      -3      -2      3       0       2       -1      0
326                  *      -4      -3      3       1       0       -2      2
327                  *      -5      -4      3       1       1       -2      1
328                  *      -6      -5      3       1       2       -2      0
329                  *
330                  * It appears that we need a total of 3 corrections:
331                  * Decrease the magnitude of a to get A.  Increase the
332                  * magnitude of Q to get q (and make it negative).
333                  * Find r = (b - 1) - R and give it the desired sign.
334                  */
335         }
337         // Divide the magnitudes.
338         mag.divideWithRemainder(b.mag, q.mag);
340         if (sign != b.sign) {
341                 // More for the harder case (as described):
342                 // Increase the magnitude of the quotient by one.
343                 q.mag++;
344                 // Modify the remainder.
345                 mag.subtract(b.mag, mag);
346                 mag--;
347         }
349         // Sign of the remainder is always the sign of the divisor b.
350         sign = b.sign;
352         // Set signs to zero as necessary.  (Thanks David Allen!)
353         if (mag.isZero())
354                 sign = zero;
355         if (q.mag.isZero())
356                 q.sign = zero;
358         // WHEW!!!
359 }
361 // Negation
362 void BigInteger::negate(const BigInteger &a) {
363         DTRT_ALIASED(this == &a, negate(a));
364         // Copy a's magnitude
365         mag = a.mag;
366         // Copy the opposite of a.sign
367         sign = Sign(-a.sign);
368 }
370 // INCREMENT/DECREMENT OPERATORS
372 // Prefix increment
373 void BigInteger::operator ++() {
374         if (sign == negative) {
375                 mag--;
376                 if (mag == 0)
377                         sign = zero;
378         } else {
379                 mag++;
380                 sign = positive; // if not already
381         }
382 }
384 // Postfix increment: same as prefix
385 void BigInteger::operator ++(int) {
386         operator ++();
387 }
389 // Prefix decrement
390 void BigInteger::operator --() {
391         if (sign == positive) {
392                 mag--;
393                 if (mag == 0)
394                         sign = zero;
395         } else {
396                 mag++;
397                 sign = negative;
398         }
399 }
401 // Postfix decrement: same as prefix
402 void BigInteger::operator --(int) {
403         operator --();
404 }