BigInteger.cc revision e6986e1e8d4a57987f47c215490cb080a65ee29a
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. 4 5// Original code by Matt McCutchen, see the LICENSE file. 6 7#include "BigInteger.hh" 8 9void 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} 18 19BigInteger::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} 37 38BigInteger::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} 56 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. */ 60 61// Done longhand to let us use initialization. 62BigInteger::BigInteger(unsigned long x) : mag(x) { sign = mag.isZero() ? zero : positive; } 63BigInteger::BigInteger(unsigned int x) : mag(x) { sign = mag.isZero() ? zero : positive; } 64BigInteger::BigInteger(unsigned short x) : mag(x) { sign = mag.isZero() ? zero : positive; } 65 66// For signed input, determine the desired magnitude and sign separately. 67 68namespace { 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} 82 83BigInteger::BigInteger(long x) : sign(signOf(x)), mag(magOf<long , unsigned long >(x)) {} 84BigInteger::BigInteger(int x) : sign(signOf(x)), mag(magOf<int , unsigned int >(x)) {} 85BigInteger::BigInteger(short x) : sign(signOf(x)), mag(magOf<short, unsigned short>(x)) {} 86 87// CONVERSION TO PRIMITIVE INTEGERS 88 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. */ 93template <class X> 94inline X convertBigUnsignedToPrimitiveAccess(const BigUnsigned &a) { 95 return a.convertToPrimitive<X>(); 96} 97 98template <class X> 99X BigInteger::convertToUnsignedPrimitive() const { 100 if (sign == negative) 101 abort(); 102 else 103 return convertBigUnsignedToPrimitiveAccess<X>(mag); 104} 105 106/* Similar to BigUnsigned::convertToPrimitive, but split into two cases for 107 * nonnegative and negative numbers. */ 108template <class X, class UX> 109X 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} 130 131unsigned long BigInteger::toUnsignedLong () const { return convertToUnsignedPrimitive<unsigned long > (); } 132unsigned int BigInteger::toUnsignedInt () const { return convertToUnsignedPrimitive<unsigned int > (); } 133unsigned short BigInteger::toUnsignedShort() const { return convertToUnsignedPrimitive<unsigned short> (); } 134long BigInteger::toLong () const { return convertToSignedPrimitive <long , unsigned long> (); } 135int BigInteger::toInt () const { return convertToSignedPrimitive <int , unsigned int> (); } 136short BigInteger::toShort () const { return convertToSignedPrimitive <short, unsigned short>(); } 137 138// COMPARISON 139BigInteger::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} 159 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. */ 163 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 } 172 173void 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; 184 mag.add(a.mag, b.mag); 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} 206 207void 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; 222 mag.add(a.mag, b.mag); 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} 246 247void 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} 261 262/* 263 * DIVISION WITH REMAINDER 264 * Please read the comments before the definition of 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 */ 284void 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 } 294 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 } 307 308 // Here *this != 0, b != 0. 309 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 } 340 341 // Divide the magnitudes. 342 mag.divideWithRemainder(b.mag, q.mag); 343 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 } 352 353 // Sign of the remainder is always the sign of the divisor b. 354 sign = b.sign; 355 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; 361 362 // WHEW!!! 363} 364 365// Negation 366void 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} 373 374// INCREMENT/DECREMENT OPERATORS 375 376// Prefix increment 377void 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} 387 388// Postfix increment: same as prefix 389void BigInteger::operator ++(int) { 390 operator ++(); 391} 392 393// Prefix decrement 394void BigInteger::operator --() { 395 if (sign == positive) { 396 mag--; 397 if (mag == 0) 398 sign = zero; 399 } else { 400 mag++; 401 sign = negative; 402 } 403} 404 405// Postfix decrement: same as prefix 406void BigInteger::operator --(int) { 407 operator --(); 408} 409 410