/* ============================================================================== This file is part of the JUCE library - "Jules' Utility Class Extensions" Copyright 2004-11 by Raw Material Software Ltd. ------------------------------------------------------------------------------ JUCE can be redistributed and/or modified under the terms of the GNU General Public License (Version 2), as published by the Free Software Foundation. A copy of the license is included in the JUCE distribution, or can be found online at www.gnu.org/licenses. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.rawmaterialsoftware.com/juce for more information. ============================================================================== */ namespace { inline size_t bitToIndex (const int bit) noexcept { return (size_t) (bit >> 5); } inline uint32 bitToMask (const int bit) noexcept { return (uint32) 1 << (bit & 31); } } //============================================================================== BigInteger::BigInteger() : numValues (4), highestBit (-1), negative (false) { values.calloc (numValues + 1); } BigInteger::BigInteger (const int32 value) : numValues (4), highestBit (31), negative (value < 0) { values.calloc (numValues + 1); values[0] = (uint32) abs (value); highestBit = getHighestBit(); } BigInteger::BigInteger (const uint32 value) : numValues (4), highestBit (31), negative (false) { values.calloc (numValues + 1); values[0] = value; highestBit = getHighestBit(); } BigInteger::BigInteger (int64 value) : numValues (4), highestBit (63), negative (value < 0) { values.calloc (numValues + 1); if (value < 0) value = -value; values[0] = (uint32) value; values[1] = (uint32) (value >> 32); highestBit = getHighestBit(); } BigInteger::BigInteger (const BigInteger& other) : numValues ((size_t) jmax ((size_t) 4, bitToIndex (other.highestBit) + 1)), highestBit (other.getHighestBit()), negative (other.negative) { values.malloc (numValues + 1); memcpy (values, other.values, sizeof (uint32) * (numValues + 1)); } #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS BigInteger::BigInteger (BigInteger&& other) noexcept : values (static_cast &&> (other.values)), numValues (other.numValues), highestBit (other.highestBit), negative (other.negative) { } BigInteger& BigInteger::operator= (BigInteger&& other) noexcept { values = static_cast &&> (other.values); numValues = other.numValues; highestBit = other.highestBit; negative = other.negative; return *this; } #endif BigInteger::~BigInteger() { } void BigInteger::swapWith (BigInteger& other) noexcept { values.swapWith (other.values); std::swap (numValues, other.numValues); std::swap (highestBit, other.highestBit); std::swap (negative, other.negative); } BigInteger& BigInteger::operator= (const BigInteger& other) { if (this != &other) { highestBit = other.getHighestBit(); jassert (other.numValues >= 4); numValues = (size_t) jmax ((size_t) 4, bitToIndex (highestBit) + 1); negative = other.negative; values.malloc (numValues + 1); memcpy (values, other.values, sizeof (uint32) * (numValues + 1)); } return *this; } void BigInteger::ensureSize (const size_t numVals) { if (numVals + 2 >= numValues) { size_t oldSize = numValues; numValues = ((numVals + 2) * 3) / 2; values.realloc (numValues + 1); while (oldSize < numValues) values [oldSize++] = 0; } } //============================================================================== bool BigInteger::operator[] (const int bit) const noexcept { return bit <= highestBit && bit >= 0 && ((values [bitToIndex (bit)] & bitToMask (bit)) != 0); } int BigInteger::toInteger() const noexcept { const int n = (int) (values[0] & 0x7fffffff); return negative ? -n : n; } BigInteger BigInteger::getBitRange (int startBit, int numBits) const { BigInteger r; numBits = jmin (numBits, getHighestBit() + 1 - startBit); r.ensureSize ((size_t) bitToIndex (numBits)); r.highestBit = numBits; int i = 0; while (numBits > 0) { r.values[i++] = getBitRangeAsInt (startBit, (int) jmin (32, numBits)); numBits -= 32; startBit += 32; } r.highestBit = r.getHighestBit(); return r; } uint32 BigInteger::getBitRangeAsInt (const int startBit, int numBits) const noexcept { if (numBits > 32) { jassertfalse; // use getBitRange() if you need more than 32 bits.. numBits = 32; } numBits = jmin (numBits, highestBit + 1 - startBit); if (numBits <= 0) return 0; const size_t pos = bitToIndex (startBit); const int offset = startBit & 31; const int endSpace = 32 - numBits; uint32 n = ((uint32) values [pos]) >> offset; if (offset > endSpace) n |= ((uint32) values [pos + 1]) << (32 - offset); return n & (((uint32) 0xffffffff) >> endSpace); } void BigInteger::setBitRangeAsInt (const int startBit, int numBits, uint32 valueToSet) { if (numBits > 32) { jassertfalse; numBits = 32; } for (int i = 0; i < numBits; ++i) { setBit (startBit + i, (valueToSet & 1) != 0); valueToSet >>= 1; } } //============================================================================== void BigInteger::clear() { if (numValues > 16) { numValues = 4; values.calloc (numValues + 1); } else { values.clear (numValues + 1); } highestBit = -1; negative = false; } void BigInteger::setBit (const int bit) { if (bit >= 0) { if (bit > highestBit) { ensureSize (bitToIndex (bit)); highestBit = bit; } values [bitToIndex (bit)] |= bitToMask (bit); } } void BigInteger::setBit (const int bit, const bool shouldBeSet) { if (shouldBeSet) setBit (bit); else clearBit (bit); } void BigInteger::clearBit (const int bit) noexcept { if (bit >= 0 && bit <= highestBit) values [bitToIndex (bit)] &= ~bitToMask (bit); } void BigInteger::setRange (int startBit, int numBits, const bool shouldBeSet) { while (--numBits >= 0) setBit (startBit++, shouldBeSet); } void BigInteger::insertBit (const int bit, const bool shouldBeSet) { if (bit >= 0) shiftBits (1, bit); setBit (bit, shouldBeSet); } //============================================================================== bool BigInteger::isZero() const noexcept { return getHighestBit() < 0; } bool BigInteger::isOne() const noexcept { return getHighestBit() == 0 && ! negative; } bool BigInteger::isNegative() const noexcept { return negative && ! isZero(); } void BigInteger::setNegative (const bool neg) noexcept { negative = neg; } void BigInteger::negate() noexcept { negative = (! negative) && ! isZero(); } #if JUCE_USE_INTRINSICS && ! defined (__INTEL_COMPILER) #pragma intrinsic (_BitScanReverse) #endif namespace BitFunctions { inline int countBitsInInt32 (uint32 n) noexcept { n -= ((n >> 1) & 0x55555555); n = (((n >> 2) & 0x33333333) + (n & 0x33333333)); n = (((n >> 4) + n) & 0x0f0f0f0f); n += (n >> 8); n += (n >> 16); return (int) (n & 0x3f); } inline int highestBitInInt (uint32 n) noexcept { jassert (n != 0); // (the built-in functions may not work for n = 0) #if JUCE_GCC return 31 - __builtin_clz (n); #elif JUCE_USE_INTRINSICS unsigned long highest; _BitScanReverse (&highest, n); return (int) highest; #else n |= (n >> 1); n |= (n >> 2); n |= (n >> 4); n |= (n >> 8); n |= (n >> 16); return countBitsInInt32 (n >> 1); #endif } } int BigInteger::countNumberOfSetBits() const noexcept { int total = 0; for (int i = (int) bitToIndex (highestBit) + 1; --i >= 0;) total += BitFunctions::countBitsInInt32 (values[i]); return total; } int BigInteger::getHighestBit() const noexcept { for (int i = (int) bitToIndex (highestBit + 1); i >= 0; --i) { const uint32 n = values[i]; if (n != 0) return BitFunctions::highestBitInInt (n) + (i << 5); } return -1; } int BigInteger::findNextSetBit (int i) const noexcept { for (; i <= highestBit; ++i) if ((values [bitToIndex (i)] & bitToMask (i)) != 0) return i; return -1; } int BigInteger::findNextClearBit (int i) const noexcept { for (; i <= highestBit; ++i) if ((values [bitToIndex (i)] & bitToMask (i)) == 0) break; return i; } //============================================================================== BigInteger& BigInteger::operator+= (const BigInteger& other) { if (other.isNegative()) return operator-= (-other); if (isNegative()) { if (compareAbsolute (other) < 0) { BigInteger temp (*this); temp.negate(); *this = other; operator-= (temp); } else { negate(); operator-= (other); negate(); } } else { if (other.highestBit > highestBit) highestBit = other.highestBit; ++highestBit; const size_t numInts = bitToIndex (highestBit) + 1; ensureSize (numInts); int64 remainder = 0; for (size_t i = 0; i <= numInts; ++i) { if (i < numValues) remainder += values[i]; if (i < other.numValues) remainder += other.values[i]; values[i] = (uint32) remainder; remainder >>= 32; } jassert (remainder == 0); highestBit = getHighestBit(); } return *this; } BigInteger& BigInteger::operator-= (const BigInteger& other) { if (other.isNegative()) return operator+= (-other); if (! isNegative()) { if (compareAbsolute (other) < 0) { BigInteger temp (other); swapWith (temp); operator-= (temp); negate(); return *this; } } else { negate(); operator+= (other); negate(); return *this; } const size_t numInts = bitToIndex (highestBit) + 1; const size_t maxOtherInts = bitToIndex (other.highestBit) + 1; int64 amountToSubtract = 0; for (size_t i = 0; i <= numInts; ++i) { if (i <= maxOtherInts) amountToSubtract += (int64) other.values[i]; if (values[i] >= amountToSubtract) { values[i] = (uint32) (values[i] - amountToSubtract); amountToSubtract = 0; } else { const int64 n = ((int64) values[i] + (((int64) 1) << 32)) - amountToSubtract; values[i] = (uint32) n; amountToSubtract = 1; } } return *this; } BigInteger& BigInteger::operator*= (const BigInteger& other) { BigInteger total; highestBit = getHighestBit(); const bool wasNegative = isNegative(); setNegative (false); for (int i = 0; i <= highestBit; ++i) { if (operator[](i)) { BigInteger n (other); n.setNegative (false); n <<= i; total += n; } } total.setNegative (wasNegative ^ other.isNegative()); swapWith (total); return *this; } void BigInteger::divideBy (const BigInteger& divisor, BigInteger& remainder) { jassert (this != &remainder); // (can't handle passing itself in to get the remainder) const int divHB = divisor.getHighestBit(); const int ourHB = getHighestBit(); if (divHB < 0 || ourHB < 0) { // division by zero remainder.clear(); clear(); } else { const bool wasNegative = isNegative(); swapWith (remainder); remainder.setNegative (false); clear(); BigInteger temp (divisor); temp.setNegative (false); int leftShift = ourHB - divHB; temp <<= leftShift; while (leftShift >= 0) { if (remainder.compareAbsolute (temp) >= 0) { remainder -= temp; setBit (leftShift); } if (--leftShift >= 0) temp >>= 1; } negative = wasNegative ^ divisor.isNegative(); remainder.setNegative (wasNegative); } } BigInteger& BigInteger::operator/= (const BigInteger& other) { BigInteger remainder; divideBy (other, remainder); return *this; } BigInteger& BigInteger::operator|= (const BigInteger& other) { // this operation doesn't take into account negative values.. jassert (isNegative() == other.isNegative()); if (other.highestBit >= 0) { ensureSize (bitToIndex (other.highestBit)); int n = (int) bitToIndex (other.highestBit) + 1; while (--n >= 0) values[n] |= other.values[n]; if (other.highestBit > highestBit) highestBit = other.highestBit; highestBit = getHighestBit(); } return *this; } BigInteger& BigInteger::operator&= (const BigInteger& other) { // this operation doesn't take into account negative values.. jassert (isNegative() == other.isNegative()); int n = (int) numValues; while (n > (int) other.numValues) values[--n] = 0; while (--n >= 0) values[n] &= other.values[n]; if (other.highestBit < highestBit) highestBit = other.highestBit; highestBit = getHighestBit(); return *this; } BigInteger& BigInteger::operator^= (const BigInteger& other) { // this operation will only work with the absolute values jassert (isNegative() == other.isNegative()); if (other.highestBit >= 0) { ensureSize (bitToIndex (other.highestBit)); int n = (int) bitToIndex (other.highestBit) + 1; while (--n >= 0) values[n] ^= other.values[n]; if (other.highestBit > highestBit) highestBit = other.highestBit; highestBit = getHighestBit(); } return *this; } BigInteger& BigInteger::operator%= (const BigInteger& divisor) { BigInteger remainder; divideBy (divisor, remainder); swapWith (remainder); return *this; } BigInteger& BigInteger::operator++() { return operator+= (1); } BigInteger& BigInteger::operator--() { return operator-= (1); } BigInteger BigInteger::operator++ (int) { const BigInteger old (*this); operator+= (1); return old; } BigInteger BigInteger::operator-- (int) { const BigInteger old (*this); operator-= (1); return old; } BigInteger BigInteger::operator-() const { BigInteger b (*this); b.negate(); return b; } BigInteger BigInteger::operator+ (const BigInteger& other) const { BigInteger b (*this); return b += other; } BigInteger BigInteger::operator- (const BigInteger& other) const { BigInteger b (*this); return b -= other; } BigInteger BigInteger::operator* (const BigInteger& other) const { BigInteger b (*this); return b *= other; } BigInteger BigInteger::operator/ (const BigInteger& other) const { BigInteger b (*this); return b /= other; } BigInteger BigInteger::operator| (const BigInteger& other) const { BigInteger b (*this); return b |= other; } BigInteger BigInteger::operator& (const BigInteger& other) const { BigInteger b (*this); return b &= other; } BigInteger BigInteger::operator^ (const BigInteger& other) const { BigInteger b (*this); return b ^= other; } BigInteger BigInteger::operator% (const BigInteger& other) const { BigInteger b (*this); return b %= other; } BigInteger BigInteger::operator<< (const int numBits) const { BigInteger b (*this); return b <<= numBits; } BigInteger BigInteger::operator>> (const int numBits) const { BigInteger b (*this); return b >>= numBits; } BigInteger& BigInteger::operator<<= (const int numBits) { shiftBits (numBits, 0); return *this; } BigInteger& BigInteger::operator>>= (const int numBits) { shiftBits (-numBits, 0); return *this; } //============================================================================== int BigInteger::compare (const BigInteger& other) const noexcept { if (isNegative() == other.isNegative()) { const int absComp = compareAbsolute (other); return isNegative() ? -absComp : absComp; } else { return isNegative() ? -1 : 1; } } int BigInteger::compareAbsolute (const BigInteger& other) const noexcept { const int h1 = getHighestBit(); const int h2 = other.getHighestBit(); if (h1 > h2) return 1; else if (h1 < h2) return -1; for (int i = (int) bitToIndex (h1) + 1; --i >= 0;) if (values[i] != other.values[i]) return (values[i] > other.values[i]) ? 1 : -1; return 0; } bool BigInteger::operator== (const BigInteger& other) const noexcept { return compare (other) == 0; } bool BigInteger::operator!= (const BigInteger& other) const noexcept { return compare (other) != 0; } bool BigInteger::operator< (const BigInteger& other) const noexcept { return compare (other) < 0; } bool BigInteger::operator<= (const BigInteger& other) const noexcept { return compare (other) <= 0; } bool BigInteger::operator> (const BigInteger& other) const noexcept { return compare (other) > 0; } bool BigInteger::operator>= (const BigInteger& other) const noexcept { return compare (other) >= 0; } //============================================================================== void BigInteger::shiftLeft (int bits, const int startBit) { if (startBit > 0) { for (int i = highestBit + 1; --i >= startBit;) setBit (i + bits, operator[] (i)); while (--bits >= 0) clearBit (bits + startBit); } else { ensureSize (bitToIndex (highestBit + bits) + 1); const size_t wordsToMove = bitToIndex (bits); size_t top = 1 + bitToIndex (highestBit); highestBit += bits; if (wordsToMove > 0) { for (int i = (int) top; --i >= 0;) values [(size_t) i + wordsToMove] = values [i]; for (size_t j = 0; j < wordsToMove; ++j) values [j] = 0; bits &= 31; } if (bits != 0) { const int invBits = 32 - bits; for (size_t i = top + 1 + wordsToMove; --i > wordsToMove;) values[i] = (values[i] << bits) | (values [i - 1] >> invBits); values [wordsToMove] = values [wordsToMove] << bits; } highestBit = getHighestBit(); } } void BigInteger::shiftRight (int bits, const int startBit) { if (startBit > 0) { for (int i = startBit; i <= highestBit; ++i) setBit (i, operator[] (i + bits)); highestBit = getHighestBit(); } else { if (bits > highestBit) { clear(); } else { const size_t wordsToMove = bitToIndex (bits); size_t top = 1 + bitToIndex (highestBit) - wordsToMove; highestBit -= bits; if (wordsToMove > 0) { size_t i; for (i = 0; i < top; ++i) values [i] = values [i + wordsToMove]; for (i = 0; i < wordsToMove; ++i) values [top + i] = 0; bits &= 31; } if (bits != 0) { const int invBits = 32 - bits; --top; for (size_t i = 0; i < top; ++i) values[i] = (values[i] >> bits) | (values [i + 1] << invBits); values[top] = (values[top] >> bits); } highestBit = getHighestBit(); } } } void BigInteger::shiftBits (int bits, const int startBit) { if (highestBit >= 0) { if (bits < 0) shiftRight (-bits, startBit); else if (bits > 0) shiftLeft (bits, startBit); } } //============================================================================== static BigInteger simpleGCD (BigInteger* m, BigInteger* n) { while (! m->isZero()) { if (n->compareAbsolute (*m) > 0) std::swap (m, n); *m -= *n; } return *n; } BigInteger BigInteger::findGreatestCommonDivisor (BigInteger n) const { BigInteger m (*this); while (! n.isZero()) { if (abs (m.getHighestBit() - n.getHighestBit()) <= 16) return simpleGCD (&m, &n); BigInteger temp2; m.divideBy (n, temp2); m.swapWith (n); n.swapWith (temp2); } return m; } void BigInteger::exponentModulo (const BigInteger& exponent, const BigInteger& modulus) { BigInteger exp (exponent); exp %= modulus; BigInteger value (1); swapWith (value); value %= modulus; while (! exp.isZero()) { if (exp [0]) { operator*= (value); operator%= (modulus); } value *= value; value %= modulus; exp >>= 1; } } void BigInteger::inverseModulo (const BigInteger& modulus) { if (modulus.isOne() || modulus.isNegative()) { clear(); return; } if (isNegative() || compareAbsolute (modulus) >= 0) operator%= (modulus); if (isOne()) return; if (! (*this)[0]) { // not invertible clear(); return; } BigInteger a1 (modulus); BigInteger a2 (*this); BigInteger b1 (modulus); BigInteger b2 (1); while (! a2.isOne()) { BigInteger temp1, multiplier (a1); multiplier.divideBy (a2, temp1); temp1 = a2; temp1 *= multiplier; BigInteger temp2 (a1); temp2 -= temp1; a1 = a2; a2 = temp2; temp1 = b2; temp1 *= multiplier; temp2 = b1; temp2 -= temp1; b1 = b2; b2 = temp2; } while (b2.isNegative()) b2 += modulus; b2 %= modulus; swapWith (b2); } //============================================================================== OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const BigInteger& value) { return stream << value.toString (10); } String BigInteger::toString (const int base, const int minimumNumCharacters) const { String s; BigInteger v (*this); if (base == 2 || base == 8 || base == 16) { const int bits = (base == 2) ? 1 : (base == 8 ? 3 : 4); static const char hexDigits[] = "0123456789abcdef"; for (;;) { const uint32 remainder = v.getBitRangeAsInt (0, bits); v >>= bits; if (remainder == 0 && v.isZero()) break; s = String::charToString ((juce_wchar) (uint8) hexDigits [remainder]) + s; } } else if (base == 10) { const BigInteger ten (10); BigInteger remainder; for (;;) { v.divideBy (ten, remainder); if (remainder.isZero() && v.isZero()) break; s = String (remainder.getBitRangeAsInt (0, 8)) + s; } } else { jassertfalse; // can't do the specified base! return String::empty; } s = s.paddedLeft ('0', minimumNumCharacters); return isNegative() ? "-" + s : s; } void BigInteger::parseString (const String& text, const int base) { clear(); String::CharPointerType t (text.getCharPointer()); if (base == 2 || base == 8 || base == 16) { const int bits = (base == 2) ? 1 : (base == 8 ? 3 : 4); for (;;) { const juce_wchar c = t.getAndAdvance(); const int digit = CharacterFunctions::getHexDigitValue (c); if (((uint32) digit) < (uint32) base) { operator<<= (bits); operator+= (digit); } else if (c == 0) { break; } } } else if (base == 10) { const BigInteger ten ((uint32) 10); for (;;) { const juce_wchar c = t.getAndAdvance(); if (c >= '0' && c <= '9') { operator*= (ten); operator+= ((int) (c - '0')); } else if (c == 0) { break; } } } setNegative (text.trimStart().startsWithChar ('-')); } MemoryBlock BigInteger::toMemoryBlock() const { const int numBytes = (getHighestBit() + 8) >> 3; MemoryBlock mb ((size_t) numBytes); for (int i = 0; i < numBytes; ++i) mb[i] = (char) getBitRangeAsInt (i << 3, 8); return mb; } void BigInteger::loadFromMemoryBlock (const MemoryBlock& data) { clear(); for (int i = (int) data.getSize(); --i >= 0;) this->setBitRangeAsInt (i << 3, 8, (uint32) data [i]); }