12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028 |
- /*
- ==============================================================================
- This file is part of the juce_core module of the JUCE library.
- Copyright (c) 2013 - Raw Material Software Ltd.
- Permission to use, copy, modify, and/or distribute this software for any purpose with
- or without fee is hereby granted, provided that the above copyright notice and this
- permission notice appear in all copies.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
- TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
- NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
- IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- ------------------------------------------------------------------------------
- NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
- All other JUCE modules are covered by a dual GPL/commercial license, so if you are
- using any other modules, be sure to check that you also comply with their license.
- For more details, visit www.juce.com
- ==============================================================================
- */
- 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 <HeapBlock <uint32>&&> (other.values)),
- numValues (other.numValues),
- highestBit (other.highestBit),
- negative (other.negative)
- {
- }
- BigInteger& BigInteger::operator= (BigInteger&& other) noexcept
- {
- values = static_cast <HeapBlock <uint32>&&> (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;
- }
- int64 BigInteger::toInt64() const noexcept
- {
- const int64 n = (((int64) (values[1] & 0x7fffffff)) << 32) | values[0];
- 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();
- }
- s = s.paddedLeft ('0', minimumNumCharacters);
- return isNegative() ? "-" + s : s;
- }
- void BigInteger::parseString (StringRef text, const int base)
- {
- clear();
- String::CharPointerType t (text.text.findEndOfWhitespace());
- setNegative (*t == (juce_wchar) '-');
- 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;
- }
- }
- }
- }
- 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]);
- }
|