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