commonMain.org.gciatto.kt.math.BigInteger.kt Maven / Gradle / Ivy
/*
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* Portions Copyright (c) 1995 Colin Plumb. All rights reserved.
*/
package org.gciatto.kt.math
import kotlin.experimental.and
import kotlin.js.JsName
import kotlin.math.*
import kotlin.random.Random
/**
* Immutable arbitrary-precision integers. All operations behave as if
* BigIntegers were represented in two's-complement notation (like Java's
* primitive integer types). BigInteger provides analogues to all of Java's
* primitive integer operators, and all relevant methods from `kotlin.math`.
* Additionally, BigInteger provides operations for modular arithmetic, GCD
* calculation, primality testing, prime generation, bit manipulation,
* and a few other miscellaneous operations.
*
*
* Semantics of arithmetic operations exactly mimic those of Java's integer
* arithmetic operators, as defined in *The Java Language Specification*.
* For example, division by zero throws an `ArithmeticException`, and
* division of a negative by a positive yields a negative (or zero) remainder.
* All of the details in the Spec concerning overflow are ignored, as
* BigIntegers are made as large as necessary to accommodate the results of an
* operation.
*
*
* Semantics of shift operations extend those of Java's shift operators
* to allow for negative shift distances. A right-shift with a negative
* shift distance results in a left shift, and vice-versa. The unsigned
* right shift operator (`>>>`) is omitted, as this operation makes
* little sense in combination with the "infinite word size" abstraction
* provided by this class.
*
*
* Semantics of bitwise logical operations exactly mimic those of Java's
* bitwise integer operators. The binary operators (`and`,
* `or`, `xor`) implicitly perform sign extension on the shorter
* of the two operands prior to performing the operation.
*
*
* Comparison operations perform signed integer comparisons, analogous to
* those performed by Java's relational and equality operators.
*
*
* Modular arithmetic operations are provided to compute residues, perform
* exponentiation, and compute multiplicative inverses. These methods always
* return a non-negative result, between `0` and `(modulus - 1)`,
* inclusive.
*
*
* Bit operations operate on a single bit of the two's-complement
* representation of their operand. If necessary, the operand is sign-
* extended so that it contains the designated bit. None of the single-bit
* operations can produce a BigInteger with a different sign from the
* BigInteger being operated on, as they affect only a single bit, and the
* "infinite word size" abstraction provided by this class ensures that there
* are infinitely many "virtual sign bits" preceding each BigInteger.
*
*
* For the sake of brevity and clarity, pseudo-code is used throughout the
* descriptions of BigInteger methods. The pseudo-code expression
* `(i + j)` is shorthand for "a BigInteger whose value is
* that of the BigInteger `i` plus that of the BigInteger `j`."
* The pseudo-code expression `(i == j)` is shorthand for
* "`true` if and only if the BigInteger `i` represents the same
* value as the BigInteger `j`." Other pseudo-code expressions are
* interpreted similarly.
*
*
* All methods and constructors in this class throw
* `NullPointerException` when passed
* a null object reference for any input parameter.
*
* BigInteger must support values in the range
* -2`Int.MAX_VALUE` (exclusive) to
* +2`Int.MAX_VALUE` (exclusive)
* and may support values outside of that range.
*
* The range of probable prime values is limited and may be less than
* the full supported positive range of `BigInteger`.
* The range must be at least 1 to 2500000000.
*
* @implNote
* BigInteger constructors and operations throw `ArithmeticException` when
* the result is out of the supported range of
* -2`Int.MAX_VALUE` (exclusive) to
* +2`Int.MAX_VALUE` (exclusive).
*
* @see BigDecimal
*
* @jls 4.2.2 Integer Operations
* @author Josh Bloch
* @author Michael McCloskey
* @author Alan Eliasen
* @author Timothy Buktu
* @since 1.1
*/
@Suppress("NAME_SHADOWING", "VARIABLE_WITH_REDUNDANT_INITIALIZER")
class BigInteger : Comparable {
/**
* The _signum of this BigInteger: -1 for negative, 0 for zero, or
* 1 for positive. Note that the BigInteger zero *must* have
* a _signum of 0. This is necessary to ensures that there is exactly one
* representation for each BigInteger value.
*/
internal val _signum: Int
/**d
* The magnitude of this BigInteger, in *big-endian* order: the
* zeroth element of this array is the most-significant int of the
* magnitude. The magnitude must be "minimal" in that the most-significant
* int (`_mag[0]`) must be non-zero. This is necessary to
* ensure that there is exactly one representation for each BigInteger
* value. Note that this implies that the BigInteger zero has a
* zero-length _mag array.
*/
internal val _mag: IntArray
// The following fields are stable variables. A stable variable's value
// changes at most once from the default zero value to a non-zero stable
// value. A stable value is calculated lazily on demand.
/**
* One plus the bitCount of this BigInteger. This is a stable variable.
*
* @see .bitCount
*/
private var _bitCountPlusOne: Int = 0
/**
* One plus the bitLength of this BigInteger. This is a stable variable.
* (either value is acceptable).
*
* @see .bitLength
*/
private var _bitLengthPlusOne: Int = 0
/**
* Two plus the lowest set bit of this BigInteger. This is a stable variable.
*
* @see .getLowestSetBit
*/
private var _lowestSetBitPlusTwo: Int = 0
/**
* Two plus the index of the lowest-order int in the magnitude of this
* BigInteger that contains a nonzero int. This is a stable variable. The
* least significant int has int-number 0, the next int in order of
* increasing significance has int-number 1, and so forth.
*
*
* Note: never used for a BigInteger with a magnitude of zero.
*
* @see .firstNonzeroIntNum
*/
private var _firstNonzeroIntNumPlusTwo: Int = 0
/**
* Returns the index of the rightmost (lowest-order) one bit in this
* BigInteger (the number of zero bits to the right of the rightmost
* one bit). Returns -1 if this BigInteger contains no one bits.
* (Computes `(this == 0? -1 : log2(this & -this))`.)
*
* @return index of the rightmost one bit in this BigInteger.
*/
// lowestSetBit not initialized yet
// Search for lowest order nonzero int
private val lowestSetBit: Int
get() {
var lsb = _lowestSetBitPlusTwo - 2
if (lsb == -2) {
lsb = 0
if (_signum == 0) {
lsb -= 1
} else {
var i: Int
var b: Int
i = 0
b = getInt(i)
while (b == 0) {
i++
b = getInt(i)
}
lsb += (i shl 5) + b.numberOfTrailingZeros()
}
_lowestSetBitPlusTwo = lsb + 2
}
return lsb
}
// Constructors
/**
* Translates a byte sub-array containing the two's-complement binary
* representation of a BigInteger into a BigInteger. The sub-array is
* specified via an offset into the array and a length. The sub-array is
* assumed to be in *big-endian* byte-order: the most significant
* byte is the element at index `off`. The `val` array is
* assumed to be unchanged for the duration of the constructor call.
*
* An `IndexOutOfBoundsException` is thrown if the length of the array
* `val` is non-zero and either `off` is negative, `len`
* is negative, or `off+len` is greater than the length of
* `val`.
*
* @param val byte array containing a sub-array which is the big-endian
* two's-complement binary representation of a BigInteger.
* @param off the start offset of the binary representation.
* @param len the number of bytes to use.
* @throws NumberFormatException `val` is zero bytes long.
* @throws IndexOutOfBoundsException if the provided array offset and
* length would cause an index into the byte array to be
* negative or greater than or equal to the array length.
* @since 9
*/
constructor(`val`: ByteArray, off: Int = 0, len: Int = `val`.size) {
if (`val`.size == 0) {
throw NumberFormatException("Zero length BigInteger")
} else if (off < 0 || off >= `val`.size || len < 0 ||
len > `val`.size - off
) { // 0 <= off < val.length
throw IndexOutOfBoundsException()
}
if (`val`[off] < 0) {
_mag = makePositive(`val`, off, len)
_signum = -1
} else {
_mag = stripLeadingZeroBytes(`val`, off, len)
_signum = if (_mag.size == 0) 0 else 1
}
if (_mag.size >= MAX_MAG_LENGTH) {
checkRange()
}
}
/**
* This private constructor translates an int array containing the
* two's-complement binary representation of a BigInteger into a
* BigInteger. The input array is assumed to be in *big-endian*
* int-order: the most significant int is in the zeroth element. The
* `val` array is assumed to be unchanged for the duration of
* the constructor call.
*/
private constructor(`val`: IntArray) {
if (`val`.size == 0)
throw NumberFormatException("Zero length BigInteger")
if (`val`[0] < 0) {
_mag = makePositive(`val`)
_signum = -1
} else {
_mag = trustedStripLeadingZeroInts(`val`)
_signum = if (_mag.size == 0) 0 else 1
}
if (_mag.size >= MAX_MAG_LENGTH) {
checkRange()
}
}
/**
* Translates the sign-magnitude representation of a BigInteger into a
* BigInteger. The sign is represented as an integer _signum value: -1 for
* negative, 0 for zero, or 1 for positive. The magnitude is a sub-array of
* a byte array in *big-endian* byte-order: the most significant byte
* is the element at index `off`. A zero value of the length
* `len` is permissible, and will result in a BigInteger value of 0,
* whether _signum is -1, 0 or 1. The `magnitude` array is assumed to
* be unchanged for the duration of the constructor call.
*
* An `IndexOutOfBoundsException` is thrown if the length of the array
* `magnitude` is non-zero and either `off` is negative,
* `len` is negative, or `off+len` is greater than the length of
* `magnitude`.
*
* @param signum _signum of the number (-1 for negative, 0 for zero, 1
* for positive).
* @param magnitude big-endian binary representation of the magnitude of
* the number.
* @param off the start offset of the binary representation.
* @param len the number of bytes to use.
* @throws NumberFormatException `_signum` is not one of the three
* legal values (-1, 0, and 1), or `_signum` is 0 and
* `magnitude` contains one or more non-zero bytes.
* @throws IndexOutOfBoundsException if the provided array offset and
* length would cause an index into the byte array to be
* negative or greater than or equal to the array length.
* @since 9
*/
constructor(signum: Int, magnitude: ByteArray, off: Int = 0, len: Int = magnitude.size) {
if (signum < -1 || signum > 1) {
throw NumberFormatException("Invalid _signum value")
} else if (off < 0 || len < 0 ||
len > 0 && (off >= magnitude.size || len > magnitude.size - off)
) { // 0 <= off < magnitude.length
throw IndexOutOfBoundsException()
}
// stripLeadingZeroBytes() returns a zero length array if len == 0
this._mag = stripLeadingZeroBytes(magnitude, off, len)
if (this._mag.size == 0) {
this._signum = 0
} else {
if (signum == 0)
throw NumberFormatException("_signum-magnitude mismatch")
this._signum = signum
}
if (_mag.size >= MAX_MAG_LENGTH) {
checkRange()
}
}
/**
* A constructor for internal use that translates the sign-magnitude
* representation of a BigInteger into a BigInteger. It checks the
* arguments and copies the magnitude so this constructor would be
* safe for external use. The `magnitude` array is assumed to be
* unchanged for the duration of the constructor call.
*/
private constructor(signum: Int, magnitude: IntArray) {
this._mag = stripLeadingZeroInts(magnitude)
if (signum < -1 || signum > 1)
throw NumberFormatException("Invalid _signum value")
if (this._mag.size == 0) {
this._signum = 0
} else {
if (signum == 0)
throw NumberFormatException("_signum-magnitude mismatch")
this._signum = signum
}
if (_mag.size >= MAX_MAG_LENGTH) {
checkRange()
}
}
/**
* Translates the String representation of a BigInteger in the
* specified radix into a BigInteger. The String representation
* consists of an optional subtract or plus sign followed by a
* sequence of one or more digits in the specified radix. The
* character-to-digit mapping is provided by `Character.digit`. The String may not contain any extraneous
* characters (whitespace, for example).
*
* @param val String representation of BigInteger.
* @param radix radix to be used in interpreting `val`.
* @throws NumberFormatException `val` is not a valid representation
* of a BigInteger in the specified radix, or `radix` is
* outside the range from [CHAR_MIN_RADIX] to
* [CHAR_MAX_RADIX], inclusive.
* @see Character.digit
*/
constructor(`val`: String, radix: Int = 10) {
var cursor = 0
val numDigits: Int
val len = `val`.length
if (radix < CHAR_MIN_RADIX || radix > CHAR_MAX_RADIX)
throw NumberFormatException("Radix out of range")
if (len == 0)
throw NumberFormatException("Zero length BigInteger")
// Check for at most one leading sign
var sign = 1
val index1 = `val`.lastIndexOf('-')
val index2 = `val`.lastIndexOf('+')
if (index1 >= 0) {
if (index1 != 0 || index2 >= 0) {
throw NumberFormatException("Illegal embedded sign character")
}
sign = -1
cursor = 1
} else if (index2 >= 0) {
if (index2 != 0) {
throw NumberFormatException("Illegal embedded sign character")
}
cursor = 1
}
if (cursor == len)
throw NumberFormatException("Zero length BigInteger")
// Skip leading zeros and compute number of digits in magnitude
while (cursor < len && `val`[cursor].toDigit(radix) == 0) {
cursor++
}
if (cursor == len) {
_signum = 0
_mag = ZERO._mag
return
}
numDigits = len - cursor
_signum = sign
// Pre-allocate array of expected size. May be too large but can
// never be too small. Typically exact.
val numBits = (numDigits * bitsPerDigit[radix]).ushr(10) + 1
if (numBits + 31 >= 1L shl 32) {
reportOverflow()
}
val numWords = (numBits + 31).toInt().ushr(5)
val magnitude = IntArray(numWords)
// Process first (potentially short) digit group
var firstGroupLen = numDigits % digitsPerInt[radix]
if (firstGroupLen == 0)
firstGroupLen = digitsPerInt[radix]
var group = `val`.substring(cursor, cursor + firstGroupLen)
cursor += firstGroupLen
magnitude[numWords - 1] = group.toInt(radix)
if (magnitude[numWords - 1] < 0)
throw NumberFormatException("Illegal digit")
// Process remaining digit groups
val superRadix = intRadix[radix]
var groupVal = 0
while (cursor < len) {
group = `val`.substring(cursor, cursor + digitsPerInt[radix])
cursor += digitsPerInt[radix]
groupVal = group.toInt(radix)
if (groupVal < 0)
throw NumberFormatException("Illegal digit")
destructiveMulAdd(magnitude, superRadix, groupVal)
}
// Required for cases where the array was overallocated.
_mag = trustedStripLeadingZeroInts(magnitude)
if (_mag.size >= MAX_MAG_LENGTH) {
checkRange()
}
}
/*
* Constructs a new BigInteger using a char array with radix=10.
* Sign is precalculated outside and not allowed in the val. The {@code val}
* array is assumed to be unchanged for the duration of the constructor
* call.
*/
internal constructor(`val`: CharArray, sign: Int, len: Int) {
var cursor = 0
val numDigits: Int
// Skip leading zeros and compute number of digits in magnitude
while (cursor < len && `val`[cursor].toDigit(10) == 0) {
cursor++
}
if (cursor == len) {
_signum = 0
_mag = ZERO._mag
return
}
numDigits = len - cursor
_signum = sign
// Pre-allocate array of expected size
val numWords: Int
if (len < 10) {
numWords = 1
} else {
val numBits = (numDigits * bitsPerDigit[10]).ushr(10) + 1
if (numBits + 31 >= 1L shl 32) {
reportOverflow()
}
numWords = (numBits + 31).toInt().ushr(5)
}
val magnitude = IntArray(numWords)
// Process first (potentially short) digit group
var firstGroupLen = numDigits % digitsPerInt[10]
if (firstGroupLen == 0)
firstGroupLen = digitsPerInt[10]
magnitude[numWords - 1] = parseInt(`val`, cursor, cursor + firstGroupLen)
cursor += firstGroupLen
// Process remaining digit groups
while (cursor < len) {
val groupVal = parseInt(`val`, cursor, cursor + digitsPerInt[10])
cursor += digitsPerInt[10]
destructiveMulAdd(
magnitude,
intRadix[10],
groupVal
)
}
_mag = trustedStripLeadingZeroInts(magnitude)
if (_mag.size >= MAX_MAG_LENGTH) {
checkRange()
}
}
// Create an integer with the digits between the two indexes
// Assumes start < end. The result may be negative, but it
// is to be treated as an unsigned value.
private fun parseInt(source: CharArray, start: Int, end: Int): Int {
var result = source[start].toDigit(10)
if (result == -1)
throw NumberFormatException(source.concatToString())
for (index in (start + 1) until end) {
val nextVal = source[index].toDigit(10)
if (nextVal == -1)
throw NumberFormatException(source.concatToString())
result = 10 * result + nextVal
}
return result
}
/**
* Constructs a randomly generated BigInteger, uniformly distributed over
* the range 0 to (2`numBits` - 1), inclusive.
* The uniformity of the distribution assumes that a fair source of random
* bits is provided in `rnd`. Note that this constructor always
* constructs a non-negative BigInteger.
*
* @param numBits maximum bitLength of the new BigInteger.
* @param rnd source of randomness to be used in computing the new
* BigInteger.
* @throws IllegalArgumentException `numBits` is negative.
* @see .bitLength
*/
constructor(numBits: Int, rnd: Random) : this(1, randomBits(numBits, rnd)) {}
/**
* Constructs a randomly generated positive BigInteger that is probably
* prime, with the specified bitLength.
*
* @apiNote It is recommended that the [probablePrime][BigInteger.probablePrime]
* method be used in preference to this constructor unless there
* is a compelling need to specify a certainty.
*
* @param bitLength bitLength of the returned BigInteger.
* @param certainty a measure of the uncertainty that the caller is
* willing to tolerate. The probability that the new BigInteger
* represents a prime number will exceed
* (1 - 1/2`certainty`). The execution time of
* this constructor is proportional to the value of this parameter.
* @param rnd source of random bits used to select candidates to be
* tested for primality.
* @throws ArithmeticException `bitLength < 2` or `bitLength` is too large.
* @see .bitLength
*/
constructor(bitLength: Int, certainty: Int, rnd: Random) {
val prime: BigInteger
if (bitLength < 2)
throw ArithmeticException("bitLength < 2")
prime = if (bitLength < SMALL_PRIME_THRESHOLD)
smallPrime(bitLength, certainty, rnd)
else
largePrime(bitLength, certainty, rnd)
_signum = 1
_mag = prime._mag
}
/**
* Returns the first integer greater than this `BigInteger` that
* is probably prime. The probability that the number returned by this
* method is composite does not exceed 2-100. This method will
* never skip over a prime when searching: if it returns `p`, there
* is no prime `q` such that `this < q < p`.
*
* @return the first integer greater than this `BigInteger` that
* is probably prime.
* @throws ArithmeticException `this < 0` or `this` is too large.
* @since 1.5
*/
@Suppress("UNREACHABLE_CODE", "UNUSED_VARIABLE")
@JsName("nextProbablePrime")
fun nextProbablePrime(): BigInteger {
if (this._signum < 0)
throw ArithmeticException("start < 0: $this")
// Handle trivial cases
if (this._signum == 0 || this == ONE)
return TWO
var result = this.plus(ONE)
// Fastpath for small numbers
if (result.bitLength < SMALL_PRIME_THRESHOLD) {
// Ensure an odd number
if (!result.testBit(0))
result = result.plus(ONE)
while (true) {
// Do cheap "pre-test" if applicable
if (result.bitLength > 6) {
val r = result.remainder(SMALL_PRIME_PRODUCT).toLong()
if (r % 3 == 0L || r % 5 == 0L || r % 7 == 0L || r % 11 == 0L ||
r % 13 == 0L || r % 17 == 0L || r % 19 == 0L || r % 23 == 0L ||
r % 29 == 0L || r % 31 == 0L || r % 37 == 0L || r % 41 == 0L
) {
result = result.plus(TWO)
continue // Candidate is composite; try another
}
}
// All candidates of bitLength 2 and 3 are prime by this point
if (result.bitLength < 4)
return result
// The expensive test
if (result.primeToCertainty(DEFAULT_PRIME_CERTAINTY, null))
return result
result = result.plus(TWO)
}
}
// Start at previous even number
if (result.testBit(0))
result = result.minus(ONE)
// Looking for the next large prime
val searchLen = getPrimeSearchLen(result.bitLength)
while (true) {
val searchSieve = BitSieve(result, searchLen)
val candidate = searchSieve.retrieve(
result,
DEFAULT_PRIME_CERTAINTY, null!!
)
if (candidate != null)
return candidate
result = result.plus(of((2 * searchLen).toLong()))
}
}
/**
* Returns `true` if this BigInteger is probably prime,
* `false` if it's definitely composite.
*
* This method assumes bitLength > 2.
*
* @param certainty a measure of the uncertainty that the caller is
* willing to tolerate: if the call returns `true`
* the probability that this BigInteger is prime exceeds
* `(1 - 1/2certainty)`. The execution time of
* this method is proportional to the value of this parameter.
* @return `true` if this BigInteger is probably prime,
* `false` if it's definitely composite.
*/
internal fun primeToCertainty(certainty: Int, random: Random?): Boolean {
var rounds = 0
val n = (max(certainty, Int.MAX_VALUE - 1) + 1) / 2
// The relationship between the certainty and the number of rounds
// we perform is given in the draft standard ANSI X9.80, "PRIME
// NUMBER GENERATION, PRIMALITY TESTING, AND PRIMALITY CERTIFICATES".
val sizeInBits = this.bitLength
if (sizeInBits < 100) {
rounds = 50
rounds = if (n < rounds) n else rounds
return passesMillerRabin(rounds, random)
}
if (sizeInBits < 256) {
rounds = 27
} else if (sizeInBits < 512) {
rounds = 15
} else if (sizeInBits < 768) {
rounds = 8
} else if (sizeInBits < 1024) {
rounds = 4
} else {
rounds = 2
}
rounds = if (n < rounds) n else rounds
return passesMillerRabin(rounds, random) && passesLucasLehmer()
}
/**
* Returns true iff this BigInteger is a Lucas-Lehmer probable prime.
*
* The following assumptions are made:
* This BigInteger is a positive, odd number.
*/
private fun passesLucasLehmer(): Boolean {
val thisPlusOne = this.plus(ONE)
// Step 1
var d = 5
while (jacobiSymbol(d, this) != -1) {
// 5, -7, 9, -11, ...
d = if (d < 0) d.absoluteValue + 2 else -(d + 2)
}
// Step 2
val u = lucasLehmerSequence(d, thisPlusOne, this)
// Step 3
return u.rem(this) == ZERO
}
/**
* Returns true iff this BigInteger passes the specified number of
* Miller-Rabin tests. This test is taken from the DSA spec (NIST FIPS
* 186-2).
*
* The following assumptions are made:
* This BigInteger is a positive, odd number greater than 2.
* iterations<=50.
*/
private fun passesMillerRabin(iterations: Int, rnd: Random?): Boolean {
var rnd = rnd
// Find a and m such that m is odd and this == 1 + 2**a * m
val thisMinusOne = this.minus(ONE)
var m = thisMinusOne
val a = m.lowestSetBit
m = m.shr(a)
if (rnd == null)
rnd = Random.Default
// Do the tests
for (i in 0 until iterations) {
// Generate a uniform random on (1, this)
var b: BigInteger
do {
b = BigInteger(this.bitLength, rnd)
} while (b.compareTo(ONE) <= 0 || b.compareTo(this) >= 0)
var j = 0
var z = b.modPow(m, this)
while (!(j == 0 && z == ONE || z == thisMinusOne)) {
if (j > 0 && z == ONE || ++j == a)
return false
z = z.modPow(TWO, this)
}
}
return true
}
/**
* This internal constructor differs from its public cousin
* with the arguments reversed in two ways: it assumes that its
* arguments are correct, and it doesn't copy the magnitude array.
*/
internal constructor(magnitude: IntArray, signum: Int) {
this._signum = if (magnitude.size == 0) 0 else signum
this._mag = magnitude
if (_mag.size >= MAX_MAG_LENGTH) {
checkRange()
}
}
/**
* This private constructor is for internal use and assumes that its
* arguments are correct. The `magnitude` array is assumed to be
* unchanged for the duration of the constructor call.
*/
private constructor(magnitude: ByteArray, signum: Int) {
this._signum = if (magnitude.size == 0) 0 else signum
this._mag = stripLeadingZeroBytes(magnitude, 0, magnitude.size)
if (_mag.size >= MAX_MAG_LENGTH) {
checkRange()
}
}
/**
* Throws an `ArithmeticException` if the `BigInteger` would be
* out of the supported range.
*
* @throws ArithmeticException if `this` exceeds the supported range.
*/
private fun checkRange() {
if (_mag.size > MAX_MAG_LENGTH || _mag.size == MAX_MAG_LENGTH && _mag[0] < 0) {
reportOverflow()
}
}
/**
* Constructs a BigInteger with the specified value, which may not be zero.
*/
private constructor(`val`: Long) {
var `val` = `val`
if (`val` < 0) {
`val` = -`val`
_signum = -1
} else {
_signum = 1
}
val highWord = `val`.ushr(32).toInt()
if (highWord == 0) {
_mag = IntArray(1)
_mag[0] = `val`.toInt()
} else {
_mag = IntArray(2)
_mag[0] = highWord
_mag[1] = `val`.toInt()
}
}
// Arithmetic Operations
/**
* Returns a BigInteger whose value is `(this + val)`.
*
* @param val value to be added to this BigInteger.
* @return `this + val`
*/
@JsName("plus")
operator fun plus(`val`: BigInteger): BigInteger {
if (`val`._signum == 0)
return this
if (_signum == 0)
return `val`
if (`val`._signum == _signum)
return BigInteger(sum(_mag, `val`._mag), _signum)
val cmp = compareMagnitude(`val`)
if (cmp == 0)
return ZERO
var resultMag = if (cmp > 0)
subtract(_mag, `val`._mag)
else
subtract(`val`._mag, _mag)
resultMag = trustedStripLeadingZeroInts(resultMag)
return BigInteger(resultMag, if (cmp == _signum) 1 else -1)
}
/**
* Package private methods used by BigDecimal code to plus a BigInteger
* with a long. Assumes val is not equal to INFLATED.
*/
internal fun plusLong(`val`: Long): BigInteger {
if (`val` == 0L)
return this
if (_signum == 0)
return of(`val`)
if (`val`.sign == _signum)
return BigInteger(sum(_mag, `val`.absoluteValue), _signum)
val cmp = compareMagnitude(`val`)
if (cmp == 0)
return ZERO
var resultMag = if (cmp > 0) subtract(
_mag,
`val`.absoluteValue
) else subtract(`val`.absoluteValue, _mag)
resultMag = trustedStripLeadingZeroInts(resultMag)
return BigInteger(resultMag, if (cmp == _signum) 1 else -1)
}
/**
* Returns a BigInteger whose value is `(this - val)`.
*
* @param val value to be subtracted from this BigInteger.
* @return `this - val`
*/
@JsName("minus")
operator fun minus(`val`: BigInteger): BigInteger {
if (`val`._signum == 0)
return this
if (_signum == 0)
return `val`.unaryMinus()
if (`val`._signum != _signum)
return BigInteger(sum(_mag, `val`._mag), _signum)
val cmp = compareMagnitude(`val`)
if (cmp == 0)
return ZERO
var resultMag = if (cmp > 0)
subtract(_mag, `val`._mag)
else
subtract(`val`._mag, _mag)
resultMag = trustedStripLeadingZeroInts(resultMag)
return BigInteger(resultMag, if (cmp == _signum) 1 else -1)
}
/**
* Returns a BigInteger whose value is `(this * val)`.
*
* @implNote An implementation may offer better algorithmic
* performance when `val == this`.
*
* @param val value to be multiplied by this BigInteger.
* @return `this * val`
*/
@JsName("times")
operator fun times(`val`: BigInteger): BigInteger {
if (`val`._signum == 0 || _signum == 0)
return ZERO
val xlen = _mag.size
if (`val` === this && xlen > MULTIPLY_SQUARE_THRESHOLD) {
return square()
}
val ylen = `val`._mag.size
if (xlen < KARATSUBA_THRESHOLD || ylen < KARATSUBA_THRESHOLD) {
val resultSign = if (_signum == `val`._signum) 1 else -1
if (`val`._mag.size == 1) {
return multiplyByInt(_mag, `val`._mag[0], resultSign)
}
if (_mag.size == 1) {
return multiplyByInt(`val`._mag, _mag[0], resultSign)
}
var result = multiplyToLen(
_mag, xlen,
`val`._mag, ylen, null
)
result = trustedStripLeadingZeroInts(result)
return BigInteger(result, resultSign)
} else {
return if (xlen < TOOM_COOK_THRESHOLD && ylen < TOOM_COOK_THRESHOLD) {
multiplyKaratsuba(this, `val`)
} else {
multiplyToomCook3(this, `val`)
}
}
}
/**
* Package private methods used by BigDecimal code to timesLong a BigInteger
* with a long. Assumes v is not equal to INFLATED.
*/
internal fun timesLong(v: Long): BigInteger {
var v = v
if (v == 0L || _signum == 0)
return ZERO
if (v == BigDecimal.INFLATED)
return times(of(v))
val rsign = if (v > 0) _signum else -_signum
if (v < 0)
v = -v
val dh = v.ushr(32) // higher order bits
val dl = v and LONG_MASK // lower order bits
val xlen = _mag.size
val value = _mag
var rmag = if (dh == 0L) IntArray(xlen + 1) else IntArray(xlen + 2)
var carry: Long = 0
var rstart = rmag.size - 1
for (i in xlen - 1 downTo 0) {
val product = (value[i].toLong() and LONG_MASK) * dl + carry
rmag[rstart--] = product.toInt()
carry = product.ushr(32)
}
rmag[rstart] = carry.toInt()
if (dh != 0L) {
carry = 0
rstart = rmag.size - 2
for (i in xlen - 1 downTo 0) {
val product = (value[i].toLong()and LONG_MASK) * dh +
(rmag[rstart].toLong()and LONG_MASK) + carry
rmag[rstart--] = product.toInt()
carry = product.ushr(32)
}
rmag[0] = carry.toInt()
}
if (carry == 0L)
rmag = rmag.copyOfRange(1, rmag.size)
return BigInteger(rmag, rsign)
}
/**
* Returns a slice of a BigInteger for use in Toom-Cook multiplication.
*
* @param lowerSize The size of the lower-order bit slices.
* @param upperSize The size of the higher-order bit slices.
* @param slice The index of which slice is requested, which must be a
* number from 0 to size-1. Slice 0 is the highest-order bits, and slice
* size-1 are the lowest-order bits. Slice 0 may be of different size than
* the other slices.
* @param fullsize The size of the larger integer array, used to align
* slices to the appropriate position when multiplying different-sized
* numbers.
*/
private fun getToomSlice(
lowerSize: Int, upperSize: Int, slice: Int,
fullsize: Int
): BigInteger {
var start: Int
val end: Int
val sliceSize: Int
val len: Int
val offset: Int
len = _mag.size
offset = fullsize - len
if (slice == 0) {
start = 0 - offset
end = upperSize - 1 - offset
} else {
start = upperSize + (slice - 1) * lowerSize - offset
end = start + lowerSize - 1
}
if (start < 0) {
start = 0
}
if (end < 0) {
return ZERO
}
sliceSize = end - start + 1
if (sliceSize <= 0) {
return ZERO
}
// While performing Toom-Cook, all slices are positive and
// the sign is adjusted when the final number is composed.
if (start == 0 && sliceSize >= len) {
return this.absoluteValue
}
val intSlice = IntArray(sliceSize)
arrayCopy(_mag, start, intSlice, 0, sliceSize)
return BigInteger(trustedStripLeadingZeroInts(intSlice), 1)
}
/**
* Does an exact division (that is, the remainder is known to be zero)
* of the specified number by 3. This is used in Toom-Cook
* multiplication. This is an efficient algorithm that runs in linear
* time. If the argument is not exactly divisible by 3, results are
* undefined. Note that this is expected to be called with positive
* arguments only.
*/
private fun exactDivideBy3(): BigInteger {
val len = _mag.size
var result = IntArray(len)
var x: Long
var w: Long
var q: Long
var borrow: Long
borrow = 0L
for (i in len - 1 downTo 0) {
x = _mag[i].toLong()and LONG_MASK
w = x - borrow
if (borrow > x) { // Did we make the number go negative?
borrow = 1L
} else {
borrow = 0L
}
// 0xAAAAAAAB is the modular inverse of 3 (rem 2^32). Thus,
// the effect of this is to div by 3 (rem 2^32).
// This is much faster than division on most architectures.
q = w * 0xAAAAAAABL and LONG_MASK
result[i] = q.toInt()
// Now check the borrow. The second check can of course be
// eliminated if the first fails.
if (q >= 0x55555556L) {
borrow++
if (q >= 0xAAAAAAABL)
borrow++
}
}
result = trustedStripLeadingZeroInts(result)
return BigInteger(result, _signum)
}
/**
* Returns a new BigInteger representing n lower ints of the number.
* This is used by Karatsuba multiplication and Karatsuba squaring.
*/
private fun getLower(n: Int): BigInteger {
val len = _mag.size
if (len <= n) {
return absoluteValue
}
val lowerInts = IntArray(n)
arrayCopy(_mag, len - n, lowerInts, 0, n)
return BigInteger(trustedStripLeadingZeroInts(lowerInts), 1)
}
/**
* Returns a new BigInteger representing _mag.length-n upper
* ints of the number. This is used by Karatsuba multiplication and
* Karatsuba squaring.
*/
private fun getUpper(n: Int): BigInteger {
val len = _mag.size
if (len <= n) {
return ZERO
}
val upperLen = len - n
val upperInts = IntArray(upperLen)
arrayCopy(_mag, 0, upperInts, 0, upperLen)
return BigInteger(trustedStripLeadingZeroInts(upperInts), 1)
}
// Squaring
/**
* Returns a BigInteger whose value is `(this2)`.
*
* @return `this2`
*/
private fun square(): BigInteger {
if (_signum == 0) {
return ZERO
}
val len = _mag.size
if (len < KARATSUBA_SQUARE_THRESHOLD) {
val z = squareToLen(_mag, len, null)
return BigInteger(trustedStripLeadingZeroInts(z), 1)
} else {
return if (len < TOOM_COOK_SQUARE_THRESHOLD) {
squareKaratsuba()
} else {
squareToomCook3()
}
}
}
/**
* Squares a BigInteger using the Karatsuba squaring algorithm. It should
* be used when both numbers are larger than a certain threshold (found
* experimentally). It is a recursive div-and-conquer algorithm that
* has better asymptotic performance than the algorithm used in
* squareToLen.
*/
private fun squareKaratsuba(): BigInteger {
val half = (_mag.size + 1) / 2
val xl = getLower(half)
val xh = getUpper(half)
val xhs = xh.square() // xhs = xh^2
val xls = xl.square() // xls = xl^2
// xh^2 << 64 + (((xl+xh)^2 - (xh^2 + xl^2)) << 32) + xl^2
return xhs.shl(half * 32).plus(xl.plus(xh).square().minus(xhs.plus(xls))).shl(half * 32).plus(xls)
}
/**
* Squares a BigInteger using the 3-way Toom-Cook squaring algorithm. It
* should be used when both numbers are larger than a certain threshold
* (found experimentally). It is a recursive div-and-conquer algorithm
* that has better asymptotic performance than the algorithm used in
* squareToLen or squareKaratsuba.
*/
private fun squareToomCook3(): BigInteger {
val len = _mag.size
// k is the size (in ints) of the lower-order slices.
val k = (len + 2) / 3 // Equal to ceil(largest/3)
// r is the size (in ints) of the highest-order slice.
val r = len - 2 * k
// Obtain slices of the numbers. a2 is the most significant
// bits of the number, and a0 the least significant.
val a0: BigInteger
val a1: BigInteger
val a2: BigInteger
a2 = getToomSlice(k, r, 0, len)
a1 = getToomSlice(k, r, 1, len)
a0 = getToomSlice(k, r, 2, len)
val v0: BigInteger
val v1: BigInteger
val v2: BigInteger
val vm1: BigInteger
val vinf: BigInteger
var t1: BigInteger
var t2: BigInteger
var tm1: BigInteger
var da1: BigInteger
v0 = a0.square()
da1 = a2.plus(a0)
vm1 = da1.minus(a1).square()
da1 = da1.plus(a1)
v1 = da1.square()
vinf = a2.square()
v2 = da1.plus(a2).shl(1).minus(a0).square()
// The algorithm requires two divisions by 2 and one by 3.
// All divisions are known to be exact, that is, they do not produce
// remainders, and all results are positive. The divisions by 2 are
// implemented as right shifts which are relatively efficient, leaving
// only a division by 3.
// The division by 3 is done by an optimized algorithm for this case.
t2 = v2.minus(vm1).exactDivideBy3()
tm1 = v1.minus(vm1).shr(1)
t1 = v1.minus(v0)
t2 = t2.minus(t1).shr(1)
t1 = t1.minus(tm1).minus(vinf)
t2 = t2.minus(vinf.shl(1))
tm1 = tm1.minus(t2)
// Number of bits to shift left.
val ss = k * 32
return vinf.shl(ss).plus(t2).shl(ss).plus(t1).shl(ss).plus(tm1).shl(ss).plus(v0)
}
// Division
/**
* Returns a BigInteger whose value is `(this / val)`.
*
* @param val value by which this BigInteger is to be divided.
* @return `this / val`
* @throws ArithmeticException if `val` is zero.
*/
@JsName("div")
operator fun div(`val`: BigInteger): BigInteger {
return if (`val`._mag.size < BURNIKEL_ZIEGLER_THRESHOLD || _mag.size - `val`._mag.size < BURNIKEL_ZIEGLER_OFFSET) {
divideKnuth(`val`)
} else {
divideBurnikelZiegler(`val`)
}
}
/**
* Returns a BigInteger whose value is `(this / val)` using an O(n^2) algorithm from Knuth.
*
* @param val value by which this BigInteger is to be divided.
* @return `this / val`
* @throws ArithmeticException if `val` is zero.
* @see MutableBigInteger.divideKnuth
*/
private fun divideKnuth(`val`: BigInteger): BigInteger {
val q = MutableBigInteger()
val a = MutableBigInteger(this._mag)
val b = MutableBigInteger(`val`._mag)
a.divideKnuth(b, q, false)
return q.toBigInteger(this._signum * `val`._signum)
}
/**
* Returns an array of two BigIntegers containing `(this / val)`
* followed by `(this % val)`.
*
* @param val value by which this BigInteger is to be divided, and the
* remainder computed.
* @return an array of two BigIntegers: the quotient `(this / val)`
* is the initial element, and the remainder `(this % val)`
* is the final element.
* @throws ArithmeticException if `val` is zero.
*/
@JsName("divideAndRemainder")
fun divideAndRemainder(`val`: BigInteger): Array {
return if (`val`._mag.size < BURNIKEL_ZIEGLER_THRESHOLD || _mag.size - `val`._mag.size < BURNIKEL_ZIEGLER_OFFSET) {
divideAndRemainderKnuth(`val`)
} else {
divideAndRemainderBurnikelZiegler(`val`)
}
}
/** Long division */
private fun divideAndRemainderKnuth(`val`: BigInteger): Array {
// val result = arrayOfNulls(2)
val q = MutableBigInteger()
val a = MutableBigInteger(this._mag)
val b = MutableBigInteger(`val`._mag)
val r = a.divideKnuth(b, q)
return arrayOf(
q.toBigInteger(if (this._signum == `val`._signum) 1 else -1),
r!!.toBigInteger(this._signum)
)
// result[0] = q.toBigInteger(if (this._signum == `val`._signum) 1 else -1)
// result[1] = r!!.toBigInteger(this._signum)
// return result
}
/**
* Returns a BigInteger whose value is `(this % val)`.
*
* @param val value by which this BigInteger is to be divided, and the
* remainder computed.
* @return `this % val`
* @throws ArithmeticException if `val` is zero.
*/
@JsName("reminder")
fun remainder(`val`: BigInteger): BigInteger {
return if (`val`._mag.size < BURNIKEL_ZIEGLER_THRESHOLD || _mag.size - `val`._mag.size < BURNIKEL_ZIEGLER_OFFSET) {
remainderKnuth(`val`)
} else {
remainderBurnikelZiegler(`val`)
}
}
/** Long division */
private fun remainderKnuth(`val`: BigInteger): BigInteger {
val q = MutableBigInteger()
val a = MutableBigInteger(this._mag)
val b = MutableBigInteger(`val`._mag)
return a.divideKnuth(b, q)!!.toBigInteger(this._signum)
}
/**
* Calculates `this / val` using the Burnikel-Ziegler algorithm.
* @param val the divisor
* @return `this / val`
*/
private fun divideBurnikelZiegler(`val`: BigInteger): BigInteger {
return divideAndRemainderBurnikelZiegler(`val`)[0]
}
/**
* Calculates `this % val` using the Burnikel-Ziegler algorithm.
* @param val the divisor
* @return `this % val`
*/
private fun remainderBurnikelZiegler(`val`: BigInteger): BigInteger {
return divideAndRemainderBurnikelZiegler(`val`)[1]
}
/**
* Computes `this / val` and `this % val` using the
* Burnikel-Ziegler algorithm.
* @param val the divisor
* @return an array containing the quotient and remainder
*/
private fun divideAndRemainderBurnikelZiegler(`val`: BigInteger): Array {
val q = MutableBigInteger()
val r = MutableBigInteger(this)
.divideAndRemainderBurnikelZiegler(MutableBigInteger(`val`), q)
val qBigInt = if (q.isZero) ZERO else q.toBigInteger(_signum * `val`._signum)
val rBigInt = if (r.isZero) ZERO else r.toBigInteger(_signum)
return arrayOf(qBigInt, rBigInt)
}
/**
* Returns a BigInteger whose value is `(thisexponent)`.
* Note that `exponent` is an integer rather than a BigInteger.
*
* @param exponent exponent to which this BigInteger is to be raised.
* @return `thisexponent`
* @throws ArithmeticException `exponent` is negative. (This would
* cause the operation to yield a non-integer value.)
*/
@JsName("pow")
infix fun pow(exponent: Int): BigInteger {
if (exponent < 0) {
throw ArithmeticException("Negative exponent")
}
if (_signum == 0) {
return if (exponent == 0) ONE else this
}
var partToSquare = this.absoluteValue
// Factor out powers of two from the base, as the exponentiation of
// these can be done by left shifts only.
// The remaining part can then be exponentiated faster. The
// powers of two will be multiplied back at the end.
val powersOfTwo = partToSquare.lowestSetBit
val bitsToShift = powersOfTwo.toLong() * exponent
if (bitsToShift > Int.MAX_VALUE) {
reportOverflow()
}
val remainingBits: Int
// Factor the powers of two out quickly by shifting right, if needed.
if (powersOfTwo > 0) {
partToSquare = partToSquare.shr(powersOfTwo)
remainingBits = partToSquare.bitLength
if (remainingBits == 1) { // Nothing left but +/- 1?
return if (_signum < 0 && exponent and 1 == 1) {
NEGATIVE_ONE.shl(powersOfTwo * exponent)
} else {
ONE.shl(powersOfTwo * exponent)
}
}
} else {
remainingBits = partToSquare.bitLength
if (remainingBits == 1) { // Nothing left but +/- 1?
return if (_signum < 0 && exponent and 1 == 1) {
NEGATIVE_ONE
} else {
ONE
}
}
}
// This is a quick way to approximate the size of the result,
// similar to doing log2[n] * exponent. This will give an upper bound
// of how big the result can be, and which algorithm to use.
val scaleFactor = remainingBits.toLong() * exponent
// Use slightly different algorithms for small and large operands.
// See if the result will safely fit into a long. (Largest 2^63-1)
if (partToSquare._mag.size == 1 && scaleFactor <= 62) {
// Small number algorithm. Everything fits into a long.
val newSign = if (_signum < 0 && exponent and 1 == 1) -1 else 1
var result: Long = 1
var baseToPow2 = partToSquare._mag[0].toLong()and LONG_MASK
var workingExponent = exponent
// Perform exponentiation using repeated squaring trick
while (workingExponent != 0) {
if (workingExponent and 1 == 1) {
result = result * baseToPow2
}
workingExponent = workingExponent ushr 1
if (workingExponent != 0) {
baseToPow2 = baseToPow2 * baseToPow2
}
}
// Multiply back the powers of two (quickly, by shifting left)
return if (powersOfTwo > 0) {
if (bitsToShift + scaleFactor <= 62) { // Fits in long?
of((result shl bitsToShift.toInt()) * newSign)
} else {
of(result * newSign).shl(bitsToShift.toInt())
}
} else {
of(result * newSign)
}
} else {
// Large number algorithm. This is basically identical to
// the algorithm above, but calls timesLong() and square()
// which may use more efficient algorithms for large numbers.
var answer = ONE
var workingExponent = exponent
// Perform exponentiation using repeated squaring trick
while (workingExponent != 0) {
if (workingExponent and 1 == 1) {
answer = answer.times(partToSquare)
}
workingExponent = workingExponent ushr 1
if (workingExponent != 0) {
partToSquare = partToSquare.square()
}
}
// Multiply back the (exponentiated) powers of two (quickly,
// by shifting left)
if (powersOfTwo > 0) {
answer = answer.shl(powersOfTwo * exponent)
}
return if (_signum < 0 && exponent and 1 == 1) {
answer.unaryMinus()
} else {
answer
}
}
}
/**
* Returns the integer square root of this BigInteger. The integer square
* root of the corresponding mathematical integer `n` is the largest
* mathematical integer `s` such that `s*s <= n`. It is equal
* to the value of `floor(sqrt(n))`, where `sqrt(n)` denotes the
* real square root of `n` treated as a real. Note that the integer
* square root will be less than the real square root if the latter is not
* representable as an integral value.
*
* @return the integer square root of `this`
* @throws ArithmeticException if `this` is negative. (The square
* root of a negative integer `val` is
* `(i * sqrt(-val))` where *i* is the
* *imaginary unit* and is equal to
* `sqrt(-1)`.)
* @since 9
*/
@JsName("sqrt")
fun sqrt(): BigInteger {
if (this._signum < 0) {
throw ArithmeticException("Negative BigInteger")
}
return MutableBigInteger(this._mag).sqrt().toBigInteger()
}
/**
* Returns an array of two BigIntegers containing the integer square root
* `s` of `this` and its remainder `this - s*s`,
* respectively.
*
* @return an array of two BigIntegers with the integer square root at
* offset 0 and the remainder at offset 1
* @throws ArithmeticException if `this` is negative. (The square
* root of a negative integer `val` is
* `(i * sqrt(-val))` where *i* is the
* *imaginary unit* and is equal to
* `sqrt(-1)`.)
* @see .sqrt
* @since 9
*/
@JsName("sqrtAndRemainder")
fun sqrtAndRemainder(): Array {
val s = sqrt()
val r = this.minus(s.square())
require(r >= ZERO)
return arrayOf(s, r)
}
/**
* Returns a BigInteger whose value is the greatest common divisor of
* `absoluteValue(this)` and `absoluteValue(val)`. Returns 0 if
* `this == 0 && val == 0`.
*
* @param val value with which the GCD is to be computed.
* @return `GCD(absoluteValue(this), absoluteValue(val))`
*/
@JsName("gcd")
fun gcd(`val`: BigInteger): BigInteger {
if (`val`._signum == 0)
return this.absoluteValue
else if (this._signum == 0)
return `val`.absoluteValue
val a = MutableBigInteger(this)
val b = MutableBigInteger(`val`)
val result = a.hybridGCD(b)
return result.toBigInteger(1)
}
/**
* Returns a BigInteger whose value is the absolute value of this
* BigInteger.
*
* @return `absoluteValue(this)`
*/
val absoluteValue: BigInteger
get() {
return if (_signum >= 0) this else this.unaryMinus()
}
/**
* Returns a BigInteger whose value is `(-this)`.
*
* @return `-this`
*/
@JsName("unaryMinus")
operator fun unaryMinus(): BigInteger {
return BigInteger(this._mag, -this._signum)
}
@JsName("unaryPlus")
operator fun unaryPlus(): BigInteger {
return this
}
/**
* Returns the _signum function of this BigInteger.
*
* @return -1, 0 or 1 as the value of this BigInteger is negative, zero or
* positive.
*/
val signum: Int
get() {
return this._signum
}
// Modular Arithmetic Operations
/**
* Returns a BigInteger whose value is `(this rem m`). This method
* differs from `remainder` in that it always returns a
* *non-negative* BigInteger.
*
* @param m the modulus.
* @return `this rem m`
* @throws ArithmeticException `m` 0
* @see .remainder
*/
@JsName("rem")
operator fun rem(m: BigInteger): BigInteger {
if (m._signum <= 0)
throw ArithmeticException("BigInteger: modulus not positive")
val result = this.remainder(m)
return if (result._signum >= 0) result else result.plus(m)
}
/**
* Returns a BigInteger whose value is
* `(thisexponent rem m)`. (Unlike `pow`, this
* method permits negative exponents.)
*
* @param exponent the exponent.
* @param m the modulus.
* @return `thisexponent rem m`
* @throws ArithmeticException `m` 0 or the exponent is
* negative and this BigInteger is not *relatively
* prime* to `m`.
* @see .modInverse
*/
@JsName("modPow")
fun modPow(exponent: BigInteger, m: BigInteger): BigInteger {
var exponent = exponent
if (m._signum <= 0)
throw ArithmeticException("BigInteger: modulus not positive")
// Trivial cases
if (exponent._signum == 0)
return if (m == ONE) ZERO else ONE
if (this == ONE)
return if (m == ONE) ZERO else ONE
if (this == ZERO && exponent._signum >= 0)
return ZERO
if (this == negConst[1] && !exponent.testBit(0))
return if (m == ONE) ZERO else ONE
val invertResult: Boolean = exponent._signum < 0
if (invertResult)
exponent = exponent.unaryMinus()
val base = if (this._signum < 0 || this >= m)
this.rem(m)
else
this
val result: BigInteger
if (m.testBit(0)) { // odd modulus
result = base.oddModPow(exponent, m)
} else {
/*
* Even modulus. Tear it into an "odd part" (m1) and power of two
* (m2), exponentiate rem m1, manually exponentiate rem m2, and
* use Chinese Remainder Theorem to combine results.
*/
// Tear m apart into odd part (m1) and power of 2 (m2)
val p = m.lowestSetBit // Max pow of 2 that divides m
val m1 = m.shr(p) // m/2**p
val m2 = ONE.shl(p) // 2**p
// Calculate new base from m1
val base2 = if (this._signum < 0 || this.compareTo(m1) >= 0)
this.rem(m1)
else
this
// Caculate (base ** exponent) rem m1.
val a1 = if (m1 == ONE)
ZERO
else
base2.oddModPow(exponent, m1)
// Calculate (this ** exponent) rem m2
val a2 = base.modPow2(exponent, p)
// Combine results using Chinese Remainder Theorem
val y1 = m2.modInverse(m1)
val y2 = m1.modInverse(m2)
if (m._mag.size < MAX_MAG_LENGTH / 2) {
result = a1.times(m2).times(y1).plus(a2.times(m1).times(y2)).rem(m)
} else {
val t1 = MutableBigInteger()
MutableBigInteger(a1.times(m2)).multiply(MutableBigInteger(y1), t1)
val t2 = MutableBigInteger()
MutableBigInteger(a2.times(m1)).multiply(MutableBigInteger(y2), t2)
t1.add(t2)
val q = MutableBigInteger()
result = t1.divide(MutableBigInteger(m), q)!!.toBigInteger()
}
}
return if (invertResult) result.modInverse(m) else result
}
/**
* Returns a BigInteger whose value is x to the power of y rem z.
* Assumes: z is odd && x < z.
*/
private fun oddModPow(y: BigInteger, z: BigInteger): BigInteger {
/*
* The algorithm is adapted from Colin Plumb's C library.
*
* The window algorithm:
* The idea is to keep a running product of b1 = n^(high-order bits of exp)
* and then keep appending exponent bits to it. The following patterns
* apply to a 3-bit window (k = 3):
* To append 0: square
* To append 1: square, timesLong by n^1
* To append 10: square, timesLong by n^1, square
* To append 11: square, square, timesLong by n^3
* To append 100: square, timesLong by n^1, square, square
* To append 101: square, square, square, timesLong by n^5
* To append 110: square, square, timesLong by n^3, square
* To append 111: square, square, square, timesLong by n^7
*
* Since each pattern involves only one timesLong, the longer the pattern
* the better, except that a 0 (no multiplies) can be appended directly.
* We precompute a table of odd powers of n, up to 2^k, and can then
* timesLong k bits of exponent at a time. Actually, assuming random
* exponents, there is on average one zero bit between needs to
* timesLong (1/2 of the time there's none, 1/4 of the time there's 1,
* 1/8 of the time, there's 2, 1/32 of the time, there's 3, etc.), so
* you have to do one timesLong per k+1 bits of exponent.
*
* The loop walks down the exponent, squaring the result buffer as
* it goes. There is a wbits+1 bit lookahead buffer, buf, that is
* filled with the upcoming exponent bits. (What is read after the
* end of the exponent is unimportant, but it is filled with zero here.)
* When the most-significant bit of this buffer becomes set, i.e.
* (buf & tblmask) != 0, we have to decide what pattern to timesLong
* by, and when to do it. We decide, remember to do it in future
* after a suitable number of squarings have passed (e.g. a pattern
* of "100" in the buffer requires that we timesLong by n^1 immediately;
* a pattern of "110" calls for multiplying by n^3 after one more
* squaring), clear the buffer, and continue.
*
* When we start, there is one more optimization: the result buffer
* is implcitly one, so squaring it or multiplying by it can be
* optimized away. Further, if we start with a pattern like "100"
* in the lookahead window, rather than placing n into the buffer
* and then starting to square it, we have already computed n^2
* to compute the odd-powers table, so we can place that into
* the buffer and save a squaring.
*
* This means that if you have a k-bit window, to compute n^z,
* where z is the high k bits of the exponent, 1/2 of the time
* it requires no squarings. 1/4 of the time, it requires 1
* squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings.
* And the remaining 1/2^(k-1) of the time, the top k bits are a
* 1 followed by k-1 0 bits, so it again only requires k-2
* squarings, not k-1. The average of these is 1. Add that
* to the one squaring we have to do to compute the table,
* and you'll see that a k-bit window saves k-2 squarings
* as well as reducing the multiplies. (It actually doesn't
* hurt in the case k = 1, either.)
*/
// Special case for exponent of one
if (y == ONE)
return this
// Special case for base of zero
if (_signum == 0)
return ZERO
val base = _mag.cloneArray()
val exp = y._mag
var mod = z._mag
var modLen = mod.size
// Make modLen even. It is conventional to use a cryptographic
// modulus that is 512, 768, 1024, or 2048 bits, so this code
// will not normally be executed. However, it is necessary for
// the correct functioning of the HotSpot intrinsics.
if (modLen and 1 != 0) {
val x = IntArray(modLen + 1)
arrayCopy(mod, 0, x, 1, modLen)
mod = x
modLen++
}
// Select an appropriate window size
var wbits = 0
var ebits = bitLength(exp, exp.size)
// if exponent is 65537 (0x10001), use minimum window size
if (ebits != 17 || exp[0] != 65537) {
while (ebits > bnExpModThreshTable[wbits]) {
wbits++
}
}
// Calculate appropriate table size
val tblmask = 1 shl wbits
// Allocate table for precomputed odd powers of base in Montgomery form
val table = (0 until tblmask).map { IntArray(modLen) } .toTypedArray()
// Compute the modular inverse of the least significant 64-bit
// digit of the modulus
val n0 = (mod[modLen - 1].toLong()and LONG_MASK) + (mod[modLen - 2].toLong()and LONG_MASK shl 32)
val inv = -MutableBigInteger.inverseMod64(n0)
// Convert base to Montgomery form
var a = leftShift(base, base.size, modLen shl 5)
val q = MutableBigInteger()
val a2 = MutableBigInteger(a)
val b2 = MutableBigInteger(mod)
b2.normalize() // MutableBigInteger.div() assumes that its
// divisor is in normal form.
val r = a2.divide(b2, q)
table[0] = r!!.toIntArray()
// Pad table[0] with leading zeros so its length is at least modLen
if (table[0].size < modLen) {
val offset = modLen - table[0].size
val t2 = IntArray(modLen)
arrayCopy(table[0], 0, t2, offset, table[0].size)
table[0] = t2
}
// Set b to the square of the base
var b = montgomerySquare(table[0], mod, modLen, inv, null)
// Set t to high half of b
var t = b.copyOf(modLen)
// Fill in the table with odd powers of the base
for (i in 1 until tblmask) {
table[i] = montgomeryMultiply(t, table[i - 1], mod, modLen, inv, null)
}
// Pre load the window that slides over the exponent
var bitpos = 1 shl (ebits - 1 and 32 - 1)
var buf = 0
var elen = exp.size
var eIndex = 0
for (i in 0..wbits) {
buf = buf shl 1 or if (exp[eIndex] and bitpos != 0) 1 else 0
bitpos = bitpos ushr 1
if (bitpos == 0) {
eIndex++
bitpos = 1 shl 32 - 1
elen--
}
}
var multpos = ebits
// The first iteration, which is hoisted out of the main loop
ebits--
var isone = true
multpos = ebits - wbits
while (buf and 1 == 0) {
buf = buf ushr 1
multpos++
}
var mult = table[buf.ushr(1)]
buf = 0
if (multpos == ebits)
isone = false
// The main loop
while (true) {
ebits--
// Advance the window
buf = buf shl 1
if (elen != 0) {
buf = buf or if (exp[eIndex] and bitpos != 0) 1 else 0
bitpos = bitpos ushr 1
if (bitpos == 0) {
eIndex++
bitpos = 1 shl 32 - 1
elen--
}
}
// Examine the window for pending multiplies
if (buf and tblmask != 0) {
multpos = ebits - wbits
while (buf and 1 == 0) {
buf = buf ushr 1
multpos++
}
mult = table[buf.ushr(1)]
buf = 0
}
// Perform timesLong
if (ebits == multpos) {
if (isone) {
b = mult.cloneArray()
isone = false
} else {
t = b
a = montgomeryMultiply(t, mult, mod, modLen, inv, a)
t = a
a = b
b = t
}
}
// Check if done
if (ebits == 0)
break
// Square the input
if (!isone) {
t = b
a = montgomerySquare(t, mod, modLen, inv, a)
t = a
a = b
b = t
}
}
// Convert result out of Montgomery form and return
var t2 = IntArray(2 * modLen)
arrayCopy(b, 0, t2, modLen, modLen)
b = montReduce(t2, mod, modLen, inv.toInt())
t2 = b.copyOf(modLen)
return BigInteger(1, t2)
}
/**
* Returns a BigInteger whose value is (this ** exponent) rem (2**p)
*/
private fun modPow2(exponent: BigInteger, p: Int): BigInteger {
/*
* Perform exponentiation using repeated squaring trick, chopping off
* high order bits as indicated by modulus.
*/
var result = ONE
var baseToPow2 = this.mod2(p)
var expOffset = 0
var limit = exponent.bitLength
if (this.testBit(0))
limit = if (p - 1 < limit) p - 1 else limit
while (expOffset < limit) {
if (exponent.testBit(expOffset))
result = result.times(baseToPow2).mod2(p)
expOffset++
if (expOffset < limit)
baseToPow2 = baseToPow2.square().mod2(p)
}
return result
}
/**
* Returns a BigInteger whose value is this rem(2**p).
* Assumes that this `BigInteger >= 0` and `p > 0`.
*/
private fun mod2(p: Int): BigInteger {
if (bitLength <= p)
return this
// Copy remaining ints of _mag
val numInts = (p + 31).ushr(5)
val mag = IntArray(numInts)
arrayCopy(this._mag, this._mag.size - numInts, mag, 0, numInts)
// Mask out any excess bits
val excessBits = (numInts shl 5) - p
mag[0] = mag[0] and ((1L shl 32 - excessBits) - 1).toInt()
return if (mag[0] == 0) BigInteger(1, mag) else BigInteger(mag, 1)
}
/**
* Returns a BigInteger whose value is `(this`-1 `rem m)`.
*
* @param m the modulus.
* @return `this`-1 `rem m`.
* @throws ArithmeticException `m` 0, or this BigInteger
* has no multiplicative inverse rem m (that is, this BigInteger
* is not *relatively prime* to m).
*/
@JsName("modInverse")
fun modInverse(m: BigInteger): BigInteger {
if (m._signum != 1)
throw ArithmeticException("BigInteger: modulus not positive")
if (m == ONE)
return ZERO
// Calculate (this rem m)
var modVal = this
if (_signum < 0 || this.compareMagnitude(m) >= 0)
modVal = this.rem(m)
if (modVal == ONE)
return ONE
val a = MutableBigInteger(modVal)
val b = MutableBigInteger(m)
val result = a.mutableModInverse(b)
return result!!.toBigInteger(1)
}
// Shift Operations
/**
* Returns a BigInteger whose value is `(this << n)`.
* The shift distance, `n`, may be negative, in which case
* this method performs a right shift.
* (Computes `floor(this * 2n)`.)
*
* @param n shift distance, in bits.
* @return `this << n`
* @see .shr
*/
@JsName("shl")
infix fun shl(n: Int): BigInteger {
if (_signum == 0)
return ZERO
return if (n > 0) {
BigInteger(shl(_mag, n), _signum)
} else if (n == 0) {
this
} else {
// Possible int overflow in (-n) is not a trouble,
// because shiftRightImpl considers its argument unsigned
shiftRightImpl(-n)
}
}
/**
* Returns a BigInteger whose value is `(this >> n)`. Sign
* extension is performed. The shift distance, `n`, may be
* negative, in which case this method performs a left shift.
* (Computes `floor(this / 2n)`.)
*
* @param n shift distance, in bits.
* @return `this >> n`
* @see .shl
*/
@JsName("shr")
infix fun shr(n: Int): BigInteger {
if (_signum == 0)
return ZERO
return if (n > 0) {
shiftRightImpl(n)
} else if (n == 0) {
this
} else {
// Possible int overflow in {@code -n} is not a trouble,
// because shl considers its argument unsigned
BigInteger(shl(_mag, -n), _signum)
}
}
/**
* Returns a BigInteger whose value is `(this >> n)`. The shift
* distance, `n`, is considered unsigned.
* (Computes `floor(this * 2-n)`.)
*
* @param n unsigned shift distance, in bits.
* @return `this >> n`
*/
private fun shiftRightImpl(n: Int): BigInteger {
val nInts = n.ushr(5)
val nBits = n and 0x1f
val magLen = _mag.size
var newMag: IntArray? = null
// Special case: entire contents shifted off the end
if (nInts >= magLen)
return if (_signum >= 0) ZERO else (negConst[1] ?: throw IllegalStateException())
if (nBits == 0) {
val newMagLen = magLen - nInts
newMag = _mag.copyOf(newMagLen)
} else {
var i = 0
val highBits = _mag[0].ushr(nBits)
if (highBits != 0) {
newMag = IntArray(magLen - nInts)
newMag[i++] = highBits
} else {
newMag = IntArray(magLen - nInts - 1)
}
val nBits2 = 32 - nBits
var j = 0
while (j < magLen - nInts - 1)
newMag[i++] = _mag[j++] shl nBits2 or _mag[j].ushr(nBits)
}
if (_signum < 0) {
// Find out whether any one-bits were shifted off the end.
var onesLost = false
var i = magLen - 1
val j = magLen - nInts
while (i >= j && !onesLost) {
onesLost = _mag[i] != 0
i--
}
if (!onesLost && nBits != 0)
onesLost = _mag[magLen - nInts - 1] shl 32 - nBits != 0
if (onesLost)
newMag = javaIncrement(newMag)
}
return BigInteger(newMag, _signum)
}
private fun javaIncrement(`val`: IntArray): IntArray {
var result = `val`
var lastSum = 0
var i = result.size - 1
while (i >= 0 && lastSum == 0) {
lastSum = (result[i]++)
i--
}
if (lastSum == 0) {
result = IntArray(result.size + 1)
result[0] = 1
}
return result
}
// Bitwise Operations
/**
* Returns a BigInteger whose value is `(this & val)`. (This
* method returns a negative BigInteger if and only if this and val are
* both negative.)
*
* @param val value to be AND'ed with this BigInteger.
* @return `this & val`
*/
@JsName("and")
fun and(`val`: BigInteger): BigInteger {
val result = IntArray(max(intLength, `val`.intLength))
for (i in result.indices)
result[i] = getInt(result.size - i - 1) and `val`.getInt(result.size - i - 1)
return of(result)
}
/**
* Returns a BigInteger whose value is `(this | val)`. (This method
* returns a negative BigInteger if and only if either this or val is
* negative.)
*
* @param val value to be OR'ed with this BigInteger.
* @return `this | val`
*/
@JsName("or")
fun or(`val`: BigInteger): BigInteger {
val result = IntArray(max(intLength, `val`.intLength))
for (i in result.indices)
result[i] = getInt(result.size - i - 1) or `val`.getInt(result.size - i - 1)
return of(result)
}
/**
* Returns a BigInteger whose value is `(this ^ val)`. (This method
* returns a negative BigInteger if and only if exactly one of this and
* val are negative.)
*
* @param val value to be XOR'ed with this BigInteger.
* @return `this ^ val`
*/
@JsName("xor")
fun xor(`val`: BigInteger): BigInteger {
val result = IntArray(max(intLength, `val`.intLength))
for (i in result.indices)
result[i] = getInt(result.size - i - 1) xor `val`.getInt(result.size - i - 1)
return of(result)
}
/**
* Returns a BigInteger whose value is `(~this)`. (This method
* returns a negative value if and only if this BigInteger is
* non-negative.)
*
* @return `~this`
*/
@JsName("not")
operator fun not(): BigInteger {
val result = IntArray(intLength)
for (i in result.indices)
result[i] = getInt(result.size - i - 1).inv()
return of(result)
}
/**
* Returns a BigInteger whose value is `(this & ~val)`. This
* method, which is equivalent to `and(val.not())`, is provided as
* a convenience for masking operations. (This method returns a negative
* BigInteger if and only if `this` is negative and `val` is
* positive.)
*
* @param val value to be complemented and AND'ed with this BigInteger.
* @return `this & ~val`
*/
@JsName("andNot")
fun andNot(`val`: BigInteger): BigInteger {
val result = IntArray(max(intLength, `val`.intLength))
for (i in result.indices)
result[i] = getInt(result.size - i - 1) and `val`.getInt(result.size - i - 1).inv()
return of(result)
}
// Single Bit Operations
/**
* Returns `true` if and only if the designated bit is set.
* (Computes `((this & (1<`certainty`). The execution time of
* this method is proportional to the value of this parameter.
* @return `true` if this BigInteger is probably prime,
* `false` if it's definitely composite.
*/
@JsName("isProbablePrime")
fun isProbablePrime(certainty: Int): Boolean {
if (certainty <= 0)
return true
val w = this.absoluteValue
if (w == TWO)
return true
return if (!w.testBit(0) || w == ONE) false else w.primeToCertainty(certainty, null)
}
// Comparison Operations
/**
* Compares this BigInteger with the specified BigInteger. This
* method is provided in preference to individual methods for each
* of the six boolean comparison operators (<, ==,
* >, >=, !=, <=). The suggested
* idiom for performing these comparisons is: `(x.compareTo(y)` <*op*> `0)`, where
* <*op*> is one of the six comparison operators.
*
* @param other BigInteger to which this BigInteger is to be compared.
* @return -1, 0 or 1 as this BigInteger is numerically less than, equal
* to, or greater than `val`.
*/
override fun compareTo(other: BigInteger): Int {
if (_signum == other._signum) {
when (_signum) {
1 -> return compareMagnitude(other)
-1 -> return other.compareMagnitude(this)
else -> return 0
}
}
return if (_signum > other._signum) 1 else -1
}
/**
* Compares the magnitude array of this BigInteger with the specified
* BigInteger's. This is the version of compareTo ignoring sign.
*
* @param val BigInteger whose magnitude array to be compared.
* @return -1, 0 or 1 as this magnitude array is less than, equal to or
* greater than the magnitude aray for the specified BigInteger's.
*/
internal fun compareMagnitude(`val`: BigInteger): Int {
val m1 = _mag
val len1 = m1.size
val m2 = `val`._mag
val len2 = m2.size
if (len1 < len2)
return -1
if (len1 > len2)
return 1
for (i in 0 until len1) {
val a = m1[i]
val b = m2[i]
if (a != b)
return if (a.toLong()and LONG_MASK < b.toLong()and LONG_MASK) -1 else 1
}
return 0
}
/**
* Version of compareMagnitude that compares magnitude with long value.
* val can't be Long.MIN_VALUE.
*/
internal fun compareMagnitude(`val`: Long): Int {
var `val` = `val`
require(`val` != Long.MIN_VALUE)
val m1 = _mag
val len = m1.size
if (len > 2) {
return 1
}
if (`val` < 0) {
`val` = -`val`
}
val highWord = `val`.ushr(32).toInt()
if (highWord == 0) {
if (len < 1)
return -1
if (len > 1)
return 1
val a = m1[0]
val b = `val`.toInt()
return if (a != b) {
if (a.toLong()and LONG_MASK < b.toLong()and LONG_MASK) -1 else 1
} else 0
} else {
if (len < 2)
return -1
var a = m1[0]
var b = highWord
if (a != b) {
return if (a.toLong()and LONG_MASK < b.toLong()and LONG_MASK) -1 else 1
}
a = m1[1]
b = `val`.toInt()
return if (a != b) {
if (a.toLong()and LONG_MASK < b.toLong()and LONG_MASK) -1 else 1
} else 0
}
}
/**
* Compares this BigInteger with the specified Object for equality.
*
* @param other Object to which this BigInteger is to be compared.
* @return `true` if and only if the specified Object is a
* BigInteger whose value is numerically equal to this BigInteger.
*/
override fun equals(other: Any?): Boolean {
// This test is just an optimization, which may or may not help
if (other === this)
return true
if (other !is BigInteger)
return false
val xInt = other as BigInteger?
if (xInt!!._signum != _signum)
return false
val m = _mag
val len = m.size
val xm = xInt._mag
if (len != xm.size)
return false
for (i in 0 until len)
if (xm[i] != m[i])
return false
return true
}
/**
* Returns the minimum of this BigInteger and `val`.
*
* @param val value with which the minimum is to be computed.
* @return the BigInteger whose value is the lesser of this BigInteger and
* `val`. If they are equal, either may be returned.
*/
@JsName("min")
fun min(`val`: BigInteger): BigInteger {
return if (this < `val`) this else `val`
}
/**
* Returns the maximum of this BigInteger and `val`.
*
* @param val value with which the maximum is to be computed.
* @return the BigInteger whose value is the greater of this and
* `val`. If they are equal, either may be returned.
*/
@JsName("max")
fun max(`val`: BigInteger): BigInteger {
return if (this > `val`) this else `val`
}
// Hash Function
/**
* Returns the hash code for this BigInteger.
*
* @return hash code for this BigInteger.
*/
override fun hashCode(): Int {
var hashCode = 0
for (i in _mag.indices)
hashCode = 31 * hashCode + (_mag[i].toLong()and LONG_MASK).toInt()
return hashCode * _signum
}
/**
* Returns the String representation of this BigInteger in the
* given radix. If the radix is outside the range from [CHAR_MIN_RADIX] to [CHAR_MAX_RADIX] inclusive,
* it will default to 10 (as is the case for
* `Int.toString`). The digit-to-character mapping
* provided by `Character.forDigit` is used, and a subtract
* sign is prepended if appropriate. (This representation is
* compatible with the String constructor.)
*
* @param radix radix of the String representation.
* @return String representation of this BigInteger in the given radix.
* @see Int.toString
*/
@JsName("toStringWithRadix")
fun toString(radix: Int): String {
var radix = radix
if (_signum == 0)
return "0"
if (radix < CHAR_MIN_RADIX || radix > CHAR_MAX_RADIX)
radix = 10
// If it's small enough, use smallToString.
if (_mag.size <= SCHOENHAGE_BASE_CONVERSION_THRESHOLD)
return smallToString(radix)
// Otherwise use recursive toString, which requires positive arguments.
// The results will be concatenated into this StringBuilder
var sb = StringBuilder()
if (_signum < 0) {
toString(this.unaryMinus(), sb, radix, 0)
sb = sb.insertChar(0, '-')
} else
toString(this, sb, radix, 0)
return sb.toString()
}
/** This method is used to perform toString when arguments are small. */
private fun smallToString(radix: Int): String {
if (_signum == 0) {
return "0"
}
// Compute upper bound on number of digit groups and allocate space
val maxNumDigitGroups = (4 * _mag.size + 6) / 7
val digitGroup = arrayOfNulls(maxNumDigitGroups)
// Translate number to string, a digit group at a time
var tmp = this.absoluteValue
var numGroups = 0
while (tmp._signum != 0) {
val d = longRadix[radix]
val q = MutableBigInteger()
val a = MutableBigInteger(tmp._mag)
val b = MutableBigInteger(d!!._mag)
val r = a.divide(b, q)
val q2 = q.toBigInteger(tmp._signum * d._signum)
val r2 = r!!.toBigInteger(tmp._signum * d._signum)
digitGroup[numGroups++] = r2.toLong().toString(radix)
// Long.toString(r2.toLong(), radix)
tmp = q2
}
// Put sign (if any) and first digit group into result buffer
val buf = StringBuilder(numGroups * digitsPerLong[radix] + 1)
if (_signum < 0) {
buf.append('-')
}
buf.append(digitGroup[numGroups - 1])
// Append remaining digit groups padded with leading zeros
for (i in numGroups - 2 downTo 0) {
// Prepend (any) leading zeros for this digit group
val numLeadingZeros = digitsPerLong[radix] - digitGroup[i]!!.length
if (numLeadingZeros != 0) {
buf.append(zeros[numLeadingZeros])
}
buf.append(digitGroup[i])
}
return buf.toString()
}
/**
* Returns the decimal String representation of this BigInteger.
* The digit-to-character mapping provided by
* `Character.forDigit` is used, and a subtract sign is
* prepended if appropriate. (This representation is compatible
* with the string constructor, and
* allows for String concatenation with Java's + operator.)
*
* @return decimal String representation of this BigInteger.
*/
override fun toString(): String {
return toString(10)
}
/**
* Returns a byte array containing the two's-complement
* representation of this BigInteger. The byte array will be in
* *big-endian* byte-order: the most significant byte is in
* the zeroth element. The array will contain the minimum number
* of bytes required to represent this BigInteger, including at
* least one sign bit, which is `(ceil((this.bitLength() +
* 1)/8))`. (This representation is compatible with the
* byte array constructor.)
*
* @return a byte array containing the two's-complement representation of
* this BigInteger.
*/
@JsName("toByteArray")
fun toByteArray(): ByteArray {
val byteLen = bitLength / 8 + 1
val byteArray = ByteArray(byteLen)
var i = byteLen - 1
var bytesCopied = 4
var nextInt = 0
var intIndex = 0
while (i >= 0) {
if (bytesCopied == 4) {
nextInt = getInt(intIndex++)
bytesCopied = 1
} else {
nextInt = nextInt ushr 8
bytesCopied++
}
byteArray[i] = nextInt.toByte()
i--
}
return byteArray
}
/**
* Converts this BigInteger to an `int`. This
* conversion is analogous to a
* *narrowing primitive conversion* from `long` to
* `int` as defined in
* The Java Language Specification:
* if this BigInteger is too big to fit in an
* `int`, only the low-order 32 bits are returned.
* Note that this conversion can lose information about the
* overall magnitude of the BigInteger value as well as return a
* result with the opposite sign.
*
* @return this BigInteger converted to an `int`.
* @see BigInteger.toIntExact
* @jls 5.1.3 Narrowing Primitive Conversion
*/
@JsName("toInt")
/*override*/ fun toInt(): Int {
var result = 0
result = getInt(0)
return result
}
/**
* Converts this BigInteger to a `long`. This
* conversion is analogous to a
* *narrowing primitive conversion* from `long` to
* `int` as defined in
* The Java Language Specification:
* if this BigInteger is too big to fit in a
* `long`, only the low-order 64 bits are returned.
* Note that this conversion can lose information about the
* overall magnitude of the BigInteger value as well as return a
* result with the opposite sign.
*
* @return this BigInteger converted to a `long`.
* @see .toLongExact
* @jls 5.1.3 Narrowing Primitive Conversion
*/
@JsName("toLong")
/*override*/ fun toLong(): Long {
var result: Long = 0
for (i in 1 downTo 0)
result = (result shl 32) + (getInt(i).toLong() and LONG_MASK)
return result
}
@JsName("toByte")
/*override*/ fun toByte(): Byte {
return toInt().toByte()
}
@JsName("toChar")
/*override*/ fun toChar(): Char {
return toInt().toChar()
}
@JsName("toShort")
/*override*/ fun toShort(): Short {
return toInt().toShort()
}
@JsName("toFloat")
/*override*/ fun toFloat(): Float {
return toInt().toFloat()
}
@JsName("toDouble")
/*override*/ fun toDouble(): Double {
return toLong().toDouble()
}
/**
* These routines provide access to the two's complement representation
* of BigIntegers.
*/
/**
* Returns the length of the two's complement representation in ints,
* including space for at least one sign bit.
*/
private val intLength: Int
get() {
return bitLength.ushr(5) + 1
}
/* Returns sign bit */
private val signBit: Int
get() {
return if (_signum < 0) 1 else 0
}
/* Returns an int of sign bits */
private val signInt: Int
get() {
return if (_signum < 0) -1 else 0
}
/**
* Returns the specified int of the little-endian two's complement
* representation (int 0 is the least significant). The int number can
* be arbitrarily high (values are logically preceded by infinitely many
* sign ints).
*/
private fun getInt(n: Int): Int {
if (n < 0)
return 0
if (n >= _mag.size)
return signInt
val magInt = _mag[_mag.size - n - 1]
return if (_signum >= 0)
magInt
else
if (n <= firstNonzeroIntNum()) -magInt else magInt.inv()
}
/**
* Returns the index of the int that contains the first nonzero int in the
* little-endian binary representation of the magnitude (int 0 is the
* least significant). If the magnitude is zero, return value is undefined.
*
*
* Note: never used for a BigInteger with a magnitude of zero.
* @see .getInt
*/
private fun firstNonzeroIntNum(): Int {
var fn = _firstNonzeroIntNumPlusTwo - 2
if (fn == -2) { // firstNonzeroIntNum not initialized yet
// Search for the first nonzero int
var i: Int
val mlen = _mag.size
i = mlen - 1
while (i >= 0 && _mag[i] == 0) {
i--
}
fn = mlen - i - 1
_firstNonzeroIntNumPlusTwo = fn + 2 // offset by two to initialize
}
return fn
}
/**
* Returns the _mag array as an array of bytes.
*/
private fun magSerializedForm(): ByteArray {
val len = _mag.size
val bitLen = if (len == 0) 0 else (len - 1 shl 5) + bitLengthForInt(_mag[0])
val byteLen = (bitLen + 7).ushr(3)
val result = ByteArray(byteLen)
var i = byteLen - 1
var bytesCopied = 4
var intIndex = len - 1
var nextInt = 0
while (i >= 0) {
if (bytesCopied == 4) {
nextInt = _mag[intIndex--]
bytesCopied = 1
} else {
nextInt = nextInt ushr 8
bytesCopied++
}
result[i] = nextInt.toByte()
i--
}
return result
}
/**
* Converts this `BigInteger` to a `long`, checking
* for lost information. If the value of this `BigInteger`
* is out of the range of the `long` type, then an
* `ArithmeticException` is thrown.
*
* @return this `BigInteger` converted to a `long`.
* @throws ArithmeticException if the value of `this` will
* not exactly fit in a `long`.
* @see BigInteger.toLong
*
* @since 1.8
*/
fun toLongExact(): Long {
return if (_mag.size <= 2 && bitLength <= 63)
toLong()
else
throw ArithmeticException("BigInteger out of long range")
}
/**
* Converts this `BigInteger` to an `int`, checking
* for lost information. If the value of this `BigInteger`
* is out of the range of the `int` type, then an
* `ArithmeticException` is thrown.
*
* @return this `BigInteger` converted to an `int`.
* @throws ArithmeticException if the value of `this` will
* not exactly fit in an `int`.
* @see BigInteger.toInt
*
* @since 1.8
*/
@JsName("toIntExact")
fun toIntExact(): Int {
return if (_mag.size <= 1 && bitLength <= 31)
toInt()
else
throw ArithmeticException("BigInteger out of int range")
}
/**
* Converts this `BigInteger` to a `short`, checking
* for lost information. If the value of this `BigInteger`
* is out of the range of the `short` type, then an
* `ArithmeticException` is thrown.
*
* @return this `BigInteger` converted to a `short`.
* @throws ArithmeticException if the value of `this` will
* not exactly fit in a `short`.
* @see BigInteger.toShort
*
* @since 1.8
*/
@JsName("toShortExact")
fun toShortExact(): Short {
if (_mag.size <= 1 && bitLength <= 31) {
val value = toInt()
if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
return toShort()
}
throw ArithmeticException("BigInteger out of short range")
}
/**
* Converts this `BigInteger` to a `byte`, checking
* for lost information. If the value of this `BigInteger`
* is out of the range of the `byte` type, then an
* `ArithmeticException` is thrown.
*
* @return this `BigInteger` converted to a `byte`.
* @throws ArithmeticException if the value of `this` will
* not exactly fit in a `byte`.
* @see BigInteger.toByte
*
* @since 1.8
*/
@JsName("toByteExact")
fun toByteExact(): Byte {
if (_mag.size <= 1 && bitLength <= 31) {
val value = toInt()
if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
return toByte()
}
throw ArithmeticException("BigInteger out of byte range")
}
companion object {
/**
* This mask is used to obtain the value of an int as if it were unsigned.
*/
const val LONG_MASK = 0xffffffffL
/**
* This constant limits `_mag.length` of BigIntegers to the supported
* range.
*/
private const val MAX_MAG_LENGTH = Int.MAX_VALUE / Int.SIZE_BITS + 1 // (1 << 26)
/**
* Bit lengths larger than this constant can cause overflow in searchLen
* calculation and in BitSieve.singleSearch method.
*/
private const val PRIME_SEARCH_BIT_LENGTH_LIMIT = 500000000
/**
* The threshold value for using Karatsuba multiplication. If the number
* of ints in both _mag arrays are greater than this number, then
* Karatsuba multiplication will be used. This value is found
* experimentally to work well.
*/
private const val KARATSUBA_THRESHOLD = 80
/**
* The threshold value for using 3-way Toom-Cook multiplication.
* If the number of ints in each _mag array is greater than the
* Karatsuba threshold, and the number of ints in at least one of
* the _mag arrays is greater than this threshold, then Toom-Cook
* multiplication will be used.
*/
private const val TOOM_COOK_THRESHOLD = 240
/**
* The threshold value for using Karatsuba squaring. If the number
* of ints in the number are larger than this value,
* Karatsuba squaring will be used. This value is found
* experimentally to work well.
*/
private const val KARATSUBA_SQUARE_THRESHOLD = 128
/**
* The threshold value for using Toom-Cook squaring. If the number
* of ints in the number are larger than this value,
* Toom-Cook squaring will be used. This value is found
* experimentally to work well.
*/
private const val TOOM_COOK_SQUARE_THRESHOLD = 216
/**
* The threshold value for using Burnikel-Ziegler division. If the number
* of ints in the divisor are larger than this value, Burnikel-Ziegler
* division may be used. This value is found experimentally to work well.
*/
internal const val BURNIKEL_ZIEGLER_THRESHOLD = 80
/**
* The offset value for using Burnikel-Ziegler division. If the number
* of ints in the divisor exceeds the Burnikel-Ziegler threshold, and the
* number of ints in the dividend is greater than the number of ints in the
* divisor plus this value, Burnikel-Ziegler division will be used. This
* value is found experimentally to work well.
*/
internal const val BURNIKEL_ZIEGLER_OFFSET = 40
/**
* The threshold value for using Schoenhage recursive base conversion. If
* the number of ints in the number are larger than this value,
* the Schoenhage algorithm will be used. In practice, it appears that the
* Schoenhage routine is faster for any threshold down to 2, and is
* relatively flat for thresholds between 2-25, so this choice may be
* varied within this range for very small effect.
*/
private const val SCHOENHAGE_BASE_CONVERSION_THRESHOLD = 20
/**
* The threshold value for using squaring code to perform multiplication
* of a `BigInteger` instance by itself. If the number of ints in
* the number are larger than this value, `timesLong(this)` will
* return `square()`.
*/
private const val MULTIPLY_SQUARE_THRESHOLD = 20
/**
* The threshold for using an intrinsic version of
* implMontgomeryXXX to perform Montgomery multiplication. If the
* number of ints in the number is more than this value we do not
* use the intrinsic.
*/
private const val MONTGOMERY_INTRINSIC_THRESHOLD = 512
// bitsPerDigit in the given radix timesLong 1024
// Rounded up to avoid underallocation.
private val bitsPerDigit = longArrayOf(
0,
0,
1024,
1624,
2048,
2378,
2648,
2875,
3072,
3247,
3402,
3543,
3672,
3790,
3899,
4001,
4096,
4186,
4271,
4350,
4426,
4498,
4567,
4633,
4696,
4756,
4814,
4870,
4923,
4975,
5025,
5074,
5120,
5166,
5210,
5253,
5295
)
// Multiply x array timesLong word y in place, and plus word z
private fun destructiveMulAdd(x: IntArray, y: Int, z: Int) {
// Perform the multiplication word by word
val ylong = y.toLong() and LONG_MASK
val zlong = z.toLong() and LONG_MASK
val len = x.size
var product: Long = 0
var carry: Long = 0
for (i in len - 1 downTo 0) {
product = ylong * (x[i].toLong() and LONG_MASK) + carry
x[i] = product.toInt()
carry = product.ushr(32)
}
// Perform the addition
var sum = (x[len - 1].toLong() and LONG_MASK) + zlong
x[len - 1] = sum.toInt()
carry = sum.ushr(32)
for (i in len - 2 downTo 0) {
sum = (x[i].toLong() and LONG_MASK) + carry
x[i] = sum.toInt()
carry = sum.ushr(32)
}
}
private fun randomBits(numBits: Int, rnd: Random): ByteArray {
if (numBits < 0)
throw IllegalArgumentException("numBits must be non-negative")
val numBytes = ((numBits.toLong() + 7) / 8).toInt() // avoid overflow
val randomBits = ByteArray(numBytes)
// Generate random bytes and mask out any excess bits
if (numBytes > 0) {
rnd.nextBytes(randomBits)
val excessBits = 8 * numBytes - numBits
randomBits[0] = randomBits[0] and ((1 shl 8 - excessBits) - 1).toByte()
}
return randomBits
}
// Minimum size in bits that the requested prime number has
// before we use the large prime number generating algorithms.
// The cutoff of 95 was chosen empirically for best performance.
private const val SMALL_PRIME_THRESHOLD = 95
// Certainty required to meet the spec of probablePrime
private const val DEFAULT_PRIME_CERTAINTY = 100
/**
* Returns a positive BigInteger that is probably prime, with the
* specified bitLength. The probability that a BigInteger returned
* by this method is composite does not exceed 2-100.
*
* @param bitLength bitLength of the returned BigInteger.
* @param rnd source of random bits used to select candidates to be
* tested for primality.
* @return a BigInteger of `bitLength` bits that is probably prime
* @throws ArithmeticException `bitLength < 2` or `bitLength` is too large.
* @see BigInteger.bitLength
* @since 1.4
*/
fun probablePrime(bitLength: Int, rnd: Random): BigInteger {
if (bitLength < 2)
throw ArithmeticException("bitLength < 2")
return if (bitLength < SMALL_PRIME_THRESHOLD)
smallPrime(
bitLength,
DEFAULT_PRIME_CERTAINTY,
rnd
)
else
largePrime(
bitLength,
DEFAULT_PRIME_CERTAINTY,
rnd
)
}
/**
* Find a random number of the specified bitLength that is probably prime.
* This method is used for smaller primes, its performance degrades on
* larger bitlengths.
*
* This method assumes bitLength > 1.
*/
private fun smallPrime(bitLength: Int, certainty: Int, rnd: Random): BigInteger {
val magLen = (bitLength + 31).ushr(5)
val temp = IntArray(magLen)
val highBit = 1 shl (bitLength + 31 and 0x1f) // High bit of high int
val highMask = (highBit shl 1) - 1 // Bits to keep in high int
while (true) {
// Construct a candidate
for (i in 0 until magLen)
temp[i] = rnd.nextInt()
temp[0] = temp[0] and highMask or highBit // Ensure exact length
if (bitLength > 2)
temp[magLen - 1] = temp[magLen - 1] or 1 // Make odd if bitlen > 2
val p = BigInteger(temp, 1)
// Do cheap "pre-test" if applicable
if (bitLength > 6) {
val r = p.remainder(SMALL_PRIME_PRODUCT).toLong()
if (r % 3 == 0L || r % 5 == 0L || r % 7 == 0L || r % 11 == 0L ||
r % 13 == 0L || r % 17 == 0L || r % 19 == 0L || r % 23 == 0L ||
r % 29 == 0L || r % 31 == 0L || r % 37 == 0L || r % 41 == 0L
)
continue // Candidate is composite; try another
}
// All candidates of bitLength 2 and 3 are prime by this point
if (bitLength < 4)
return p
// Do expensive test if we survive pre-test (or it's inapplicable)
if (p.primeToCertainty(certainty, rnd))
return p
}
}
private val SMALL_PRIME_PRODUCT = of(3L * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29 * 31 * 37 * 41)
/**
* Find a random number of the specified bitLength that is probably prime.
* This method is more appropriate for larger bitlengths since it uses
* a sieve to eliminate most composites before using a more expensive
* test.
*/
private fun largePrime(bitLength: Int, certainty: Int, rnd: Random): BigInteger {
var p: BigInteger
p = BigInteger(bitLength, rnd).setBit(bitLength - 1)
p._mag[p._mag.size - 1] = p._mag[p._mag.size - 1] and -0x2
// Use a sieve length likely to contain the next prime number
val searchLen = getPrimeSearchLen(bitLength)
var searchSieve = BitSieve(p, searchLen)
var candidate = searchSieve.retrieve(p, certainty, rnd)
while (candidate == null || candidate.bitLength != bitLength) {
p = p.plus(of((2 * searchLen).toLong()))
if (p.bitLength != bitLength)
p = BigInteger(bitLength, rnd).setBit(bitLength - 1)
p._mag[p._mag.size - 1] = p._mag[p._mag.size - 1] and -0x2
searchSieve = BitSieve(p, searchLen)
candidate = searchSieve.retrieve(p, certainty, rnd)
}
return candidate
}
private fun getPrimeSearchLen(bitLength: Int): Int {
if (bitLength > PRIME_SEARCH_BIT_LENGTH_LIMIT + 1) {
throw ArithmeticException("Prime search implementation restriction on bitLength")
}
return bitLength / 20 * 64
}
/**
* Computes Jacobi(p,n).
* Assumes n positive, odd, n>=3.
*/
private fun jacobiSymbol(p: Int, n: BigInteger): Int {
var p = p
if (p == 0)
return 0
// Algorithm and comments adapted from Colin Plumb's C library.
var j = 1
var u = n._mag[n._mag.size - 1]
// Make p positive
if (p < 0) {
p = -p
val n8 = u and 7
if (n8 == 3 || n8 == 7)
j = -j // 3 (011) or 7 (111) rem 8
}
// Get rid of factors of 2 in p
while (p and 3 == 0)
p = p shr 2
if (p and 1 == 0) {
p = p shr 1
if (u xor (u shr 1) and 2 != 0)
j = -j // 3 (011) or 5 (101) rem 8
}
if (p == 1)
return j
// Then, apply quadratic reciprocity
if (p and u and 2 != 0)
// p = u = 3 (rem 4)?
j = -j
// And reduce u rem p
u = n.rem(of(p.toLong())).toInt()
// Now compute Jacobi(u,p), u < p
while (u != 0) {
while (u and 3 == 0)
u = u shr 2
if (u and 1 == 0) {
u = u shr 1
if (p xor (p shr 1) and 2 != 0)
j = -j // 3 (011) or 5 (101) rem 8
}
if (u == 1)
return j
// Now both u and p are odd, so use quadratic reciprocity
require(u < p)
val t = u
u = p
p = t
if (u and p and 2 != 0)
// u = p = 3 (rem 4)?
j = -j
// Now u >= p, so it can be reduced
u %= p
}
return 0
}
private fun lucasLehmerSequence(z: Int, k: BigInteger, n: BigInteger): BigInteger {
val d = of(z.toLong())
var u = ONE
var u2: BigInteger
var v = ONE
var v2: BigInteger
for (i in k.bitLength - 2 downTo 0) {
u2 = u.times(v).rem(n)
v2 = v.square().plus(d.times(u.square())).rem(n)
if (v2.testBit(0))
v2 = v2.minus(n)
v2 = v2.shr(1)
u = u2
v = v2
if (k.testBit(i)) {
u2 = u.plus(v).rem(n)
if (u2.testBit(0))
u2 = u2.minus(n)
u2 = u2.shr(1)
v2 = v.plus(d.times(u)).rem(n)
if (v2.testBit(0))
v2 = v2.minus(n)
v2 = v2.shr(1)
u = u2
v = v2
}
}
return u
}
private fun reportOverflow() {
throw ArithmeticException("BigInteger would overflow supported range")
}
//Static Factory Methods
/**
* Returns a BigInteger whose value is equal to that of the
* specified `long`.
*
* @apiNote This static factory method is provided in preference
* to a (`long`) constructor because it allows for reuse of
* frequently used BigIntegers.
*
* @param val value of the BigInteger to return.
* @return a BigInteger with the specified value.
*/
@JsName("ofLong")
fun of(`val`: Long): BigInteger {
// If -MAX_CONSTANT < val < MAX_CONSTANT, return stashed constant
if (`val` == 0L)
return ZERO
if (`val` in 1..MAX_CONSTANT)
return posConst[`val`.toInt()] ?: throw IllegalStateException()
else if (`val` < 0 && `val` >= -MAX_CONSTANT)
return negConst[(-`val`).toInt()] ?: throw IllegalStateException()
return BigInteger(`val`)
}
@JsName("of")
fun of(value: Int): BigInteger {
return of(value.toLong())
}
private fun String.getRadix(): Pair {
return when {
this.contains("0B", ignoreCase = true) -> {
Pair(2, this.replaceFirst("0B", "").replaceFirst("0b", ""))
}
this.contains("0O", ignoreCase = true) -> {
Pair(8, this.replaceFirst("0O", "").replaceFirst("0o", ""))
}
this.contains("0X", ignoreCase = true) -> {
Pair(16, this.replaceFirst("0X", "").replaceFirst("0x", ""))
}
else -> Pair(10, this)
}
}
@JsName("parse")
fun of(value: String): BigInteger {
val radixed = value.getRadix()
return BigInteger(radixed.second, radixed.first)
}
@JsName("parseWithRadix")
fun of(value: String, radix: Int): BigInteger {
return BigInteger(value, radix)
}
/**
* Returns a BigInteger with the given two's complement representation.
* Assumes that the input array will not be modified (the returned
* BigInteger will reference the input array if feasible).
*/
@JsName("ofIntArray")
private fun of(`val`: IntArray): BigInteger {
return if (`val`[0] > 0) BigInteger(`val`, 1) else BigInteger(`val`)
}
// Constants
/**
* Initialize static constant array when class is loaded.
*/
private val MAX_CONSTANT = 16
private val posConst = arrayOfNulls(MAX_CONSTANT + 1)
private val negConst = arrayOfNulls(MAX_CONSTANT + 1)
/**
* The cache of powers of each radix. This allows us to not have to
* recalculate powers of radix^(2^n) more than once. This speeds
* Schoenhage recursive base conversion significantly.
*/
private var powerCache: Array?> = arrayOfNulls(0)
/** The cache of logarithms of radices for base conversion. */
private val logCache: DoubleArray
/** The natural log of 2. This is used in computing cache indices. */
private val LOG_TWO = ln(2.0)
init {
for (i in 1..MAX_CONSTANT) {
val magnitude = IntArray(1)
magnitude[0] = i
posConst[i] = BigInteger(magnitude, 1)
negConst[i] = BigInteger(magnitude, -1)
}
/*
* Initialize the cache of radix^(2^x) values used for base conversion
* with just the very first value. Additional values will be created
* on demand.
*/
powerCache = arrayOfNulls(CHAR_MAX_RADIX + 1)
logCache = DoubleArray(CHAR_MAX_RADIX + 1)
for (i in CHAR_MIN_RADIX .. CHAR_MAX_RADIX) {
powerCache[i] = arrayOf(of(i.toLong()))
logCache[i] = ln(i.toDouble())
}
}
/**
* The BigInteger constant zero.
*
* @since 1.2
*/
val ZERO = BigInteger(IntArray(0), 0)
/**
* The BigInteger constant one.
*
* @since 1.2
*/
val ONE = of(1)
/**
* The BigInteger constant two.
*
* @since 9
*/
val TWO = of(2)
/**
* The BigInteger constant -1. (Not exported.)
*/
private val NEGATIVE_ONE = of(-1)
/**
* The BigInteger constant ten.
*
* @since 1.5
*/
val TEN = of(10)
/**
* Adds the contents of the int array x and long value val. This
* method allocates a new int array to hold the answer and returns
* a reference to that array. Assumes x.length > 0 and val is
* non-negative
*/
private fun sum(x: IntArray, `val`: Long): IntArray {
var sum: Long = 0
var xIndex = x.size
val result: IntArray
val highWord = `val`.ushr(32).toInt()
if (highWord == 0) {
result = IntArray(xIndex)
sum = (x[--xIndex].toLong()and LONG_MASK) + `val`
result[xIndex] = sum.toInt()
} else {
if (xIndex == 1) {
result = IntArray(2)
sum = `val` + (x[0].toLong()and LONG_MASK)
result[1] = sum.toInt()
result[0] = sum.ushr(32).toInt()
return result
} else {
result = IntArray(xIndex)
sum = (x[--xIndex].toLong()and LONG_MASK) + (`val`.toLong()and LONG_MASK)
result[xIndex] = sum.toInt()
sum = (x[--xIndex].toLong()and LONG_MASK) + (highWord.toLong()and LONG_MASK) + sum.ushr(32)
result[xIndex] = sum.toInt()
}
}
// Copy remainder of longer number while carry propagation is required
var carry = sum.ushr(32) != 0L
while (xIndex > 0 && carry) {
result[xIndex - 1] = x[xIndex] + 1
carry = result[--xIndex] == 0
}
// Copy remainder of longer number
while (xIndex > 0)
result[--xIndex] = x[xIndex]
// Grow result if necessary
if (carry) {
val bigger = IntArray(result.size + 1)
arrayCopy(result, 0, bigger, 1, result.size)
bigger[0] = 0x01
return bigger
}
return result
}
/**
* Adds the contents of the int arrays x and y. This method allocates
* a new int array to hold the answer and returns a reference to that
* array.
*/
private fun sum(x: IntArray, y: IntArray): IntArray {
var x = x
var y = y
// If x is shorter, swap the two arrays
if (x.size < y.size) {
val tmp = x
x = y
y = tmp
}
var xIndex = x.size
var yIndex = y.size
val result = IntArray(xIndex)
var sum: Long = 0
if (yIndex == 1) {
xIndex--
sum = (x[xIndex].toLong()and LONG_MASK) + (y[0].toLong()and LONG_MASK)
result[xIndex] = sum.toInt()
} else {
// Add common parts of both numbers
while (yIndex > 0) {
sum = (x[--xIndex].toLong()and LONG_MASK) +
(y[--yIndex].toLong()and LONG_MASK) + sum.ushr(32)
result[xIndex] = sum.toInt()
}
}
// Copy remainder of longer number while carry propagation is required
var carry = sum.ushr(32) != 0L
while (xIndex > 0 && carry) {
//carry = ((result[--xIndex] = x[xIndex] + 1) == 0)
result[--xIndex] = x[xIndex] + 1
carry = result[xIndex] == 0
}
// Copy remainder of longer number
while (xIndex > 0)
result[--xIndex] = x[xIndex]
// Grow result if necessary
if (carry) {
val bigger = IntArray(result.size + 1)
arrayCopy(result, 0, bigger, 1, result.size)
bigger[0] = 0x01
return bigger
}
return result
}
private fun subtract(`val`: Long, little: IntArray): IntArray {
val highWord = `val`.ushr(32).toInt()
if (highWord == 0) {
val result = IntArray(1)
result[0] = (`val` - (little[0].toLong() and LONG_MASK)).toInt()
return result
} else {
val result = IntArray(2)
if (little.size == 1) {
val difference = (`val`.toInt().toLong() and LONG_MASK) - (little[0].toLong() and LONG_MASK)
result[1] = difference.toInt()
// Subtract remainder of longer number while borrow propagates
val borrow = difference shr 32 != 0L
if (borrow) {
result[0] = highWord - 1
} else { // Copy remainder of longer number
result[0] = highWord
}
return result
} else { // little.length == 2
var difference = (`val`.toInt().toLong() and LONG_MASK) - (little[1].toLong() and LONG_MASK)
result[1] = difference.toInt()
difference = (highWord.toLong() and LONG_MASK) - (little[0].toLong() and LONG_MASK) + (difference shr 32)
result[0] = difference.toInt()
return result
}
}
}
/**
* Subtracts the contents of the second argument (val) from the
* first (big). The first int array (big) must represent a larger number
* than the second. This method allocates the space necessary to hold the
* answer.
* assumes val >= 0
*/
private fun subtract(big: IntArray, `val`: Long): IntArray {
val highWord = `val`.ushr(32).toInt()
var bigIndex = big.size
val result = IntArray(bigIndex)
var difference: Long = 0
if (highWord == 0) {
difference = (big[--bigIndex].toLong() and LONG_MASK) - `val`
result[bigIndex] = difference.toInt()
} else {
difference = (big[--bigIndex].toLong() and LONG_MASK) - (`val` and LONG_MASK)
result[bigIndex] = difference.toInt()
difference = (big[--bigIndex].toLong() and LONG_MASK) - (highWord.toLong() and LONG_MASK) + (difference shr 32)
result[bigIndex] = difference.toInt()
}
// Subtract remainder of longer number while borrow propagates
var borrow = difference shr 32 != 0L
while (bigIndex > 0 && borrow) {
result[--bigIndex] = big[bigIndex] - 1
borrow = result[bigIndex] == -1
}
// Copy remainder of longer number
while (bigIndex > 0)
result[--bigIndex] = big[bigIndex]
return result
}
/**
* Subtracts the contents of the second int arrays (little) from the
* first (big). The first int array (big) must represent a larger number
* than the second. This method allocates the space necessary to hold the
* answer.
*/
private fun subtract(big: IntArray, little: IntArray): IntArray {
var bigIndex = big.size
val result = IntArray(bigIndex)
var littleIndex = little.size
var difference: Long = 0
// Subtract common parts of both numbers
while (littleIndex > 0) {
difference =
(big[--bigIndex].toLong() and LONG_MASK) - (little[--littleIndex].toLong() and LONG_MASK) + (difference shr 32)
result[bigIndex] = difference.toInt()
}
// Subtract remainder of longer number while borrow propagates
var borrow = difference shr 32 != 0L
while (bigIndex > 0 && borrow) {
result[--bigIndex] = big[bigIndex] - 1
borrow = result[bigIndex] == -1
}
// Copy remainder of longer number
while (bigIndex > 0)
result[--bigIndex] = big[bigIndex]
return result
}
private fun multiplyByInt(x: IntArray, y: Int, sign: Int): BigInteger {
if (y.bitCount() == 1) {
return BigInteger(
shl(
x,
y.numberOfTrailingZeros()
), sign
)
}
val xlen = x.size
var rmag = IntArray(xlen + 1)
var carry: Long = 0
val yl = y.toLong() and LONG_MASK
var rstart = rmag.size - 1
for (i in xlen - 1 downTo 0) {
val product = (x[i].toLong() and LONG_MASK) * yl + carry
rmag[rstart--] = product.toInt()
carry = product.ushr(32)
}
if (carry == 0L) {
rmag = rmag.copyOfRange(1, rmag.size)
} else {
rmag[rstart] = carry.toInt()
}
return BigInteger(rmag, sign)
}
/**
* Multiplies int arrays x and y to the specified lengths and places
* the result into z. There will be no leading zeros in the resultant array.
*/
private fun multiplyToLen(x: IntArray, xlen: Int, y: IntArray, ylen: Int, z: IntArray?): IntArray {
multiplyToLenCheck(x, xlen)
multiplyToLenCheck(y, ylen)
return implMultiplyToLen(x, xlen, y, ylen, z)
}
private fun implMultiplyToLen(x: IntArray, xlen: Int, y: IntArray, ylen: Int, z: IntArray?): IntArray {
var z = z
val xstart = xlen - 1
val ystart = ylen - 1
if (z == null || z.size < xlen + ylen)
z = IntArray(xlen + ylen)
var carry: Long = 0
run {
var j = ystart
var k = ystart + 1 + xstart
while (j >= 0) {
val product = (y[j].toLong() and LONG_MASK) * (x[xstart].toLong() and LONG_MASK) + carry
z[k] = product.toInt()
carry = product.ushr(32)
j--
k--
}
}
z[xstart] = carry.toInt()
for (i in xstart - 1 downTo 0) {
carry = 0
var j = ystart
var k = ystart + 1 + i
while (j >= 0) {
val product = (y[j].toLong() and LONG_MASK) * (x[i].toLong() and LONG_MASK) +
(z[k].toLong() and LONG_MASK) + carry
z[k] = product.toInt()
carry = product.ushr(32)
j--
k--
}
z[i] = carry.toInt()
}
return z
}
private fun multiplyToLenCheck(array: IntArray, length: Int) {
if (length <= 0) {
return // not an error because multiplyToLen won't execute if len <= 0
}
if (length > array.size) {
throw IndexOutOfBoundsException("${length - 1}")
}
}
/**
* Multiplies two BigIntegers using the Karatsuba multiplication
* algorithm. This is a recursive div-and-conquer algorithm which is
* more efficient for large numbers than what is commonly called the
* "grade-school" algorithm used in multiplyToLen. If the numbers to be
* multiplied have length n, the "grade-school" algorithm has an
* asymptotic complexity of O(n^2). In contrast, the Karatsuba algorithm
* has complexity of O(n^(log2(3))), or O(n^1.585). It achieves this
* increased performance by doing 3 multiplies instead of 4 when
* evaluating the product. As it has some overhead, should be used when
* both numbers are larger than a certain threshold (found
* experimentally).
*
* See: http://en.wikipedia.org/wiki/Karatsuba_algorithm
*/
private fun multiplyKaratsuba(x: BigInteger, y: BigInteger): BigInteger {
val xlen = x._mag.size
val ylen = y._mag.size
// The number of ints in each half of the number.
val half = (max(xlen, ylen) + 1) / 2
// xl and yl are the lower halves of x and y respectively,
// xh and yh are the upper halves.
val xl = x.getLower(half)
val xh = x.getUpper(half)
val yl = y.getLower(half)
val yh = y.getUpper(half)
val p1 = xh.times(yh) // p1 = xh*yh
val p2 = xl.times(yl) // p2 = xl*yl
// p3=(xh+xl)*(yh+yl)
val p3 = xh.plus(xl).times(yh.plus(yl))
// result = p1 * 2^(32*2*half) + (p3 - p1 - p2) * 2^(32*half) + p2
val result = p1.shl(32 * half).plus(p3.minus(p1).minus(p2)).shl(32 * half).plus(p2)
return if (x._signum != y._signum) {
result.unaryMinus()
} else {
result
}
}
/**
* Multiplies two BigIntegers using a 3-way Toom-Cook multiplication
* algorithm. This is a recursive div-and-conquer algorithm which is
* more efficient for large numbers than what is commonly called the
* "grade-school" algorithm used in multiplyToLen. If the numbers to be
* multiplied have length n, the "grade-school" algorithm has an
* asymptotic complexity of O(n^2). In contrast, 3-way Toom-Cook has a
* complexity of about O(n^1.465). It achieves this increased asymptotic
* performance by breaking each number into three parts and by doing 5
* multiplies instead of 9 when evaluating the product. Due to overhead
* (additions, shifts, and one division) in the Toom-Cook algorithm, it
* should only be used when both numbers are larger than a certain
* threshold (found experimentally). This threshold is generally larger
* than that for Karatsuba multiplication, so this algorithm is generally
* only used when numbers become significantly larger.
*
* The algorithm used is the "optimal" 3-way Toom-Cook algorithm outlined
* by Marco Bodrato.
*
* See: http://bodrato.it/toom-cook/
* http://bodrato.it/papers/#WAIFI2007
*
* "Towards Optimal Toom-Cook Multiplication for Univariate and
* Multivariate Polynomials in Characteristic 2 and 0." by Marco BODRATO;
* In C.Carlet and B.Sunar, Eds., "WAIFI'07 proceedings", p. 116-133,
* LNCS #4547. Springer, Madrid, Spain, June 21-22, 2007.
*
*/
private fun multiplyToomCook3(a: BigInteger, b: BigInteger): BigInteger {
val alen = a._mag.size
val blen = b._mag.size
val largest = max(alen, blen)
// k is the size (in ints) of the lower-order slices.
val k = (largest + 2) / 3 // Equal to ceil(largest/3)
// r is the size (in ints) of the highest-order slice.
val r = largest - 2 * k
// Obtain slices of the numbers. a2 and b2 are the most significant
// bits of the numbers a and b, and a0 and b0 the least significant.
val a0: BigInteger
val a1: BigInteger
val a2: BigInteger
val b0: BigInteger
val b1: BigInteger
val b2: BigInteger
a2 = a.getToomSlice(k, r, 0, largest)
a1 = a.getToomSlice(k, r, 1, largest)
a0 = a.getToomSlice(k, r, 2, largest)
b2 = b.getToomSlice(k, r, 0, largest)
b1 = b.getToomSlice(k, r, 1, largest)
b0 = b.getToomSlice(k, r, 2, largest)
val v0: BigInteger
val v1: BigInteger
val v2: BigInteger
val vm1: BigInteger
val vinf: BigInteger
var t1: BigInteger
var t2: BigInteger
var tm1: BigInteger
var da1: BigInteger
var db1: BigInteger
v0 = a0.times(b0)
da1 = a2.plus(a0)
db1 = b2.plus(b0)
vm1 = da1.minus(a1).times(db1.minus(b1))
da1 = da1.plus(a1)
db1 = db1.plus(b1)
v1 = da1.times(db1)
v2 = da1.plus(a2).shl(1).minus(a0).times(
db1.plus(b2).shl(1).minus(b0)
)
vinf = a2.times(b2)
// The algorithm requires two divisions by 2 and one by 3.
// All divisions are known to be exact, that is, they do not produce
// remainders, and all results are positive. The divisions by 2 are
// implemented as right shifts which are relatively efficient, leaving
// only an exact division by 3, which is done by a specialized
// linear-time algorithm.
t2 = v2.minus(vm1).exactDivideBy3()
tm1 = v1.minus(vm1).shr(1)
t1 = v1.minus(v0)
t2 = t2.minus(t1).shr(1)
t1 = t1.minus(tm1).minus(vinf)
t2 = t2.minus(vinf.shl(1))
tm1 = tm1.minus(t2)
// Number of bits to shift left.
val ss = k * 32
val result = vinf.shl(ss).plus(t2).shl(ss).plus(t1).shl(ss).plus(tm1).shl(ss).plus(v0)
return if (a._signum != b._signum) {
result.unaryMinus()
} else {
result
}
}
/**
* Squares the contents of the int array x. The result is placed into the
* int array z. The contents of x are not changed.
*/
private fun squareToLen(x: IntArray, len: Int, z: IntArray?): IntArray {
var z = z
val zlen = len shl 1
if (z == null || z.size < zlen)
z = IntArray(zlen)
// Execute checks before calling intrinsified method.
implSquareToLenChecks(x, len, z, zlen)
return implSquareToLen(x, len, z, zlen)
}
/**
* Parameters validation.
*/
private fun implSquareToLenChecks(x: IntArray, len: Int, z: IntArray, zlen: Int) {
if (len < 1) {
throw IllegalArgumentException("invalid input length: $len")
}
if (len > x.size) {
throw IllegalArgumentException(
"input length out of bound: " +
len + " > " + x.size
)
}
if (len * 2 > z.size) {
throw IllegalArgumentException(
"input length out of bound: " +
len * 2 + " > " + z.size
)
}
if (zlen < 1) {
throw IllegalArgumentException("invalid input length: $zlen")
}
if (zlen > z.size) {
throw IllegalArgumentException(
"input length out of bound: " +
len + " > " + z.size
)
}
}
/**
* Java Runtime may use intrinsic for this method.
*/
private fun implSquareToLen(x: IntArray, len: Int, z: IntArray, zlen: Int): IntArray {
/*
* The algorithm used here is adapted from Colin Plumb's C library.
* Technique: Consider the partial products in the multiplication
* of "abcde" by itself:
*
* a b c d e
* * a b c d e
* ==================
* ae be ce de ee
* ad bd cd dd de
* ac bc cc cd ce
* ab bb bc bd be
* aa ab ac ad ae
*
* Note that everything above the main diagonal:
* ae be ce de = (abcd) * e
* ad bd cd = (abc) * d
* ac bc = (ab) * c
* ab = (a) * b
*
* is a copy of everything below the main diagonal:
* de
* cd ce
* bc bd be
* ab ac ad ae
*
* Thus, the sum is 2 * (off the diagonal) + diagonal.
*
* This is accumulated beginning with the diagonal (which
* consist of the squares of the digits of the input), which is then
* divided by two, the off-diagonal added, and multiplied by two
* again. The low bit is simply a copy of the low bit of the
* input, so it doesn't need special care.
*/
// Store the squares, right shifted one bit (i.e., divided by 2)
var lastProductLowWord = 0
run {
var j = 0
var i = 0
while (j < len) {
val piece = x[j].toLong() and LONG_MASK
val product = piece * piece
z[i++] = lastProductLowWord shl 31 or product.ushr(33).toInt()
z[i++] = product.ushr(1).toInt()
lastProductLowWord = product.toInt()
j++
}
}
// Add in off-diagonal sums
var i = len
var offset = 1
while (i > 0) {
var t = x[i - 1]
t = mulAdd(z, x, offset, i - 1, t)
addOne(z, offset - 1, i, t)
i--
offset += 2
}
// Shift back up and set low bit
primitiveLeftShift(z, zlen, 1)
z[zlen - 1] = z[zlen - 1] or (x[len - 1] and 1)
return z
}
/**
* Package private method to return bit length for an integer.
*/
internal fun bitLengthForInt(n: Int): Int {
return 32 - n.numberOfLeadingZeros()
}
/**
* Left shift int array a up to len by n bits. Returns the array that
* results from the shift since space may have to be reallocated.
*/
private fun leftShift(a: IntArray, len: Int, n: Int): IntArray {
val nInts = n.ushr(5)
val nBits = n and 0x1F
val bitsInHighWord = bitLengthForInt(a[0])
// If shift can be done without recopy, do so
if (n <= 32 - bitsInHighWord) {
primitiveLeftShift(a, len, nBits)
return a
} else { // Array must be resized
if (nBits <= 32 - bitsInHighWord) {
val result = IntArray(nInts + len)
arrayCopy(a, 0, result, 0, len)
primitiveLeftShift(result, result.size, nBits)
return result
} else {
val result = IntArray(nInts + len + 1)
arrayCopy(a, 0, result, 0, len)
primitiveRightShift(result, result.size, 32 - nBits)
return result
}
}
}
// shifts a up to len right n bits assumes no leading zeros, 0 0) {
val b = c
c = a[i - 1]
a[i] = c shl n2 or b.ushr(n)
i--
}
a[0] = a[0] ushr n
}
// shifts a up to len left n bits assumes no leading zeros, 0<=n<32
internal fun primitiveLeftShift(a: IntArray, len: Int, n: Int) {
if (len == 0 || n == 0)
return
val n2 = 32 - n
var i = 0
var c = a[i]
val m = i + len - 1
while (i < m) {
val b = c
c = a[i + 1]
a[i] = b shl n or c.ushr(n2)
i++
}
a[len - 1] = a[len - 1] shl n
}
/**
* Calculate bitlength of contents of the first len elements an int array,
* assuming there are no leading zero ints.
*/
private fun bitLength(`val`: IntArray, len: Int): Int {
return if (len == 0) 0 else (len - 1 shl 5) + bitLengthForInt(`val`[0])
}
// Montgomery multiplication. These are wrappers for
// implMontgomeryXX routines which are expected to be replaced by
// virtual machine intrinsics. We don't use the intrinsics for
// very large operands: MONTGOMERY_INTRINSIC_THRESHOLD should be
// larger than any reasonable crypto key.
private fun montgomeryMultiply(
a: IntArray, b: IntArray, n: IntArray, len: Int, inv: Long,
product: IntArray?
): IntArray {
var product = product
implMontgomeryMultiplyChecks(a, b, n, len, product)
if (len > MONTGOMERY_INTRINSIC_THRESHOLD) {
// Very long argument: do not use an intrinsic
product = multiplyToLen(a, len, b, len, product)
return montReduce(product, n, len, inv.toInt())
} else {
return implMontgomeryMultiply(
a,
b,
n,
len,
inv,
materialize(product, len)
)
}
}
private fun montgomerySquare(
a: IntArray, n: IntArray, len: Int, inv: Long,
product: IntArray?
): IntArray {
var product = product
implMontgomeryMultiplyChecks(a, a, n, len, product)
if (len > MONTGOMERY_INTRINSIC_THRESHOLD) {
// Very long argument: do not use an intrinsic
product = squareToLen(a, len, product)
return montReduce(product, n, len, inv.toInt())
} else {
return implMontgomerySquare(
a,
n,
len,
inv,
materialize(product, len)
)
}
}
private fun implMontgomeryMultiplyChecks(a: IntArray, b: IntArray, n: IntArray, len: Int, product: IntArray?) {
if (len % 2 != 0) {
throw IllegalArgumentException("input array length must be even: $len")
}
if (len < 1) {
throw IllegalArgumentException("invalid input length: $len")
}
if (len > a.size ||
len > b.size ||
len > n.size ||
product != null && len > product.size
) {
throw IllegalArgumentException("input array length out of bound: $len")
}
}
// Make sure that the int array z (which is expected to contain
// the result of a Montgomery multiplication) is present and
// sufficiently large.
private fun materialize(z: IntArray?, len: Int): IntArray {
var z = z
if (z == null || z.size < len)
z = IntArray(len)
return z
}
// These methods are intended to be be replaced by virtual machine
// intrinsics.
private fun implMontgomeryMultiply(
a: IntArray, b: IntArray, n: IntArray, len: Int,
inv: Long, product: IntArray
): IntArray {
var product = product
product = multiplyToLen(a, len, b, len, product)
return montReduce(product, n, len, inv.toInt())
}
private fun implMontgomerySquare(
a: IntArray, n: IntArray, len: Int,
inv: Long, product: IntArray
): IntArray {
var product = product
product = squareToLen(a, len, product)
return montReduce(product, n, len, inv.toInt())
}
internal var bnExpModThreshTable = intArrayOf(7, 25, 81, 241, 673, 1793, Int.MAX_VALUE) // Sentinel
/**
* Montgomery reduce n, modulo rem. This reduces modulo rem and divides
* by 2^(32*mlen). Adapted from Colin Plumb's C library.
*/
private fun montReduce(n: IntArray, mod: IntArray, mlen: Int, inv: Int): IntArray {
var c = 0
var len = mlen
var offset = 0
do {
val nEnd = n[n.size - 1 - offset]
val carry = mulAdd(n, mod, offset, mlen, inv * nEnd)
c += addOne(n, offset, mlen, carry)
offset++
} while (--len > 0)
while (c > 0)
c += subN(n, mod, mlen)
while (intArrayCmpToLen(n, mod, mlen) >= 0)
subN(n, mod, mlen)
return n
}
/*
* Returns -1, 0 or +1 as big-endian unsigned int array arg1 is less than,
* equal to, or greater than arg2 up to length len.
*/
private fun intArrayCmpToLen(arg1: IntArray, arg2: IntArray, len: Int): Int {
for (i in 0 until len) {
val b1 = arg1[i].toLong() and LONG_MASK
val b2 = arg2[i].toLong() and LONG_MASK
if (b1 < b2)
return -1
if (b1 > b2)
return 1
}
return 0
}
/**
* Subtracts two numbers of same length, returning borrow.
*/
private fun subN(a: IntArray, b: IntArray, len: Int): Int {
var len = len
var sum: Long = 0
while (--len >= 0) {
sum = (a[len].toLong() and LONG_MASK) - (b[len].toLong() and LONG_MASK) + (sum shr 32)
a[len] = sum.toInt()
}
return (sum shr 32).toInt()
}
/**
* Multiply an array by one word k and plus to result, return the carry
*/
internal fun mulAdd(out: IntArray, `in`: IntArray, offset: Int, len: Int, k: Int): Int {
implMulAddCheck(out, `in`, offset, len, k)
return implMulAdd(out, `in`, offset, len, k)
}
/**
* Parameters validation.
*/
@Suppress("UNUSED_PARAMETER")
private fun implMulAddCheck(out: IntArray, `in`: IntArray, offset: Int, len: Int, k: Int) {
if (len > `in`.size) {
throw IllegalArgumentException("input length is out of bound: " + len + " > " + `in`.size)
}
if (offset < 0) {
throw IllegalArgumentException("input offset is invalid: $offset")
}
if (offset > out.size - 1) {
throw IllegalArgumentException("input offset is out of bound: " + offset + " > " + (out.size - 1))
}
if (len > out.size - offset) {
throw IllegalArgumentException("input len is out of bound: " + len + " > " + (out.size - offset))
}
}
/**
* Java Runtime may use intrinsic for this method.
*/
private fun implMulAdd(out: IntArray, `in`: IntArray, offset: Int, len: Int, k: Int): Int {
var offset = offset
val kLong = k.toLong() and LONG_MASK
var carry: Long = 0
offset = out.size - offset - 1
for (j in len - 1 downTo 0) {
val product = (`in`[j].toLong() and LONG_MASK) * kLong +
(out[offset].toLong() and LONG_MASK) + carry
out[offset--] = product.toInt()
carry = product.ushr(32)
}
return carry.toInt()
}
/**
* Add one word to the number a mlen words into a. Return the resulting
* carry.
*/
internal fun addOne(a: IntArray, offset: Int, mlen: Int, carry: Int): Int {
var offset = offset
var mlen = mlen
offset = a.size - 1 - mlen - offset
val t = (a[offset].toLong() and LONG_MASK) + (carry.toLong() and LONG_MASK)
a[offset] = t.toInt()
if (t.ushr(32) == 0L)
return 0
while (--mlen >= 0) {
if (--offset < 0) { // Carry out of number
return 1
} else {
a[offset]++
if (a[offset] != 0)
return 0
}
}
return 1
}
/**
* Returns a magnitude array whose value is `(_mag << n)`.
* The shift distance, `n`, is considered unnsigned.
* (Computes `this * 2n`.)
*
* @param mag magnitude, the most-significant int (`_mag[0]`) must be non-zero.
* @param n unsigned shift distance, in bits.
* @return `_mag << n`
*/
private fun shl(mag: IntArray, n: Int): IntArray {
val nInts = n.ushr(5)
val nBits = n and 0x1f
val magLen = mag.size
var newMag: IntArray? = null
if (nBits == 0) {
newMag = IntArray(magLen + nInts)
arrayCopy(mag, 0, newMag, 0, magLen)
} else {
var i = 0
val nBits2 = 32 - nBits
val highBits = mag[0].ushr(nBits2)
if (highBits != 0) {
newMag = IntArray(magLen + nInts + 1)
newMag[i++] = highBits
} else {
newMag = IntArray(magLen + nInts)
}
var j = 0
while (j < magLen - 1)
newMag[i++] = mag[j++] shl nBits or mag[j].ushr(nBits2)
newMag[i] = mag[j] shl nBits
}
return newMag
}
/**
* Converts the specified BigInteger to a string and appends to
* `sb`. This implements the recursive Schoenhage algorithm
* for base conversions.
*
*
* See Knuth, Donald, _The Art of Computer Programming_, Vol. 2,
* Answers to Exercises (4.4) Question 14.
*
* @param u The number to convert to a string.
* @param sb The StringBuilder that will be appended to in place.
* @param radix The base to convert to.
* @param digits The minimum number of digits to pad to.
*/
private fun toString(
u: BigInteger, sb: StringBuilder, radix: Int,
digits: Int
) {
// If we're smaller than a certain threshold, use the smallToString
// method, padding with leading zeroes when necessary.
if (u._mag.size <= SCHOENHAGE_BASE_CONVERSION_THRESHOLD) {
val s = u.smallToString(radix)
// Pad with internal zeros if necessary.
// Don't pad if we're at the beginning of the string.
if (s.length < digits && sb.length > 0) {
for (i in s.length until digits) {
sb.append('0')
}
}
sb.append(s)
return
}
val b: Int
val n: Int
b = u.bitLength
// Calculate a value for n in the equation radix^(2^n) = u
// and subtract 1 from that value. This is used to find the
// cache index that contains the best value to div u.
n = round(ln(b * LOG_TWO / logCache[radix]) / LOG_TWO - 1.0).toInt()
val v = getRadixConversionCache(radix, n)
val results: Array
results = u.divideAndRemainder(v)
val expectedDigits = 1 shl n
// Now recursively build the two halves of each number.
toString(results[0], sb, radix, digits - expectedDigits)
toString(results[1], sb, radix, expectedDigits)
}
/**
* Returns the value radix^(2^exponent) from the cache.
* If this value doesn't already exist in the cache, it is added.
*
*
* This could be changed to a more complicated caching method using
* `Future`.
*/
private fun getRadixConversionCache(radix: Int, exponent: Int): BigInteger {
// volatile read
var cacheLine: Array? = powerCache[radix]
if (exponent < cacheLine!!.size) {
return cacheLine[exponent]
}
val oldLength = cacheLine.size
val cacheLine2 = cacheLine.copyOf(exponent + 1)
for (i in oldLength..exponent) {
cacheLine2[i] = cacheLine2[i - 1]!!.pow(2)
}
var pc = powerCache // volatile read again
if (exponent >= pc[radix]!!.size) {
pc = pc.cloneArray()
pc[radix] = cacheLine2.requireNoNulls()
powerCache = pc // volatile write, publish
}
return cacheLine2[exponent]!!
}
/* zero[i] is a string of i consecutive zeros. */
private val zeros = arrayOfNulls(64)
init {
zeros[63] = "000000000000000000000000000000000000000000000000000000000000000"
for (i in 0..62)
zeros[i] = zeros[63]!!.substring(0, i)
}
/**
* Returns a copy of the input array stripped of any leading zero bytes.
*/
private fun stripLeadingZeroInts(`val`: IntArray): IntArray {
val vlen = `val`.size
var keep: Int
// Find first nonzero byte
keep = 0
while (keep < vlen && `val`[keep] == 0) {
keep++
}
return `val`.copyOfRange(keep, vlen)
}
/**
* Returns the input array stripped of any leading zero bytes.
* Since the source is trusted the copying may be skipped.
*/
private fun trustedStripLeadingZeroInts(`val`: IntArray): IntArray {
val vlen = `val`.size
var keep: Int
// Find first nonzero byte
keep = 0
while (keep < vlen && `val`[keep] == 0) {
keep++
}
return if (keep == 0) `val` else `val`.copyOfRange(keep, vlen)
}
/**
* Returns a copy of the input array stripped of any leading zero bytes.
*/
private fun stripLeadingZeroBytes(a: ByteArray, off: Int, len: Int): IntArray {
val indexBound = off + len
var keep: Int
// Find first nonzero byte
keep = off
while (keep < indexBound && a[keep].toInt() == 0) {
keep++
}
// Allocate new array and copy relevant part of input array
val intLength = (indexBound - keep + 3).ushr(2)
val result = IntArray(intLength)
var b = indexBound - 1
for (i in intLength - 1 downTo 0) {
result[i] = a[b--].toInt() and 0xff
val bytesRemaining = b - keep + 1
val bytesToTransfer = min(3, bytesRemaining)
var j = 8
while (j <= bytesToTransfer shl 3) {
result[i] = result[i] or (a[b--].toInt() and 0xff shl j)
j += 8
}
}
return result
}
/**
* Takes an array a representing a negative 2's-complement number and
* returns the minimal (no leading zero bytes) unsigned whose value is -a.
*/
private fun makePositive(a: ByteArray, off: Int, len: Int): IntArray {
var keep: Int
var k: Int
val indexBound = off + len
// Find first non-sign (0xff) byte of input
keep = off
while (keep < indexBound && a[keep].toInt() == -1) {
keep++
}
/* Allocate output array. If all non-sign bytes are 0x00, we must
* allocate space for one extra output byte. */
k = keep
while (k < indexBound && a[k].toInt() == 0) {
k++
}
val extraByte = if (k == indexBound) 1 else 0
val intLength = (indexBound - keep + extraByte + 3).ushr(2)
val result = IntArray(intLength)
/* Copy one's complement of input into output, leaving extra
* byte (if it exists) == 0x00 */
var b = indexBound - 1
for (i in intLength - 1 downTo 0) {
result[i] = a[b--].toInt() and 0xff
var numBytesToTransfer = min(3, b - keep + 1)
if (numBytesToTransfer < 0)
numBytesToTransfer = 0
var j = 8
while (j <= 8 * numBytesToTransfer) {
result[i] = result[i] or (a[b--].toInt() and 0xff shl j)
j += 8
}
// Mask indicates which bits must be complemented
val mask = (-1).ushr(8 * (3 - numBytesToTransfer))
result[i] = result[i].inv() and mask
}
// Add one to one's complement to generate two's complement
for (i in result.indices.reversed()) {
result[i] = ((result[i].toLong() and LONG_MASK) + 1L).toInt()
if (result[i] != 0)
break
}
return result
}
/**
* Takes an array a representing a negative 2's-complement number and
* returns the minimal (no leading zero ints) unsigned whose value is -a.
*/
private fun makePositive(a: IntArray): IntArray {
var keep: Int
var j: Int
// Find first non-sign (0xffffffff) int of input
keep = 0
while (keep < a.size && a[keep] == -1) {
keep++
}
/* Allocate output array. If all non-sign ints are 0x00, we must
* allocate space for one extra output int. */
j = keep
while (j < a.size && a[j] == 0) {
j++
}
val extraInt = if (j == a.size) 1 else 0
val result = IntArray(a.size - keep + extraInt)
/* Copy one's complement of input into output, leaving extra
* int (if it exists) == 0x00 */
for (i in keep until a.size)
result[i - keep + extraInt] = a[i].inv()
// Add one to one's complement to generate two's complement
var i = result.size - 1
while (++result[i] == 0) {
i--
}
return result
}
/*
* The following two arrays are used for fast String conversions. Both
* are indexed by radix. The first is the number of digits of the given
* radix that can fit in a Java long without "going negative", i.e., the
* highest integer n such that radix**n < 2**63. The second is the
* "long radix" that tears each number into "long digits", each of which
* consists of the number of digits in the corresponding element in
* digitsPerLong (longRadix[i] = i**digitPerLong[i]). Both arrays have
* nonsense values in their 0 and 1 elements, as radixes 0 and 1 are not
* used.
*/
private val digitsPerLong = intArrayOf(
0,
0,
62,
39,
31,
27,
24,
22,
20,
19,
18,
18,
17,
17,
16,
16,
15,
15,
15,
14,
14,
14,
14,
13,
13,
13,
13,
13,
13,
12,
12,
12,
12,
12,
12,
12,
12
)
private val longRadix = arrayOf(
null,
null,
of(0x4000000000000000L),
of(0x383d9170b85ff80bL),
of(0x4000000000000000L),
of(0x6765c793fa10079dL),
of(0x41c21cb8e1000000L),
of(0x3642798750226111L),
of(0x1000000000000000L),
of(0x12bf307ae81ffd59L),
of(0xde0b6b3a7640000L),
of(0x4d28cb56c33fa539L),
of(0x1eca170c00000000L),
of(0x780c7372621bd74dL),
of(0x1e39a5057d810000L),
of(0x5b27ac993df97701L),
of(0x1000000000000000L),
of(0x27b95e997e21d9f1L),
of(0x5da0e1e53c5c8000L),
of(0xb16a458ef403f19L),
of(0x16bcc41e90000000L),
of(0x2d04b7fdd9c0ef49L),
of(0x5658597bcaa24000L),
of(0x6feb266931a75b7L),
of(0xc29e98000000000L),
of(0x14adf4b7320334b9L),
of(0x226ed36478bfa000L),
of(0x383d9170b85ff80bL),
of(0x5a3c23e39c000000L),
of(0x4e900abb53e6b71L),
of(0x7600ec618141000L),
of(0xaee5720ee830681L),
of(0x1000000000000000L),
of(0x172588ad4f5f0981L),
of(0x211e44f7d02c1000L),
of(0x2ee56725f06e5c71L),
of(0x41c21cb8e1000000L)
)
/*
* These two arrays are the integer analogue of above.
*/
private val digitsPerInt = intArrayOf(
0,
0,
30,
19,
15,
13,
11,
11,
10,
9,
9,
8,
8,
8,
8,
7,
7,
7,
7,
7,
7,
7,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
5
)
private val intRadix = intArrayOf(
0,
0,
0x40000000,
0x4546b3db,
0x40000000,
0x48c27395,
0x159fd800,
0x75db9c97,
0x40000000,
0x17179149,
0x3b9aca00,
0xcc6db61,
0x19a10000,
0x309f1021,
0x57f6c100,
0xa2f1b6f,
0x10000000,
0x18754571,
0x247dbc80,
0x3547667b,
0x4c4b4000,
0x6b5a6e1d,
0x6c20a40,
0x8d2d931,
0xb640000,
0xe8d4a51,
0x1269ae40,
0x17179149,
0x1cb91000,
0x23744899,
0x2b73a840,
0x34e63b41,
0x40000000,
0x4cfa3cc1,
0x5c13d840,
0x6d91b519,
0x39aa400
)
}
}
/**
* Translates a byte array containing the two's-complement binary
* representation of a BigInteger into a BigInteger. The input array is
* assumed to be in *big-endian* byte-order: the most significant
* byte is in the zeroth element. The `val` array is assumed to be
* unchanged for the duration of the constructor call.
*
* @param val big-endian two's-complement binary representation of a
* BigInteger.
* @throws NumberFormatException `val` is zero bytes long.
*/
/**
* Translates the sign-magnitude representation of a BigInteger into a
* BigInteger. The sign is represented as an integer _signum value: -1 for
* negative, 0 for zero, or 1 for positive. The magnitude is a byte array
* in *big-endian* byte-order: the most significant byte is the
* zeroth element. A zero-length magnitude array is permissible, and will
* result in a BigInteger value of 0, whether _signum is -1, 0 or 1. The
* `magnitude` array is assumed to be unchanged for the duration of
* the constructor call.
*
* @param _signum _signum of the number (-1 for negative, 0 for zero, 1
* for positive).
* @param magnitude big-endian binary representation of the magnitude of
* the number.
* @throws NumberFormatException `_signum` is not one of the three
* legal values (-1, 0, and 1), or `_signum` is 0 and
* `magnitude` contains one or more non-zero bytes.
*/
/**
* Translates the decimal String representation of a BigInteger into a
* BigInteger. The String representation consists of an optional minus
* sign followed by a sequence of one or more decimal digits. The
* character-to-digit mapping is provided by `Character.digit`.
* The String may not contain any extraneous characters (whitespace, for
* example).
*
* @param val decimal String representation of BigInteger.
* @throws NumberFormatException `val` is not a valid representation
* of a BigInteger.
* @see Character.digit
*/
© 2015 - 2025 Weber Informatics LLC | Privacy Policy