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