From 8121086032af26ae3d0fd232fe6e36c4444b561c Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Tue, 2 Jan 2024 10:11:28 +0100 Subject: [PATCH] fix: code style, according to new version of kt-lint --- .editorconfig | 7 +- gradle/libs.versions.toml | 2 +- settings.gradle.kts | 6 +- .../kotlin/org/gciatto/kt/math/BigDecimal.kt | 106 +- .../kotlin/org/gciatto/kt/math/BigInteger.kt | 35 +- .../org/gciatto/kt/math/BigIntegerRange.kt | 19 +- .../kotlin/org/gciatto/kt/math/BitSieve.kt | 25 +- .../org/gciatto/kt/math/CommonBigDecimal.kt | 1553 ++++++++++------- .../org/gciatto/kt/math/CommonBigInteger.kt | 877 ++++++---- .../kotlin/org/gciatto/kt/math/Lock.kt | 5 +- .../kotlin/org/gciatto/kt/math/MathContext.kt | 4 +- .../org/gciatto/kt/math/MutableBigInteger.kt | 276 ++- .../org/gciatto/kt/math/RoundingMode.kt | 14 +- .../kt/math/SignedMutableBigInteger.kt | 1 - .../kotlin/org/gciatto/kt/math/Utils.kt | 128 +- .../gciatto/kt/math/AbstractIntBenchmark.kt | 20 +- .../kotlin/org/gciatto/kt/math/Assertions.kt | 14 +- .../kotlin/org/gciatto/kt/math/Contants.kt | 14 +- .../kotlin/org/gciatto/kt/math/KtIntAlgos.kt | 42 +- .../org/gciatto/kt/math/TestDecimals.kt | 61 +- .../org/gciatto/kt/math/TestIntegers.kt | 1 - .../kotlin/org/gciatto/kt/math/JsUtils.kt | 90 +- src/jsMain/kotlin/org/gciatto/kt/math/Lock.kt | 5 +- .../org/gciatto/kt/math/ActualConstants.kt | 35 +- .../gciatto/kt/math/JavaBigDecimalAdapter.kt | 291 +-- .../gciatto/kt/math/JavaBigIntegerAdapter.kt | 45 +- .../kotlin/org/gciatto/kt/math/JvmUtils.kt | 150 +- .../kotlin/org/gciatto/kt/math/Lock.kt | 5 +- .../org/gciatto/kt/math/ActualConstants.kt | 35 +- .../kotlin/org/gciatto/kt/math/JvmIntAlgos.kt | 48 +- .../org/gciatto/kt/math/JvmIntBenchmark.kt | 2 +- .../org/gciatto/kt/math/TestRoundingMode.kt | 16 +- 32 files changed, 2439 insertions(+), 1493 deletions(-) diff --git a/.editorconfig b/.editorconfig index a0a13a6..d1cf045 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,3 +1,6 @@ +root = true + [*.{kt,kts}] -ktlint_disabled_rules=import-ordering -max_line_length=120 +max_line_length = 120 +ktlint_standard_property-naming = disabled +# ktlint_standard_discouraged-comment-location = disabled \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0788cd0..63a2ae8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ kotlin = "1.9.22" jvm = "1.8" node = "16-latest" -ktMpp = "4.0.3" +ktMpp = "4.1.0" [libraries] kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } diff --git a/settings.gradle.kts b/settings.gradle.kts index a8ef04f..49b6fc0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,8 +14,10 @@ plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0" } -fun tag(format: String, vararg properties: String): String = - format.format(*properties.map { System.getProperty(it) ?: error("Missing property $it") }.toTypedArray()) +fun tag( + format: String, + vararg properties: String, +): String = format.format(*properties.map { System.getProperty(it) ?: error("Missing property $it") }.toTypedArray()) val ci = !System.getenv("CI").isNullOrBlank() val ciTag = if (ci) "CI" else "Local" diff --git a/src/commonMain/kotlin/org/gciatto/kt/math/BigDecimal.kt b/src/commonMain/kotlin/org/gciatto/kt/math/BigDecimal.kt index 7871db2..e1f55ae 100644 --- a/src/commonMain/kotlin/org/gciatto/kt/math/BigDecimal.kt +++ b/src/commonMain/kotlin/org/gciatto/kt/math/BigDecimal.kt @@ -91,7 +91,10 @@ interface BigDecimal : Comparable { * @since 1.5 */ @JsName("plusWithContext") - fun plus(augend: BigDecimal?, mc: MathContext): BigDecimal + fun plus( + augend: BigDecimal?, + mc: MathContext, + ): BigDecimal /** * Returns a [BigDecimal] whose value is `(this - @@ -119,7 +122,10 @@ interface BigDecimal : Comparable { * @since 1.5 */ @JsName("minusWithContext") - fun minus(subtrahend: BigDecimal, mc: MathContext): BigDecimal + fun minus( + subtrahend: BigDecimal, + mc: MathContext, + ): BigDecimal /** * Returns a [BigDecimal] whose value is `(this @@ -144,7 +150,10 @@ interface BigDecimal : Comparable { * @since 1.5 */ @JsName("timesWithContext") - fun times(multiplicand: BigDecimal, mc: MathContext): BigDecimal + fun times( + multiplicand: BigDecimal, + mc: MathContext, + ): BigDecimal /** * Returns a [BigDecimal] whose value is `(this / @@ -177,7 +186,10 @@ interface BigDecimal : Comparable { * @since 1.5 */ @JsName("divWithContext") - fun div(divisor: BigDecimal, mc: MathContext): BigDecimal? + fun div( + divisor: BigDecimal, + mc: MathContext, + ): BigDecimal? /** * Returns a [BigDecimal] whose value is the integer part @@ -214,7 +226,10 @@ interface BigDecimal : Comparable { * @author Joseph D. Darcy */ @JsName("divideToIntegralValueWithContext") - fun divideToIntegralValue(divisor: BigDecimal, mc: MathContext): BigDecimal + fun divideToIntegralValue( + divisor: BigDecimal, + mc: MathContext, + ): BigDecimal /** * Returns a [BigDecimal] whose value is `(this % divisor)`. @@ -259,7 +274,10 @@ interface BigDecimal : Comparable { * @since 1.5 */ @JsName("remWithContext") - fun rem(divisor: BigDecimal, mc: MathContext): BigDecimal + fun rem( + divisor: BigDecimal, + mc: MathContext, + ): BigDecimal /** * Returns a two-element [BigDecimal] array containing the @@ -313,7 +331,10 @@ interface BigDecimal : Comparable { * @since 1.5 */ @JsName("divideAndRemainderWithContext") - fun divideAndRemainder(divisor: BigDecimal, mc: MathContext): Pair + fun divideAndRemainder( + divisor: BigDecimal, + mc: MathContext, + ): Pair /** * Returns an approximation to the square root of `this` @@ -423,7 +444,10 @@ interface BigDecimal : Comparable { * @since 1.5 */ @JsName("powWithContext") - fun pow(n: Int, mc: MathContext): BigDecimal? + fun pow( + n: Int, + mc: MathContext, + ): BigDecimal? /** * Returns a [BigDecimal] whose value is the absolute value @@ -546,7 +570,10 @@ interface BigDecimal : Comparable { * @since 1.5 */ @JsName("setScaleRounding") - fun setScale(newScale: Int, roundingMode: RoundingMode): BigDecimal + fun setScale( + newScale: Int, + roundingMode: RoundingMode, + ): BigDecimal /** * Returns a [BigDecimal] whose _scale is the specified @@ -593,10 +620,13 @@ interface BigDecimal : Comparable { * @see .ROUND_UNNECESSARY */ @Deprecated( - "The method {@link #setScale(int, RoundingMode)} should be used in preference to this legacy method." + "The method {@link #setScale(int, RoundingMode)} should be used in preference to this legacy method.", ) @JsName("setScaleInt") - fun setScale(newScale: Int, roundingMode: Int): BigDecimal + fun setScale( + newScale: Int, + roundingMode: Int, + ): BigDecimal /** * Returns a [BigDecimal] whose _scale is the specified @@ -870,7 +900,6 @@ interface BigDecimal : Comparable { * @return this [BigDecimal] converted to a `long`. * @jls 5.1.3 Narrowing Primitive Conversion */ - /*override*/ @JsName("toLong") fun toLong(): Long @@ -906,19 +935,15 @@ interface BigDecimal : Comparable { * @return this [BigDecimal] converted to an `int`. * @jls 5.1.3 Narrowing Primitive Conversion */ - /*override*/ @JsName("toInt") fun toInt(): Int - /*override*/ @JsName("toByte") fun toByte(): Byte - /*override*/ @JsName("toChar") fun toChar(): Char - /*override*/ @JsName("toShort") fun toShort(): Short @@ -983,7 +1008,6 @@ interface BigDecimal : Comparable { * @return this [BigDecimal] converted to a `float`. * @jls 5.1.3 Narrowing Primitive Conversion */ - /*override*/ @JsName("toFloat") fun toFloat(): Float @@ -1003,7 +1027,6 @@ interface BigDecimal : Comparable { * @return this [BigDecimal] converted to a `double`. * @jls 5.1.3 Narrowing Primitive Conversion */ - /*override*/ @JsName("toDouble") fun toDouble(): Double @@ -1093,7 +1116,10 @@ interface BigDecimal : Comparable { */ @JvmStatic @JsName("ofScaledLong") - fun of(unscaledVal: Long, scale: Int): BigDecimal = bigDecimalOf(unscaledVal, scale) + fun of( + unscaledVal: Long, + scale: Int, + ): BigDecimal = bigDecimalOf(unscaledVal, scale) /** * Translates a `long` value into a [BigDecimal] @@ -1108,7 +1134,11 @@ interface BigDecimal : Comparable { */ @JvmStatic @JsName("ofScaledLongWithPrecision") - fun of(unscaledVal: Long, scale: Int, prec: Int): BigDecimal = bigDecimalOf(unscaledVal, scale, prec) + fun of( + unscaledVal: Long, + scale: Int, + prec: Int, + ): BigDecimal = bigDecimalOf(unscaledVal, scale, prec) @JvmStatic @JsName("ofInt") @@ -1120,7 +1150,11 @@ interface BigDecimal : Comparable { @JvmStatic @JsName("ofScaledBigIntegerWithPrecision") - fun of(intVal: BigInteger, scale: Int, prec: Int): BigDecimal = bigDecimalOf(intVal, scale, prec) + fun of( + intVal: BigInteger, + scale: Int, + prec: Int, + ): BigDecimal = bigDecimalOf(intVal, scale, prec) /** * Translates a `double` into a [BigDecimal], using @@ -1141,29 +1175,47 @@ interface BigDecimal : Comparable { @JvmStatic @JsName("ofDouble") @JvmOverloads - fun of(`val`: Double, ctx: MathContext? = null): BigDecimal = bigDecimalOf(`val`, ctx) + fun of( + `val`: Double, + ctx: MathContext? = null, + ): BigDecimal = bigDecimalOf(`val`, ctx) @JvmStatic @JsName("ofFloat") @JvmOverloads - fun of(`val`: Float, ctx: MathContext? = null): BigDecimal = bigDecimalOf(`val`, ctx) + fun of( + `val`: Float, + ctx: MathContext? = null, + ): BigDecimal = bigDecimalOf(`val`, ctx) @JvmStatic @JsName("parse") @JvmOverloads - fun of(`val`: String, ctx: MathContext? = null): BigDecimal = bigDecimalOf(`val`, ctx) + fun of( + `val`: String, + ctx: MathContext? = null, + ): BigDecimal = bigDecimalOf(`val`, ctx) @JvmStatic @JsName("ofBigInteger") @JvmOverloads - fun of(`val`: BigInteger, ctx: MathContext? = null): BigDecimal = bigDecimalOf(`val`, ctx) + fun of( + `val`: BigInteger, + ctx: MathContext? = null, + ): BigDecimal = bigDecimalOf(`val`, ctx) @JvmStatic @JsName("ofIntWithContext") - fun of(`val`: Int, ctx: MathContext): BigDecimal = bigDecimalOf(`val`, ctx) + fun of( + `val`: Int, + ctx: MathContext, + ): BigDecimal = bigDecimalOf(`val`, ctx) @JvmStatic @JsName("ofWithContext") - fun of(`val`: Long, ctx: MathContext): BigDecimal = bigDecimalOf(`val`, ctx) + fun of( + `val`: Long, + ctx: MathContext, + ): BigDecimal = bigDecimalOf(`val`, ctx) } } diff --git a/src/commonMain/kotlin/org/gciatto/kt/math/BigInteger.kt b/src/commonMain/kotlin/org/gciatto/kt/math/BigInteger.kt index ba1489f..1204575 100644 --- a/src/commonMain/kotlin/org/gciatto/kt/math/BigInteger.kt +++ b/src/commonMain/kotlin/org/gciatto/kt/math/BigInteger.kt @@ -287,7 +287,10 @@ interface BigInteger : Comparable { * @see .modInverse */ @JsName("modPow") - fun modPow(exponent: BigInteger, modulus: BigInteger): BigInteger + fun modPow( + exponent: BigInteger, + modulus: BigInteger, + ): BigInteger /** * Returns a BigInteger whose value is `(this`-1 `rem m)`. @@ -428,7 +431,10 @@ interface BigInteger : Comparable { operator fun get(n: Int): Boolean @JsName("set") - operator fun set(n: Int, b: Boolean): BigInteger + operator fun set( + n: Int, + b: Boolean, + ): BigInteger /** * Returns a BigInteger whose value is equivalent to this BigInteger @@ -592,7 +598,6 @@ interface BigInteger : Comparable { * @see BigInteger.toIntExact * @jls 5.1.3 Narrowing Primitive Conversion */ - /*override*/ @JsName("toInt") fun toInt(): Int @@ -612,27 +617,21 @@ interface BigInteger : Comparable { * @see .toLongExact * @jls 5.1.3 Narrowing Primitive Conversion */ - /*override*/ @JsName("toLong") fun toLong(): Long - /*override*/ @JsName("toByte") fun toByte(): Byte - /*override*/ @JsName("toChar") fun toChar(): Char - /*override*/ @JsName("toShort") fun toShort(): Short - /*override*/ @JsName("toFloat") fun toFloat(): Float - /*override*/ @JsName("toDouble") fun toDouble(): Double @@ -758,7 +757,10 @@ interface BigInteger : Comparable { */ @JvmStatic @JsName("probablePrime") - fun probablePrime(bitLength: Int, rnd: Random): BigInteger = bigProbablePrimeInteger(bitLength, rnd) + fun probablePrime( + bitLength: Int, + rnd: Random, + ): BigInteger = bigProbablePrimeInteger(bitLength, rnd) /** * Returns a BigInteger whose value is equal to that of the @@ -785,7 +787,10 @@ interface BigInteger : Comparable { @JsName("parseWithRadix") @JvmStatic - fun of(value: String, radix: Int): BigInteger = bigIntegerOf(value, radix) + fun of( + value: String, + radix: Int, + ): BigInteger = bigIntegerOf(value, radix) /** * Returns a BigInteger with the given two's complement representation. @@ -797,7 +802,11 @@ interface BigInteger : Comparable { fun of(value: IntArray): BigInteger = bigIntegerOf(value) @JsName("ofSlideIntArray") - fun of(signum: Int, magnitude: ByteArray, off: Int, len: Int): BigInteger = - bigIntegerOf(signum, magnitude, off, len) + fun of( + signum: Int, + magnitude: ByteArray, + off: Int, + len: Int, + ): BigInteger = bigIntegerOf(signum, magnitude, off, len) } } diff --git a/src/commonMain/kotlin/org/gciatto/kt/math/BigIntegerRange.kt b/src/commonMain/kotlin/org/gciatto/kt/math/BigIntegerRange.kt index 9fab2dc..8637345 100644 --- a/src/commonMain/kotlin/org/gciatto/kt/math/BigIntegerRange.kt +++ b/src/commonMain/kotlin/org/gciatto/kt/math/BigIntegerRange.kt @@ -6,17 +6,18 @@ import kotlin.js.JsExport @Suppress("WRONG_EXPORTED_DECLARATION", "NON_EXPORTABLE_TYPE") data class BigIntegerRange( override val start: BigInteger, - override val endInclusive: BigInteger + override val endInclusive: BigInteger, ) : ClosedRange, Iterable { - override fun iterator(): Iterator = object : Iterator { - private var current = start + override fun iterator(): Iterator = + object : Iterator { + private var current = start - override fun hasNext(): Boolean = current <= endInclusive + override fun hasNext(): Boolean = current <= endInclusive - override fun next(): BigInteger { - val temp = current - current += BigInteger.ONE - return temp + override fun next(): BigInteger { + val temp = current + current += BigInteger.ONE + return temp + } } - } } diff --git a/src/commonMain/kotlin/org/gciatto/kt/math/BitSieve.kt b/src/commonMain/kotlin/org/gciatto/kt/math/BitSieve.kt index 6abc82f..04ce2cc 100644 --- a/src/commonMain/kotlin/org/gciatto/kt/math/BitSieve.kt +++ b/src/commonMain/kotlin/org/gciatto/kt/math/BitSieve.kt @@ -148,7 +148,10 @@ internal class BitSieve { * array that occurs at or after start. It will not search past the * specified limit. It returns -1 if there is no such clear bit. */ - private fun sieveSearch(limit: Int, start: Int): Int { + private fun sieveSearch( + limit: Int, + start: Int, + ): Int { if (start >= limit) { return -1 } @@ -168,7 +171,11 @@ internal class BitSieve { * multiples of the specified step starting at the specified start index, * up to the specified limit. */ - private fun sieveSingle(limit: Int, start: Int, step: Int) { + private fun sieveSingle( + limit: Int, + start: Int, + step: Int, + ) { var start = start while (start < limit) { set(start) @@ -179,16 +186,21 @@ internal class BitSieve { /** * Test probable primes in the sieve and return successful candidates. */ - fun retrieve(initValue: CommonBigInteger, certainty: Int, random: Random): CommonBigInteger? { + fun retrieve( + initValue: CommonBigInteger, + certainty: Int, + random: Random, + ): CommonBigInteger? { // Examine the sieve one long at a time to find possible primes var offset = 1 for (i in bits!!.indices) { var nextLong = bits!![i].inv() for (j in 0..63) { if (nextLong and 1 == 1L) { - val candidate = initValue.plus( - CommonBigInteger.of(offset.toLong()) - ) + val candidate = + initValue.plus( + CommonBigInteger.of(offset.toLong()), + ) if (candidate.primeToCertainty(certainty, random)) { return candidate } @@ -201,7 +213,6 @@ internal class BitSieve { } companion object { - /** * A small sieve used to filter out multiples of small primes in a search * sieve. diff --git a/src/commonMain/kotlin/org/gciatto/kt/math/CommonBigDecimal.kt b/src/commonMain/kotlin/org/gciatto/kt/math/CommonBigDecimal.kt index f240291..6b306f6 100644 --- a/src/commonMain/kotlin/org/gciatto/kt/math/CommonBigDecimal.kt +++ b/src/commonMain/kotlin/org/gciatto/kt/math/CommonBigDecimal.kt @@ -23,9 +23,7 @@ package org.gciatto.kt.math * 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 IBM Corporation, 2001. All Rights Reserved. */ @@ -34,8 +32,8 @@ import kotlin.js.JsName import kotlin.jvm.JvmField import kotlin.jvm.JvmOverloads import kotlin.jvm.JvmStatic -import kotlin.math.absoluteValue import kotlin.math.abs +import kotlin.math.absoluteValue import kotlin.math.ceil import kotlin.math.max import kotlin.math.min @@ -247,7 +245,6 @@ import kotlin.math.sqrt */ @Suppress("NAME_SHADOWING", "DEPRECATION", "UNREACHABLE_CODE", "UNUSED_PARAMETER") internal class CommonBigDecimal : BigDecimal { - /** * The unscaled value of this CommonBigDecimal, as returned by [CommonBigDecimal.unscaledValue]. * @@ -332,7 +329,7 @@ internal class CommonBigDecimal : BigDecimal { `in`: CharArray, offset: Int = 0, len: Int = `in`.size, - mc: MathContext = MathContext.UNLIMITED + mc: MathContext = MathContext.UNLIMITED, ) { var offset = offset var len = len @@ -433,7 +430,7 @@ internal class CommonBigDecimal : BigDecimal { throw NumberFormatException( "Character " + c + " is neither a decimal digit number, decimal point, nor" + - " \"e\" notation exponential mark." + " \"e\" notation exponential mark.", ) } offset++ @@ -568,7 +565,10 @@ internal class CommonBigDecimal : BigDecimal { this._intVal = rb } - private fun adjustScale(scl: Int, exp: Long): Int { + private fun adjustScale( + scl: Int, + exp: Long, + ): Int { var scl = scl val adjustedScale = scl - exp if (adjustedScale > Int.MAX_VALUE || adjustedScale < Int.MIN_VALUE) { @@ -751,11 +751,12 @@ internal class CommonBigDecimal : BigDecimal { val valBits = `val`.toBits() val sign = if (valBits shr 63 == 0L) 1 else -1 var exponent = (valBits shr 52 and 0x7ffL).toInt() - var significand = if (exponent == 0) { - valBits and (1L shl 52) - 1 shl 1 - } else { - valBits and (1L shl 52) - 1 or (1L shl 52) - } + var significand = + if (exponent == 0) { + valBits and (1L shl 52) - 1 shl 1 + } else { + valBits and (1L shl 52) - 1 or (1L shl 52) + } exponent -= 1075 // At this point, val == sign * significand * 2**exponent. @@ -1052,7 +1053,10 @@ internal class CommonBigDecimal : BigDecimal { } } - override fun plus(augend: BigDecimal?, mc: MathContext): CommonBigDecimal { + override fun plus( + augend: BigDecimal?, + mc: MathContext, + ): CommonBigDecimal { var augend: CommonBigDecimal = augend!!.castTo() if (mc.precision == 0) { return plus(augend) @@ -1129,7 +1133,7 @@ internal class CommonBigDecimal : BigDecimal { lhs: CommonBigDecimal, augend: CommonBigDecimal, padding: Long, - mc: MathContext + mc: MathContext, ): Array { require(padding != 0L) val big: CommonBigDecimal @@ -1164,10 +1168,11 @@ internal class CommonBigDecimal : BigDecimal { if (smallHighDigitPos > big._scale + 2 && // big and small disjoint smallHighDigitPos > estResultUlpScale + 2 ) { // small digits not visible - small = CommonBigDecimal.of( - small.signum.toLong(), - this.checkScale(max(big._scale.toLong(), estResultUlpScale) + 3) - ) + small = + CommonBigDecimal.of( + small.signum.toLong(), + this.checkScale(max(big._scale.toLong(), estResultUlpScale) + 3), + ) } // Since addition is symmetric, preserving input order in @@ -1195,7 +1200,10 @@ internal class CommonBigDecimal : BigDecimal { } } - override fun minus(subtrahend: BigDecimal, mc: MathContext): CommonBigDecimal { + override fun minus( + subtrahend: BigDecimal, + mc: MathContext, + ): CommonBigDecimal { val subtrahend: CommonBigDecimal = subtrahend.castTo() return if (mc.precision == 0) minus(subtrahend) else plus(subtrahend.unaryMinus(), mc) // share the special rounding code in plus() @@ -1219,7 +1227,10 @@ internal class CommonBigDecimal : BigDecimal { } } - override fun times(multiplicand: BigDecimal, mc: MathContext): CommonBigDecimal { + override fun times( + multiplicand: BigDecimal, + mc: MathContext, + ): CommonBigDecimal { val multiplicand: CommonBigDecimal = multiplicand.castTo() if (mc.precision == 0) { return times(multiplicand) @@ -1276,9 +1287,13 @@ internal class CommonBigDecimal : BigDecimal { "The method {@link #div(CommonBigDecimal, int, RoundingMode)}\n" + " should be used in preference to this legacy method.\n" + " \n" + - " " + " ", ) - private fun div(divisor: CommonBigDecimal, scale: Int, roundingMode: Int): CommonBigDecimal { + private fun div( + divisor: CommonBigDecimal, + scale: Int, + roundingMode: Int, + ): CommonBigDecimal { if (roundingMode < RoundingMode.UP.value || roundingMode > RoundingMode.UNNECESSARY.value) { throw IllegalArgumentException("Invalid rounding mode") } @@ -1332,9 +1347,12 @@ internal class CommonBigDecimal : BigDecimal { "The method {@link #div(CommonBigDecimal, RoundingMode)}\n" + " should be used in preference to this legacy method.\n" + " \n" + - " " + " ", ) - private fun div(divisor: CommonBigDecimal, roundingMode: Int): CommonBigDecimal { + private fun div( + divisor: CommonBigDecimal, + roundingMode: Int, + ): CommonBigDecimal { return this.div(divisor, _scale, roundingMode) } @@ -1366,19 +1384,20 @@ internal class CommonBigDecimal : BigDecimal { * _precision and do a div with the UNNECESSARY rounding * mode. */ - val mc = MathContext( - min( - this.precision + ceil(10.0 * divisor.precision / 3.0).toLong(), - Int.MAX_VALUE.toLong() - ).toInt(), - RoundingMode.UNNECESSARY - ) + val mc = + MathContext( + min( + this.precision + ceil(10.0 * divisor.precision / 3.0).toLong(), + Int.MAX_VALUE.toLong(), + ).toInt(), + RoundingMode.UNNECESSARY, + ) val quotient: CommonBigDecimal? try { quotient = this.div(divisor, mc) } catch (e: ArithmeticException) { throw ArithmeticException( - "Non-terminating decimal expansion; " + "no exact representable decimal result." + "Non-terminating decimal expansion; " + "no exact representable decimal result.", ) } @@ -1391,7 +1410,7 @@ internal class CommonBigDecimal : BigDecimal { return if (preferredScale > quotientScale) { quotient.setScale( preferredScale, - RoundingMode.UNNECESSARY.value + RoundingMode.UNNECESSARY.value, ) } else { quotient @@ -1399,7 +1418,10 @@ internal class CommonBigDecimal : BigDecimal { } } - override fun div(divisor: BigDecimal, mc: MathContext): CommonBigDecimal? { + override fun div( + divisor: BigDecimal, + mc: MathContext, + ): CommonBigDecimal? { val divisor: CommonBigDecimal = divisor.castTo() val mcp = mc.precision if (mcp == 0) { @@ -1464,19 +1486,21 @@ internal class CommonBigDecimal : BigDecimal { // Perform a div with enough digits to round to a correct // integer value; then remove any fractional digits - val maxDigits = min( - this.precision.toLong() + - ceil(10.0 * divisor.precision / 3.0).toLong() + - abs(this.scale.toLong() - divisor.scale) + 2, - Int.MAX_VALUE.toLong() - ).toInt() - var quotient = this.div( - divisor, - MathContext( - maxDigits, - RoundingMode.DOWN + val maxDigits = + min( + this.precision.toLong() + + ceil(10.0 * divisor.precision / 3.0).toLong() + + abs(this.scale.toLong() - divisor.scale) + 2, + Int.MAX_VALUE.toLong(), + ).toInt() + var quotient = + this.div( + divisor, + MathContext( + maxDigits, + RoundingMode.DOWN, + ), ) - ) if (quotient!!._scale > 0) { quotient = quotient.setScale(0, RoundingMode.DOWN) quotient = stripZerosToMatchScale(quotient._intVal, quotient._intCompact, quotient._scale, preferredScale) @@ -1490,7 +1514,10 @@ internal class CommonBigDecimal : BigDecimal { return quotient } - override fun divideToIntegralValue(divisor: BigDecimal, mc: MathContext): CommonBigDecimal { + override fun divideToIntegralValue( + divisor: BigDecimal, + mc: MathContext, + ): CommonBigDecimal { val divisor: CommonBigDecimal = divisor.castTo() if (mc.precision == 0 || // exact result this.compareMagnitude(divisor) < 0 @@ -1551,7 +1578,10 @@ internal class CommonBigDecimal : BigDecimal { return divrem.second } - override fun rem(divisor: BigDecimal, mc: MathContext): CommonBigDecimal { + override fun rem( + divisor: BigDecimal, + mc: MathContext, + ): CommonBigDecimal { val divrem = this.divideAndRemainder(divisor, mc) return divrem.second } @@ -1566,11 +1596,14 @@ internal class CommonBigDecimal : BigDecimal { val temp = this.divideToIntegralValue(divisor) return Pair( temp, - temp.times(divisor) + temp.times(divisor), ) } - override fun divideAndRemainder(divisor: BigDecimal, mc: MathContext): Pair { + override fun divideAndRemainder( + divisor: BigDecimal, + mc: MathContext, + ): Pair { val divisor: CommonBigDecimal = divisor.castTo() if (mc.precision == 0) { return divideAndRemainder(divisor) @@ -1586,7 +1619,7 @@ internal class CommonBigDecimal : BigDecimal { val temp = lhs.divideToIntegralValue(divisor, mc) return Pair( temp, - lhs.minus(temp.times(divisor)) + lhs.minus(temp.times(divisor)), ) } @@ -1657,16 +1690,18 @@ internal class CommonBigDecimal : BigDecimal { // Now the _precision / _scale adjustment val scale = stripped.scale - stripped.precision + 1 - val scaleAdjust: Int = if (scale % 2 == 0) { - scale - } else { - scale - 1 - } + val scaleAdjust: Int = + if (scale % 2 == 0) { + scale + } else { + scale - 1 + } val working = stripped.scaleByPowerOfTen(scaleAdjust) - require( // Verify 0.1 <= working < 10 - ONE_TENTH <= working && working < TEN + require( + // Verify 0.1 <= working < 10 + ONE_TENTH <= working && working < TEN, ) // Use good ole' Math.sqrt to get the initial guess for @@ -1715,10 +1750,11 @@ internal class CommonBigDecimal : BigDecimal { var approx = guess val workingPrecision = working.precision do { - val tmpPrecision = max( - max(guessPrecision, targetPrecision + 2), - workingPrecision - ) + val tmpPrecision = + max( + max(guessPrecision, targetPrecision + 2), + workingPrecision, + ) val mcTmp = MathContext(tmpPrecision, RoundingMode.HALF_EVEN) // approx = 0.5 * (approx + fraction / approx) approx = ONE_HALF.times(approx.plus(working.div(approx, mcTmp), mcTmp)) @@ -1748,10 +1784,11 @@ internal class CommonBigDecimal : BigDecimal { // stripTrailingZeros(), adding a zero of the // preferred _scale rounding the correct _precision will // perform the proper _scale vs _precision tradeoffs. - result = result.stripTrailingZeros().plus( - zeroWithFinalPreferredScale, - MathContext(originalPrecision, RoundingMode.UNNECESSARY) - ) + result = + result.stripTrailingZeros().plus( + zeroWithFinalPreferredScale, + MathContext(originalPrecision, RoundingMode.UNNECESSARY), + ) } require(squareRootResultAssertions(result, mc)) return result @@ -1773,7 +1810,10 @@ internal class CommonBigDecimal : BigDecimal { * input. Conversely, for UP and CEIL, result^2 must be `>=` the * input and (result-ulp)^2 must be `<` the input. */ - private fun squareRootResultAssertions(result: CommonBigDecimal, mc: MathContext): Boolean { + private fun squareRootResultAssertions( + result: CommonBigDecimal, + mc: MathContext, + ): Boolean { if (result.signum == 0) { return squareRootZeroResultAssertions(result, mc) } else { @@ -1826,7 +1866,10 @@ internal class CommonBigDecimal : BigDecimal { } } - private fun squareRootZeroResultAssertions(result: CommonBigDecimal, mc: MathContext): Boolean { + private fun squareRootZeroResultAssertions( + result: CommonBigDecimal, + mc: MathContext, + ): Boolean { return this.compareTo(ZERO) == 0 } @@ -1840,7 +1883,10 @@ internal class CommonBigDecimal : BigDecimal { return CommonBigDecimal(this.inflated().pow(n), newScale) } - override fun pow(n: Int, mc: MathContext): CommonBigDecimal? { + override fun pow( + n: Int, + mc: MathContext, + ): CommonBigDecimal? { if (mc.precision == 0) { return pow(n) } @@ -1859,10 +1905,11 @@ internal class CommonBigDecimal : BigDecimal { // X3.274 rule throw ArithmeticException("Invalid operation") } - workmc = MathContext( - mc.precision + elength + 1, - mc.roundingMode - ) + workmc = + MathContext( + mc.precision + elength + 1, + mc.roundingMode, + ) } // ready to carry out power calculation... var acc = ONE // accumulator @@ -1959,15 +2006,21 @@ internal class CommonBigDecimal : BigDecimal { return unaryPlus(mc) } - override fun setScale(newScale: Int, roundingMode: RoundingMode): CommonBigDecimal { + override fun setScale( + newScale: Int, + roundingMode: RoundingMode, + ): CommonBigDecimal { return setScale(newScale, roundingMode.value) } @Deprecated( "The method {@link #setScale(int, RoundingMode)} should " + - "be used in preference to this legacy method." + "be used in preference to this legacy method.", ) - override fun setScale(newScale: Int, roundingMode: Int): CommonBigDecimal { + override fun setScale( + newScale: Int, + roundingMode: Int, + ): CommonBigDecimal { if (roundingMode < RoundingMode.UP.value || roundingMode > RoundingMode.UNNECESSARY.value) { throw IllegalArgumentException("Invalid rounding mode") } @@ -2016,7 +2069,7 @@ internal class CommonBigDecimal : BigDecimal { LONG_TEN_POWERS_TABLE[drop], newScale, roundingMode, - newScale + newScale, ) } else { divideAndRound(this._intVal!!, bigTenToThe(drop), newScale, roundingMode, newScale) @@ -2048,7 +2101,7 @@ internal class CommonBigDecimal : BigDecimal { _intVal, _intCompact, checkScale(_scale.toLong() - n), - _precision + _precision, ) } @@ -2069,7 +2122,15 @@ internal class CommonBigDecimal : BigDecimal { val xs = _intCompact val ys = other._intCompact if (xs != INFLATED && ys != INFLATED) { - return if (xs != ys) if (xs > ys) 1 else -1 else 0 + return if (xs != ys) { + if (xs > ys) { + 1 + } else { + -1 + } + } else { + 0 + } } } val xsign = this.signum @@ -2109,7 +2170,12 @@ internal class CommonBigDecimal : BigDecimal { if (sdiff < 0) { // The cases sdiff <= Int.MIN_VALUE intentionally fall through. if (sdiff > Int.MIN_VALUE && - (xs == INFLATED || run { xs = longMultiplyPowerTen(xs, (-sdiff).toInt()); xs } == INFLATED) && + ( + xs == INFLATED || run { + xs = longMultiplyPowerTen(xs, (-sdiff).toInt()) + xs + } == INFLATED + ) && ys == INFLATED ) { val rb = bigMultiplyPowerTen((-sdiff).toInt()) @@ -2118,7 +2184,12 @@ internal class CommonBigDecimal : BigDecimal { } else { // sdiff > 0 // The cases sdiff > Int.MAX_VALUE intentionally fall through. if (sdiff <= Int.MAX_VALUE && - (ys == INFLATED || run { ys = longMultiplyPowerTen(ys, sdiff.toInt()); ys } == INFLATED) && + ( + ys == INFLATED || run { + ys = longMultiplyPowerTen(ys, sdiff.toInt()) + ys + } == INFLATED + ) && xs == INFLATED ) { val rb = `val`.bigMultiplyPowerTen(sdiff.toInt()) @@ -2227,9 +2298,13 @@ internal class CommonBigDecimal : BigDecimal { return getValueString(signum, str, _scale) } - /* Returns a digit.digit string */ - private fun getValueString(signum: Int, intString: String, scale: Int): String { - /* Insert decimal point */ + // Returns a digit.digit string + private fun getValueString( + signum: Int, + intString: String, + scale: Int, + ): String { + // Insert decimal point val buf: StringBuilder val insertionPoint = intString.length - scale if (insertionPoint == 0) { // Point goes right before _intVal @@ -2422,12 +2497,13 @@ internal class CommonBigDecimal : BigDecimal { // the compact representation of CommonBigDecimal (except for '-' sign' if it is // negative) if its _intCompact field is not INFLATED. It is shared by all // calls to toString() and its variants in that particular thread. - internal class StringBuilderHelper( // Placeholder for CommonBigDecimal string + internal class StringBuilderHelper( + // Placeholder for CommonBigDecimal string // All non negative longs can be made to fit into 19 character array. - val sb: StringBuilder = StringBuilder(), // character array to place the _intCompact - val compactCharArray: CharArray = CharArray(19) + val sb: StringBuilder = StringBuilder(), + // character array to place the _intCompact + val compactCharArray: CharArray = CharArray(19), ) { - // Accessors. val stringBuilder: StringBuilder get() { @@ -2483,212 +2559,213 @@ internal class CommonBigDecimal : BigDecimal { } companion object { + val DIGIT_TENS = + charArrayOf( + '0', + '0', + '0', + '0', + '0', + '0', + '0', + '0', + '0', + '0', + '1', + '1', + '1', + '1', + '1', + '1', + '1', + '1', + '1', + '1', + '2', + '2', + '2', + '2', + '2', + '2', + '2', + '2', + '2', + '2', + '3', + '3', + '3', + '3', + '3', + '3', + '3', + '3', + '3', + '3', + '4', + '4', + '4', + '4', + '4', + '4', + '4', + '4', + '4', + '4', + '5', + '5', + '5', + '5', + '5', + '5', + '5', + '5', + '5', + '5', + '6', + '6', + '6', + '6', + '6', + '6', + '6', + '6', + '6', + '6', + '7', + '7', + '7', + '7', + '7', + '7', + '7', + '7', + '7', + '7', + '8', + '8', + '8', + '8', + '8', + '8', + '8', + '8', + '8', + '8', + '9', + '9', + '9', + '9', + '9', + '9', + '9', + '9', + '9', + '9', + ) - val DIGIT_TENS = charArrayOf( - '0', - '0', - '0', - '0', - '0', - '0', - '0', - '0', - '0', - '0', - '1', - '1', - '1', - '1', - '1', - '1', - '1', - '1', - '1', - '1', - '2', - '2', - '2', - '2', - '2', - '2', - '2', - '2', - '2', - '2', - '3', - '3', - '3', - '3', - '3', - '3', - '3', - '3', - '3', - '3', - '4', - '4', - '4', - '4', - '4', - '4', - '4', - '4', - '4', - '4', - '5', - '5', - '5', - '5', - '5', - '5', - '5', - '5', - '5', - '5', - '6', - '6', - '6', - '6', - '6', - '6', - '6', - '6', - '6', - '6', - '7', - '7', - '7', - '7', - '7', - '7', - '7', - '7', - '7', - '7', - '8', - '8', - '8', - '8', - '8', - '8', - '8', - '8', - '8', - '8', - '9', - '9', - '9', - '9', - '9', - '9', - '9', - '9', - '9', - '9' - ) - - val DIGIT_ONES = charArrayOf( - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9' - ) + val DIGIT_ONES = + charArrayOf( + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + ) } } @@ -2850,7 +2927,13 @@ internal class CommonBigDecimal : BigDecimal { if (asInt.toLong() != `val`) { asInt = if (`val` > Int.MAX_VALUE) Int.MAX_VALUE else Int.MIN_VALUE val b: CommonBigInteger? - if (_intCompact != 0L && (run { b = _intVal; b } == null || b!!.signum != 0)) { + if (_intCompact != 0L && ( + run { + b = _intVal + b + } == null || b!!.signum != 0 + ) + ) { throw ArithmeticException(if (asInt > 0) "Underflow" else "Overflow") } } @@ -2894,7 +2977,7 @@ internal class CommonBigDecimal : BigDecimal { print("audit", this) throw AssertionError( "Inconsistent state, _intCompact=" + - _intCompact + "\t _intVal=" + `val` + _intCompact + "\t _intVal=" + `val`, ) } } @@ -2908,7 +2991,6 @@ internal class CommonBigDecimal : BigDecimal { } companion object { - /** * Sentinel value for [CommonBigDecimal._intCompact] indicating the * significand information is only available from `_intVal`. @@ -2922,45 +3004,46 @@ internal class CommonBigDecimal : BigDecimal { private const val MAX_COMPACT_DIGITS = 18 // Cache of common small CommonBigDecimal values. - private val ZERO_THROUGH_TEN = arrayOf( - CommonBigDecimal(CommonBigInteger.ZERO, 0, 0, 1), - CommonBigDecimal(CommonBigInteger.ONE, 1, 0, 1), - CommonBigDecimal(CommonBigInteger.TWO, 2, 0, 1), - CommonBigDecimal(CommonBigInteger.of(3), 3, 0, 1), - CommonBigDecimal(CommonBigInteger.of(4), 4, 0, 1), - CommonBigDecimal(CommonBigInteger.of(5), 5, 0, 1), - CommonBigDecimal(CommonBigInteger.of(6), 6, 0, 1), - CommonBigDecimal(CommonBigInteger.of(7), 7, 0, 1), - CommonBigDecimal(CommonBigInteger.of(8), 8, 0, 1), - CommonBigDecimal(CommonBigInteger.of(9), 9, 0, 1), - CommonBigDecimal(CommonBigInteger.TEN, 10, 0, 2) - ) + private val ZERO_THROUGH_TEN = + arrayOf( + CommonBigDecimal(CommonBigInteger.ZERO, 0, 0, 1), + CommonBigDecimal(CommonBigInteger.ONE, 1, 0, 1), + CommonBigDecimal(CommonBigInteger.TWO, 2, 0, 1), + CommonBigDecimal(CommonBigInteger.of(3), 3, 0, 1), + CommonBigDecimal(CommonBigInteger.of(4), 4, 0, 1), + CommonBigDecimal(CommonBigInteger.of(5), 5, 0, 1), + CommonBigDecimal(CommonBigInteger.of(6), 6, 0, 1), + CommonBigDecimal(CommonBigInteger.of(7), 7, 0, 1), + CommonBigDecimal(CommonBigInteger.of(8), 8, 0, 1), + CommonBigDecimal(CommonBigInteger.of(9), 9, 0, 1), + CommonBigDecimal(CommonBigInteger.TEN, 10, 0, 2), + ) // Cache of zero scaled by 0 - 15 - private val ZERO_SCALED_BY = arrayOf( - ZERO_THROUGH_TEN[0], - CommonBigDecimal(CommonBigInteger.ZERO, 0, 1, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 2, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 3, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 4, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 5, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 6, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 7, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 8, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 9, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 10, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 11, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 12, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 13, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 14, 1), - CommonBigDecimal(CommonBigInteger.ZERO, 0, 15, 1) - ) + private val ZERO_SCALED_BY = + arrayOf( + ZERO_THROUGH_TEN[0], + CommonBigDecimal(CommonBigInteger.ZERO, 0, 1, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 2, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 3, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 4, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 5, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 6, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 7, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 8, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 9, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 10, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 11, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 12, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 13, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 14, 1), + CommonBigDecimal(CommonBigInteger.ZERO, 0, 15, 1), + ) // Half of Long.MIN_VALUE & Long.MAX_VALUE. private const val HALF_LONG_MAX_VALUE = Long.MAX_VALUE / 2 private const val HALF_LONG_MIN_VALUE = Long.MIN_VALUE / 2 - // Constants /** * The value 0, with a _scale of 0. * @@ -3014,7 +3097,11 @@ internal class CommonBigDecimal : BigDecimal { @JsName("E") val E = of(E_STRING) - private fun parseExp(`in`: CharArray, offset: Int, len: Int): Long { + private fun parseExp( + `in`: CharArray, + offset: Int, + len: Int, + ): Long { var offset = offset var len = len var exp: Long = 0 @@ -3069,8 +3156,6 @@ internal class CommonBigDecimal : BigDecimal { return exp } - // Static Factory Methods - /** * Translates a `long` unscaled value and an * `int` _scale into a [CommonBigDecimal]. @@ -3086,7 +3171,10 @@ internal class CommonBigDecimal : BigDecimal { */ @JvmStatic @JsName("ofScaledLong") - fun of(unscaledVal: Long, scale: Int): CommonBigDecimal { + fun of( + unscaledVal: Long, + scale: Int, + ): CommonBigDecimal { if (scale == 0) { return of(unscaledVal) } else if (unscaledVal == 0L) { @@ -3100,31 +3188,17 @@ internal class CommonBigDecimal : BigDecimal { }, unscaledVal, scale, - 0 + 0, ) } - /** - * Translates a `long` value into a [CommonBigDecimal] - * with a _scale of zero. - * - * @apiNote This static factory method is provided in preference - * to a (`long`) constructor because it allows for reuse of - * frequently used [CommonBigDecimal] values. - * - * @param val value of the [CommonBigDecimal]. - * @return a [CommonBigDecimal] whose value is `val`. - */ -// fun of(`val`: Long): CommonBigDecimal { -// if (`val` >= 0 && `val` < ZERO_THROUGH_TEN.size) -// return ZERO_THROUGH_TEN[`val`.toInt()] -// else if (`val` != INFLATED) -// return CommonBigDecimal(null, `val`, 0, 0) -// return CommonBigDecimal(INFLATED_BIGINT, `val`, 0, 0) -// } @JvmStatic @JsName("ofScaledLongWithPrecision") - fun of(unscaledVal: Long, scale: Int, prec: Int): CommonBigDecimal { + fun of( + unscaledVal: Long, + scale: Int, + prec: Int, + ): CommonBigDecimal { return if (scale == 0 && unscaledVal >= 0 && unscaledVal < ZERO_THROUGH_TEN.size) { ZERO_THROUGH_TEN[unscaledVal.toInt()] } else if (unscaledVal == 0L) { @@ -3134,7 +3208,7 @@ internal class CommonBigDecimal : BigDecimal { if (unscaledVal == INFLATED) INFLATED_BIGINT else null, unscaledVal, scale, - prec + prec, ) } } @@ -3145,6 +3219,17 @@ internal class CommonBigDecimal : BigDecimal { return of(`val`.toLong()) } + /** + * Translates a `long` value into a [CommonBigDecimal] + * with a _scale of zero. + * + * @apiNote This static factory method is provided in preference + * to a (`long`) constructor because it allows for reuse of + * frequently used [CommonBigDecimal] values. + * + * @param val value of the [CommonBigDecimal]. + * @return a [CommonBigDecimal] whose value is `val`. + */ @JvmStatic @JsName("of") fun of(`val`: Long): CommonBigDecimal { @@ -3158,7 +3243,7 @@ internal class CommonBigDecimal : BigDecimal { INFLATED_BIGINT, `val`, 0, - 0 + 0, ) } } @@ -3166,7 +3251,11 @@ internal class CommonBigDecimal : BigDecimal { @JvmStatic @JsName("ofScaledBigIntegerWithPrecision") - fun of(intVal: CommonBigInteger, scale: Int, prec: Int): CommonBigDecimal { + fun of( + intVal: CommonBigInteger, + scale: Int, + prec: Int, + ): CommonBigDecimal { val `val` = compactValFor(intVal) if (`val` == 0L) { return zeroValueOf(scale) @@ -3202,20 +3291,29 @@ internal class CommonBigDecimal : BigDecimal { */ @JvmStatic @JsName("ofDouble") - fun of(`val`: Double, ctx: MathContext): CommonBigDecimal { + fun of( + `val`: Double, + ctx: MathContext, + ): CommonBigDecimal { return CommonBigDecimal(`val`, ctx) } @JvmStatic @JsName("ofFloat") - fun of(`val`: Float, ctx: MathContext): CommonBigDecimal { + fun of( + `val`: Float, + ctx: MathContext, + ): CommonBigDecimal { return of(`val`.toDouble(), ctx) } @JvmStatic @JsName("parse") @JvmOverloads - fun of(`val`: String, ctx: MathContext? = null): CommonBigDecimal { + fun of( + `val`: String, + ctx: MathContext? = null, + ): CommonBigDecimal { return if (ctx === null) { CommonBigDecimal(`val`) } else { @@ -3226,7 +3324,10 @@ internal class CommonBigDecimal : BigDecimal { @JvmStatic @JsName("ofBigInteger") @JvmOverloads - fun of(`val`: CommonBigInteger, ctx: MathContext? = null): CommonBigDecimal { + fun of( + `val`: CommonBigInteger, + ctx: MathContext? = null, + ): CommonBigDecimal { return if (ctx === null) { CommonBigDecimal(`val`) } else { @@ -3236,44 +3337,51 @@ internal class CommonBigDecimal : BigDecimal { @JvmStatic @JsName("ofIntWithContext") - fun of(`val`: Int, ctx: MathContext): CommonBigDecimal { + fun of( + `val`: Int, + ctx: MathContext, + ): CommonBigDecimal { return CommonBigDecimal(`val`.toLong(), ctx) } @JvmStatic @JsName("ofWithContext") - fun of(`val`: Long, ctx: MathContext): CommonBigDecimal { + fun of( + `val`: Long, + ctx: MathContext, + ): CommonBigDecimal { return CommonBigDecimal(`val`, ctx) } /** * Powers of 10 which can be represented exactly in `double`. */ - private val DOUBLE_10_POW = doubleArrayOf( - 1.0e0, - 1.0e1, - 1.0e2, - 1.0e3, - 1.0e4, - 1.0e5, - 1.0e6, - 1.0e7, - 1.0e8, - 1.0e9, - 1.0e10, - 1.0e11, - 1.0e12, - 1.0e13, - 1.0e14, - 1.0e15, - 1.0e16, - 1.0e17, - 1.0e18, - 1.0e19, - 1.0e20, - 1.0e21, - 1.0e22 - ) + private val DOUBLE_10_POW = + doubleArrayOf( + 1.0e0, + 1.0e1, + 1.0e2, + 1.0e3, + 1.0e4, + 1.0e5, + 1.0e6, + 1.0e7, + 1.0e8, + 1.0e9, + 1.0e10, + 1.0e11, + 1.0e12, + 1.0e13, + 1.0e14, + 1.0e15, + 1.0e16, + 1.0e17, + 1.0e18, + 1.0e19, + 1.0e20, + 1.0e21, + 1.0e22, + ) /** * Powers of 10 which can be represented exactly in `float`. @@ -3338,80 +3446,86 @@ internal class CommonBigDecimal : BigDecimal { } } - private val LONG_TEN_POWERS_TABLE = longArrayOf( - 1, // 0 / 10^0 - 10, // 1 / 10^1 - 100, // 2 / 10^2 - 1000, // 3 / 10^3 - 10000, // 4 / 10^4 - 100000, // 5 / 10^5 - 1000000, // 6 / 10^6 - 10000000, // 7 / 10^7 - 100000000, // 8 / 10^8 - 1000000000, // 9 / 10^9 - 10000000000L, // 10 / 10^10 - 100000000000L, // 11 / 10^11 - 1000000000000L, // 12 / 10^12 - 10000000000000L, // 13 / 10^13 - 100000000000000L, // 14 / 10^14 - 1000000000000000L, // 15 / 10^15 - 10000000000000000L, // 16 / 10^16 - 100000000000000000L, // 17 / 10^17 - 1000000000000000000L // 18 / 10^18 - ) + private val LONG_TEN_POWERS_TABLE = + longArrayOf( + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000L, + 100000000000L, + 1000000000000L, + 10000000000000L, + 100000000000000L, + 1000000000000000L, + 10000000000000000L, + 100000000000000000L, + 1000000000000000000L, + ) - private var BIG_TEN_POWERS_TABLE = arrayOf( - CommonBigInteger.ONE, - CommonBigInteger.of(10), - CommonBigInteger.of(100), - CommonBigInteger.of(1000), - CommonBigInteger.of(10000), - CommonBigInteger.of(100000), - CommonBigInteger.of(1000000), - CommonBigInteger.of(10000000), - CommonBigInteger.of(100000000), - CommonBigInteger.of(1000000000), - CommonBigInteger.of(10000000000L), - CommonBigInteger.of(100000000000L), - CommonBigInteger.of(1000000000000L), - CommonBigInteger.of(10000000000000L), - CommonBigInteger.of(100000000000000L), - CommonBigInteger.of(1000000000000000L), - CommonBigInteger.of(10000000000000000L), - CommonBigInteger.of(100000000000000000L), - CommonBigInteger.of(1000000000000000000L) - ) + private var BIG_TEN_POWERS_TABLE = + arrayOf( + CommonBigInteger.ONE, + CommonBigInteger.of(10), + CommonBigInteger.of(100), + CommonBigInteger.of(1000), + CommonBigInteger.of(10000), + CommonBigInteger.of(100000), + CommonBigInteger.of(1000000), + CommonBigInteger.of(10000000), + CommonBigInteger.of(100000000), + CommonBigInteger.of(1000000000), + CommonBigInteger.of(10000000000L), + CommonBigInteger.of(100000000000L), + CommonBigInteger.of(1000000000000L), + CommonBigInteger.of(10000000000000L), + CommonBigInteger.of(100000000000000L), + CommonBigInteger.of(1000000000000000L), + CommonBigInteger.of(10000000000000000L), + CommonBigInteger.of(100000000000000000L), + CommonBigInteger.of(1000000000000000000L), + ) private val BIG_TEN_POWERS_TABLE_INITLEN = BIG_TEN_POWERS_TABLE.size private val BIG_TEN_POWERS_TABLE_MAX = 16 * BIG_TEN_POWERS_TABLE_INITLEN - private val THRESHOLDS_TABLE = longArrayOf( - Long.MAX_VALUE, // 0 - Long.MAX_VALUE / 10L, // 1 - Long.MAX_VALUE / 100L, // 2 - Long.MAX_VALUE / 1000L, // 3 - Long.MAX_VALUE / 10000L, // 4 - Long.MAX_VALUE / 100000L, // 5 - Long.MAX_VALUE / 1000000L, // 6 - Long.MAX_VALUE / 10000000L, // 7 - Long.MAX_VALUE / 100000000L, // 8 - Long.MAX_VALUE / 1000000000L, // 9 - Long.MAX_VALUE / 10000000000L, // 10 - Long.MAX_VALUE / 100000000000L, // 11 - Long.MAX_VALUE / 1000000000000L, // 12 - Long.MAX_VALUE / 10000000000000L, // 13 - Long.MAX_VALUE / 100000000000000L, // 14 - Long.MAX_VALUE / 1000000000000000L, // 15 - Long.MAX_VALUE / 10000000000000000L, // 16 - Long.MAX_VALUE / 100000000000000000L, // 17 - Long.MAX_VALUE / 1000000000000000000L // 18 - ) + private val THRESHOLDS_TABLE = + longArrayOf( + Long.MAX_VALUE, + Long.MAX_VALUE / 10L, + Long.MAX_VALUE / 100L, + Long.MAX_VALUE / 1000L, + Long.MAX_VALUE / 10000L, + Long.MAX_VALUE / 100000L, + Long.MAX_VALUE / 1000000L, + Long.MAX_VALUE / 10000000L, + Long.MAX_VALUE / 100000000L, + Long.MAX_VALUE / 1000000000L, + Long.MAX_VALUE / 10000000000L, + Long.MAX_VALUE / 100000000000L, + Long.MAX_VALUE / 1000000000000L, + Long.MAX_VALUE / 10000000000000L, + Long.MAX_VALUE / 100000000000000L, + Long.MAX_VALUE / 1000000000000000L, + Long.MAX_VALUE / 10000000000000000L, + Long.MAX_VALUE / 100000000000000000L, + Long.MAX_VALUE / 1000000000000000000L, + ) /** * Compute val * 10 ^ n; return this product if it is * representable as a long, INFLATED otherwise. */ - private fun longMultiplyPowerTen(`val`: Long, n: Int): Long { + private fun longMultiplyPowerTen( + `val`: Long, + n: Int, + ): Long { if (`val` == 0L || n <= 0) { return `val` } @@ -3523,15 +3637,19 @@ internal class CommonBigDecimal : BigDecimal { return INFLATED } - val u = if (len == 2) { - (m[1].toLong() and LONG_MASK) + (d.toLong() shl 32) - } else { - d.toLong() and LONG_MASK - } + val u = + if (len == 2) { + (m[1].toLong() and LONG_MASK) + (d.toLong() shl 32) + } else { + d.toLong() and LONG_MASK + } return if (b._signum < 0) -u else u } - private fun longCompareMagnitude(x: Long, y: Long): Int { + private fun longCompareMagnitude( + x: Long, + y: Long, + ): Int { var x = x var y = y if (x < 0) { @@ -3540,25 +3658,40 @@ internal class CommonBigDecimal : BigDecimal { if (y < 0) { y = -y } - return if (x < y) -1 else if (x == y) 0 else 1 + return if (x < y) { + -1 + } else if (x == y) { + 0 + } else { + 1 + } } private fun saturateLong(s: Long): Int { val i = s.toInt() - return if (s == i.toLong()) i else if (s < 0) Int.MIN_VALUE else Int.MAX_VALUE + return if (s == i.toLong()) { + i + } else if (s < 0) { + Int.MIN_VALUE + } else { + Int.MAX_VALUE + } } /* * Internal printing routine */ - private fun print(name: String, bd: CommonBigDecimal) { + private fun print( + name: String, + bd: CommonBigDecimal, + ) { println( "$name:\t_intCompact ${bd._intCompact}\t_intVal " + - "${bd._intVal}\t_scale ${bd._scale}\t_precision ${bd._precision}" + "${bd._intVal}\t_scale ${bd._scale}\t_precision ${bd._precision}", ) } - /* the same as checkScale where value!=0 */ + // the same as checkScale where value!=0 private fun checkScaleNonZero(`val`: Long): Int { val asInt = `val`.toInt() if (asInt.toLong() != `val`) { @@ -3567,7 +3700,10 @@ internal class CommonBigDecimal : BigDecimal { return asInt } - private fun checkScale(intCompact: Long, `val`: Long): Int { + private fun checkScale( + intCompact: Long, + `val`: Long, + ): Int { var asInt = `val`.toInt() if (asInt.toLong() != `val`) { asInt = if (`val` > Int.MAX_VALUE) Int.MAX_VALUE else Int.MIN_VALUE @@ -3578,7 +3714,10 @@ internal class CommonBigDecimal : BigDecimal { return asInt } - private fun checkScale(intVal: CommonBigInteger?, `val`: Long): Int { + private fun checkScale( + intVal: CommonBigInteger?, + `val`: Long, + ): Int { var asInt = `val`.toInt() if (asInt.toLong() != `val`) { asInt = if (`val` > Int.MAX_VALUE) Int.MAX_VALUE else Int.MIN_VALUE @@ -3602,7 +3741,10 @@ internal class CommonBigDecimal : BigDecimal { * `RoundingMode.UNNECESSARY` and the * result is inexact. */ - private fun doRound(`val`: CommonBigDecimal?, mc: MathContext): CommonBigDecimal? { + private fun doRound( + `val`: CommonBigDecimal?, + mc: MathContext, + ): CommonBigDecimal? { val mcp = mc.precision var wasDivided = false if (mcp > 0) { @@ -3648,7 +3790,11 @@ internal class CommonBigDecimal : BigDecimal { * Returns a {@code CommonBigDecimal} created from {@code long} value with * given _scale rounded according to the MathContext settings */ - private fun doRound(compactVal: Long, scale: Int, mc: MathContext): CommonBigDecimal { + private fun doRound( + compactVal: Long, + scale: Int, + mc: MathContext, + ): CommonBigDecimal { var compactVal = compactVal var scale = scale val mcp = mc.precision @@ -3670,7 +3816,11 @@ internal class CommonBigDecimal : BigDecimal { * Returns a {@code CommonBigDecimal} created from {@code BigInteger} value with * given _scale rounded according to the MathContext settings */ - private fun doRound(intVal: CommonBigInteger, scale: Int, mc: MathContext): CommonBigDecimal { + private fun doRound( + intVal: CommonBigInteger, + scale: Int, + mc: MathContext, + ): CommonBigDecimal { var intVal = intVal var scale = scale val mcp = mc.precision @@ -3712,7 +3862,11 @@ internal class CommonBigDecimal : BigDecimal { /* * Divides {@code BigInteger} value by ten power. */ - private fun divideAndRoundByTenPow(intVal: CommonBigInteger, tenPow: Int, roundingMode: Int): CommonBigInteger { + private fun divideAndRoundByTenPow( + intVal: CommonBigInteger, + tenPow: Int, + roundingMode: Int, + ): CommonBigInteger { var intVal = intVal if (tenPow < LONG_TEN_POWERS_TABLE.size) { intVal = divideAndRound(intVal, LONG_TEN_POWERS_TABLE[tenPow], roundingMode) @@ -3736,7 +3890,7 @@ internal class CommonBigDecimal : BigDecimal { ldivisor: Long, scale: Int, roundingMode: Int, - preferredScale: Int + preferredScale: Int, ): CommonBigDecimal { val qsign: Int // quotient sign val q = ldividend / ldivisor // store quotient in long @@ -3761,7 +3915,11 @@ internal class CommonBigDecimal : BigDecimal { * Divides `long` by `long` and do rounding based on the * passed in roundingMode. */ - private fun divideAndRound(ldividend: Long, ldivisor: Long, roundingMode: Int): Long { + private fun divideAndRound( + ldividend: Long, + ldivisor: Long, + roundingMode: Int, + ): Long { val qsign: Int // quotient sign val q = ldividend / ldivisor // store quotient in long if (roundingMode == RoundingMode.DOWN.value) { @@ -3780,27 +3938,32 @@ internal class CommonBigDecimal : BigDecimal { /** * Shared logic of need increment computation. */ - private fun commonNeedIncrement(roundingMode: Int, qsign: Int, cmpFracHalf: Int, oddQuot: Boolean): Boolean { + private fun commonNeedIncrement( + roundingMode: Int, + qsign: Int, + cmpFracHalf: Int, + oddQuot: Boolean, + ): Boolean { when (roundingMode) { RoundingMode.UNNECESSARY.value -> throw ArithmeticException("Rounding necessary") - RoundingMode.UP.value // Away from zero + RoundingMode.UP.value, // Away from zero -> return true - RoundingMode.DOWN.value // Towards zero + RoundingMode.DOWN.value, // Towards zero -> return false - RoundingMode.CEILING.value // Towards +infinity + RoundingMode.CEILING.value, // Towards +infinity -> return qsign > 0 - RoundingMode.FLOOR.value // Towards -infinity + RoundingMode.FLOOR.value, // Towards -infinity -> return qsign < 0 else // Some kind of half-way rounding -> { require( roundingMode >= RoundingMode.HALF_UP.value && - roundingMode <= RoundingMode.HALF_EVEN.value + roundingMode <= RoundingMode.HALF_EVEN.value, ) { "Unexpected rounding mode" + RoundingMode.valueOf(roundingMode) } @@ -3831,7 +3994,13 @@ internal class CommonBigDecimal : BigDecimal { /** * Tests if quotient has to be incremented according the roundingMode */ - private fun needIncrement(ldivisor: Long, roundingMode: Int, qsign: Int, q: Long, r: Long): Boolean { + private fun needIncrement( + ldivisor: Long, + roundingMode: Int, + qsign: Int, + q: Long, + r: Long, + ): Boolean { require(r != 0L) val cmpFracHalf: Int @@ -3848,7 +4017,11 @@ internal class CommonBigDecimal : BigDecimal { * Divides [CommonBigInteger] value by `long` value and * do rounding based on the passed in roundingMode. */ - private fun divideAndRound(bdividend: CommonBigInteger, ldivisor: Long, roundingMode: Int): CommonBigInteger { + private fun divideAndRound( + bdividend: CommonBigInteger, + ldivisor: Long, + roundingMode: Int, + ): CommonBigInteger { // Descend into mutables for faster remainder checks val mdividend = MutableBigInteger(bdividend._mag) // store quotient @@ -3881,7 +4054,7 @@ internal class CommonBigDecimal : BigDecimal { ldivisor: Long, scale: Int, roundingMode: Int, - preferredScale: Int + preferredScale: Int, ): CommonBigDecimal { // Descend into mutables for faster remainder checks val mdividend = MutableBigInteger(bdividend._mag) @@ -3920,7 +4093,7 @@ internal class CommonBigDecimal : BigDecimal { roundingMode: Int, qsign: Int, mq: MutableBigInteger, - r: Long + r: Long, ): Boolean { require(r != 0L) @@ -3941,7 +4114,7 @@ internal class CommonBigDecimal : BigDecimal { private fun divideAndRound( bdividend: CommonBigInteger, bdivisor: CommonBigInteger, - roundingMode: Int + roundingMode: Int, ): CommonBigInteger { val isRemainderZero: Boolean // record remainder is zero or not val qsign: Int // quotient sign @@ -3974,7 +4147,7 @@ internal class CommonBigDecimal : BigDecimal { bdivisor: CommonBigInteger, scale: Int, roundingMode: Int, - preferredScale: Int + preferredScale: Int, ): CommonBigDecimal { val isRemainderZero: Boolean // record remainder is zero or not val qsign: Int // quotient sign @@ -4012,7 +4185,7 @@ internal class CommonBigDecimal : BigDecimal { roundingMode: Int, qsign: Int, mq: MutableBigInteger, - mr: MutableBigInteger + mr: MutableBigInteger, ): Boolean { require(!mr.isZero) val cmpFracHalf = mr.compareHalf(mdivisor) @@ -4031,7 +4204,7 @@ internal class CommonBigDecimal : BigDecimal { private fun createAndStripZerosToMatchScale( intVal: CommonBigInteger, scale: Int, - preferredScale: Long + preferredScale: Long, ): CommonBigDecimal { var intVal = intVal var scale = scale @@ -4062,7 +4235,7 @@ internal class CommonBigDecimal : BigDecimal { private fun createAndStripZerosToMatchScale( compactVal: Long, scale: Int, - preferredScale: Long + preferredScale: Long, ): CommonBigDecimal { var compactVal = compactVal var scale = scale @@ -4084,7 +4257,7 @@ internal class CommonBigDecimal : BigDecimal { intVal: CommonBigInteger?, intCompact: Long, scale: Int, - preferredScale: Int + preferredScale: Int, ): CommonBigDecimal { return if (intCompact != INFLATED) { createAndStripZerosToMatchScale(intCompact, scale, preferredScale.toLong()) @@ -4092,7 +4265,7 @@ internal class CommonBigDecimal : BigDecimal { createAndStripZerosToMatchScale( intVal ?: INFLATED_BIGINT, scale, - preferredScale.toLong() + preferredScale.toLong(), ) } } @@ -4100,7 +4273,10 @@ internal class CommonBigDecimal : BigDecimal { /* * returns INFLATED if oveflow */ - private fun sum(xs: Long, ys: Long): Long { + private fun sum( + xs: Long, + ys: Long, + ): Long { val sum = xs + ys // See "Hacker's Delight" section 2-12 for explanation of // the overflow test. @@ -4111,19 +4287,28 @@ internal class CommonBigDecimal : BigDecimal { } } - private fun sum(xs: Long, ys: Long, scale: Int): CommonBigDecimal { + private fun sum( + xs: Long, + ys: Long, + scale: Int, + ): CommonBigDecimal { val sum = sum(xs, ys) return if (sum != INFLATED) { CommonBigDecimal.of(sum, scale) } else { CommonBigDecimal( CommonBigInteger.of(xs).plusLong(ys), - scale + scale, ) } } - private fun sum(xs: Long, scale1: Int, ys: Long, scale2: Int): CommonBigDecimal { + private fun sum( + xs: Long, + scale1: Int, + ys: Long, + scale2: Int, + ): CommonBigDecimal { val sdiff = scale1.toLong() - scale2 if (sdiff == 0L) { return sum(xs, ys, scale1) @@ -4157,7 +4342,12 @@ internal class CommonBigDecimal : BigDecimal { } } - private fun sum(xs: Long, scale1: Int, snd: CommonBigInteger, scale2: Int): CommonBigDecimal { + private fun sum( + xs: Long, + scale1: Int, + snd: CommonBigInteger, + scale2: Int, + ): CommonBigDecimal { var snd = snd var rscale = scale1 val sdiff = rscale.toLong() - scale2 @@ -4184,7 +4374,12 @@ internal class CommonBigDecimal : BigDecimal { } } - private fun sum(fst: CommonBigInteger?, scale1: Int, snd: CommonBigInteger?, scale2: Int): CommonBigDecimal { + private fun sum( + fst: CommonBigInteger?, + scale1: Int, + snd: CommonBigInteger?, + scale2: Int, + ): CommonBigDecimal { var fst = fst var snd = snd var rscale = scale1 @@ -4207,11 +4402,17 @@ internal class CommonBigDecimal : BigDecimal { } } - private fun bigMultiplyPowerTen(value: Long, n: Int): CommonBigInteger { + private fun bigMultiplyPowerTen( + value: Long, + n: Int, + ): CommonBigInteger { return if (n <= 0) CommonBigInteger.of(value) else bigTenToThe(n).timesLong(value) } - private fun bigMultiplyPowerTen(value: CommonBigInteger?, n: Int): CommonBigInteger? { + private fun bigMultiplyPowerTen( + value: CommonBigInteger?, + n: Int, + ): CommonBigInteger? { if (n <= 0) { return value } @@ -4235,7 +4436,7 @@ internal class CommonBigDecimal : BigDecimal { ys: Long, yscale: Int, preferredScale: Long, - mc: MathContext + mc: MathContext, ): CommonBigDecimal? { var yscale = yscale val mcp = mc.precision @@ -4243,11 +4444,12 @@ internal class CommonBigDecimal : BigDecimal { require(xscale <= yscale && yscale < 18 && mcp < 18) val xraise = yscale - xscale // xraise >=0 - val scaledX = if (xraise == 0) { - xs - } else { - longMultiplyPowerTen(xs, xraise) // can't overflow here! - } + val scaledX = + if (xraise == 0) { + xs + } else { + longMultiplyPowerTen(xs, xraise) // can't overflow here! + } var quotient: CommonBigDecimal? val cmp = longCompareMagnitude(scaledX, ys) @@ -4262,24 +4464,26 @@ internal class CommonBigDecimal : BigDecimal { if (scaledXs == INFLATED) { quotient = null if (mcp - 1 >= 0 && mcp - 1 < LONG_TEN_POWERS_TABLE.size) { - quotient = multiplyDivideAndRound( - LONG_TEN_POWERS_TABLE[mcp - 1], - scaledX, - ys, - scl, - roundingMode, - checkScaleNonZero(preferredScale) - ) + quotient = + multiplyDivideAndRound( + LONG_TEN_POWERS_TABLE[mcp - 1], + scaledX, + ys, + scl, + roundingMode, + checkScaleNonZero(preferredScale), + ) } if (quotient == null) { val rb = bigMultiplyPowerTen(scaledX, mcp - 1) - quotient = divideAndRound( - rb, - ys, - scl, - roundingMode, - checkScaleNonZero(preferredScale) - ) + quotient = + divideAndRound( + rb, + ys, + scl, + roundingMode, + checkScaleNonZero(preferredScale), + ) } } else { quotient = divideAndRound(scaledXs, ys, scl, roundingMode, checkScaleNonZero(preferredScale)) @@ -4294,13 +4498,14 @@ internal class CommonBigDecimal : BigDecimal { val scaledYs: Long = longMultiplyPowerTen(ys, raise) if (scaledYs == INFLATED) { val rb = bigMultiplyPowerTen(ys, raise) - quotient = divideAndRound( - CommonBigInteger.of(xs), - rb, - scl, - roundingMode, - checkScaleNonZero(preferredScale) - ) + quotient = + divideAndRound( + CommonBigInteger.of(xs), + rb, + scl, + roundingMode, + checkScaleNonZero(preferredScale), + ) } else { quotient = divideAndRound(xs, scaledYs, scl, roundingMode, checkScaleNonZero(preferredScale)) @@ -4313,36 +4518,39 @@ internal class CommonBigDecimal : BigDecimal { val scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp) if (cmp == 0) { // absoluteValue(scaleX)== absoluteValue(ys) => result will be scaled 10^mcp + correct sign - quotient = roundedTenPower( - if (scaledX < 0 == ys < 0) 1 else -1, - mcp, - scl, - checkScaleNonZero(preferredScale) - ) + quotient = + roundedTenPower( + if (scaledX < 0 == ys < 0) 1 else -1, + mcp, + scl, + checkScaleNonZero(preferredScale), + ) } else { // absoluteValue(scaledX) < absoluteValue(ys) val scaledXs: Long = longMultiplyPowerTen(scaledX, mcp) if (scaledXs == INFLATED) { quotient = null if (mcp < LONG_TEN_POWERS_TABLE.size) { - quotient = multiplyDivideAndRound( - LONG_TEN_POWERS_TABLE[mcp], - scaledX, - ys, - scl, - roundingMode, - checkScaleNonZero(preferredScale) - ) + quotient = + multiplyDivideAndRound( + LONG_TEN_POWERS_TABLE[mcp], + scaledX, + ys, + scl, + roundingMode, + checkScaleNonZero(preferredScale), + ) } if (quotient == null) { val rb = bigMultiplyPowerTen(scaledX, mcp) - quotient = divideAndRound( - rb, - ys, - scl, - roundingMode, - checkScaleNonZero(preferredScale) - ) + quotient = + divideAndRound( + rb, + ys, + scl, + roundingMode, + checkScaleNonZero(preferredScale), + ) } } else { quotient = divideAndRound(scaledXs, ys, scl, roundingMode, checkScaleNonZero(preferredScale)) @@ -4363,7 +4571,7 @@ internal class CommonBigDecimal : BigDecimal { ys: Long, yscale: Int, preferredScale: Long, - mc: MathContext + mc: MathContext, ): CommonBigDecimal? { var yscale = yscale val mcp = mc.precision @@ -4398,13 +4606,14 @@ internal class CommonBigDecimal : BigDecimal { val scaledYs: Long = longMultiplyPowerTen(ys, raise) if (scaledYs == INFLATED) { val rb = bigMultiplyPowerTen(ys, raise) - quotient = divideAndRound( - CommonBigInteger.of(xs), - rb, - scl, - roundingMode, - checkScaleNonZero(preferredScale) - ) + quotient = + divideAndRound( + CommonBigInteger.of(xs), + rb, + scl, + roundingMode, + checkScaleNonZero(preferredScale), + ) } else { quotient = divideAndRound(xs, scaledYs, scl, roundingMode, checkScaleNonZero(preferredScale)) } @@ -4424,7 +4633,7 @@ internal class CommonBigDecimal : BigDecimal { ys: Long, yscale: Int, preferredScale: Long, - mc: MathContext + mc: MathContext, ): CommonBigDecimal? { var yscale = yscale // Normalize dividend & divisor so that both fall into [0.1, 0.999...] @@ -4473,7 +4682,7 @@ internal class CommonBigDecimal : BigDecimal { ys: CommonBigInteger?, yscale: Int, preferredScale: Long, - mc: MathContext + mc: MathContext, ): CommonBigDecimal? { var yscale = yscale // Normalize dividend & divisor so that both fall into [0.1, 0.999...] @@ -4513,7 +4722,7 @@ internal class CommonBigDecimal : BigDecimal { ys: CommonBigInteger?, yscale: Int, preferredScale: Long, - mc: MathContext + mc: MathContext, ): CommonBigDecimal? { var yscale = yscale // Normalize dividend & divisor so that both fall into [0.1, 0.999...] @@ -4552,7 +4761,7 @@ internal class CommonBigDecimal : BigDecimal { divisor: Long, scale: Int, roundingMode: Int, - preferredScale: Int + preferredScale: Int, ): CommonBigDecimal? { var dividend0 = dividend0 var dividend1 = dividend1 @@ -4600,7 +4809,7 @@ internal class CommonBigDecimal : BigDecimal { sign: Int, scale: Int, roundingMode: Int, - preferredScale: Int + preferredScale: Int, ): CommonBigDecimal? { var divisor = divisor if (dividendHi >= divisor) { @@ -4711,7 +4920,12 @@ internal class CommonBigDecimal : BigDecimal { * calculate divideAndRound for ldividend*10^raise / divisor * when absoluteValue(dividend)==absoluteValue(divisor); */ - private fun roundedTenPower(qsign: Int, raise: Int, scale: Int, preferredScale: Int): CommonBigDecimal { + private fun roundedTenPower( + qsign: Int, + raise: Int, + scale: Int, + preferredScale: Int, + ): CommonBigDecimal { if (scale > preferredScale) { val diff = scale - preferredScale return if (diff < raise) { @@ -4724,7 +4938,11 @@ internal class CommonBigDecimal : BigDecimal { } } - internal fun scaledTenPow(n: Int, sign: Int, scale: Int): CommonBigDecimal { + internal fun scaledTenPow( + n: Int, + sign: Int, + scale: Int, + ): CommonBigDecimal { if (n < LONG_TEN_POWERS_TABLE.size) { return of(sign * LONG_TEN_POWERS_TABLE[n], scale) } else { @@ -4745,7 +4963,10 @@ internal class CommonBigDecimal : BigDecimal { * @return a two-element {@long} array with the remainder and quotient in * the initial and final elements, respectively */ - private fun divRemNegativeLong(n: Long, d: Long): LongArray { + private fun divRemNegativeLong( + n: Long, + d: Long, + ): LongArray { require(n < 0) { "Non-negative numerator $n" } require(d != 1L) { "Unity denominator" } @@ -4767,25 +4988,45 @@ internal class CommonBigDecimal : BigDecimal { return longArrayOf(r, q) } - private fun make64(hi: Long, lo: Long): Long { + private fun make64( + hi: Long, + lo: Long, + ): Long { return hi shl 32 or lo } - private fun mulsub(u1: Long, u0: Long, v1: Long, v0: Long, q0: Long): Long { + private fun mulsub( + u1: Long, + u0: Long, + v1: Long, + v0: Long, + q0: Long, + ): Long { val tmp = u0 - q0 * v0 return make64(u1 + tmp.ushr(32) - q0 * v1, tmp and LONG_MASK) } - private fun unsignedLongCompare(one: Long, two: Long): Boolean { + private fun unsignedLongCompare( + one: Long, + two: Long, + ): Boolean { return one + Long.MIN_VALUE > two + Long.MIN_VALUE } - private fun unsignedLongCompareEq(one: Long, two: Long): Boolean { + private fun unsignedLongCompareEq( + one: Long, + two: Long, + ): Boolean { return one + Long.MIN_VALUE >= two + Long.MIN_VALUE } // Compare Normalize dividend & divisor so that both fall into [0.1, 0.999...] - private fun compareMagnitudeNormalized(xs: Long, xscale: Int, ys: Long, yscale: Int): Int { + private fun compareMagnitudeNormalized( + xs: Long, + xscale: Int, + ys: Long, + yscale: Int, + ): Int { var xs = xs var ys = ys // require xs!=0 && ys!=0 @@ -4805,7 +5046,12 @@ internal class CommonBigDecimal : BigDecimal { } // Compare Normalize dividend & divisor so that both fall into [0.1, 0.999...] - private fun compareMagnitudeNormalized(xs: Long, xscale: Int, ys: CommonBigInteger?, yscale: Int): Int { + private fun compareMagnitudeNormalized( + xs: Long, + xscale: Int, + ys: CommonBigInteger?, + yscale: Int, + ): Int { // require "ys can't be represented as long" if (xs == 0L) { return -1 @@ -4824,7 +5070,7 @@ internal class CommonBigDecimal : BigDecimal { xs: CommonBigInteger?, xscale: Int, ys: CommonBigInteger?, - yscale: Int + yscale: Int, ): Int { val sdiff = xscale - yscale return if (sdiff < 0) { @@ -4834,7 +5080,10 @@ internal class CommonBigDecimal : BigDecimal { } } - private fun multiply(x: Long, y: Long): Long { + private fun multiply( + x: Long, + y: Long, + ): Long { val product = x * y val ax = abs(x) val ay = abs(y) @@ -4845,7 +5094,11 @@ internal class CommonBigDecimal : BigDecimal { } } - private fun multiply(x: Long, y: Long, scale: Int): CommonBigDecimal { + private fun multiply( + x: Long, + y: Long, + scale: Int, + ): CommonBigDecimal { val product = multiply(x, y) return if (product != INFLATED) { of(product, scale) @@ -4854,7 +5107,11 @@ internal class CommonBigDecimal : BigDecimal { } } - private fun multiply(x: Long, y: CommonBigInteger?, scale: Int): CommonBigDecimal { + private fun multiply( + x: Long, + y: CommonBigInteger?, + scale: Int, + ): CommonBigDecimal { return if (x == 0L) { zeroValueOf(scale) } else { @@ -4862,14 +5119,23 @@ internal class CommonBigDecimal : BigDecimal { } } - private fun multiply(x: CommonBigInteger, y: CommonBigInteger?, scale: Int): CommonBigDecimal { + private fun multiply( + x: CommonBigInteger, + y: CommonBigInteger?, + scale: Int, + ): CommonBigDecimal { return CommonBigDecimal(x.times(y!!), INFLATED, scale, 0) } /** * Multiplies two long values and rounds according `MathContext` */ - private fun multiplyAndRound(x: Long, y: Long, scale: Int, mc: MathContext): CommonBigDecimal { + private fun multiplyAndRound( + x: Long, + y: Long, + scale: Int, + mc: MathContext, + ): CommonBigDecimal { var x = x var y = y var product = multiply(x, y) @@ -4915,7 +5181,12 @@ internal class CommonBigDecimal : BigDecimal { return doRound(res, mc)!! } - private fun multiplyAndRound(x: Long, y: CommonBigInteger?, scale: Int, mc: MathContext): CommonBigDecimal { + private fun multiplyAndRound( + x: Long, + y: CommonBigInteger?, + scale: Int, + mc: MathContext, + ): CommonBigDecimal { return if (x == 0L) { zeroValueOf(scale) } else { @@ -4927,7 +5198,7 @@ internal class CommonBigDecimal : BigDecimal { x: CommonBigInteger, y: CommonBigInteger?, scale: Int, - mc: MathContext + mc: MathContext, ): CommonBigDecimal { return doRound(x.times(y!!), scale, mc) } @@ -4936,22 +5207,29 @@ internal class CommonBigDecimal : BigDecimal { * rounds 128-bit value according `MathContext` * returns null if result can't be repsented as compact CommonBigDecimal. */ - private fun doRound128(hi: Long, lo: Long, sign: Int, scale: Int, mc: MathContext): CommonBigDecimal? { + private fun doRound128( + hi: Long, + lo: Long, + sign: Int, + scale: Int, + mc: MathContext, + ): CommonBigDecimal? { var scale = scale val mcp = mc.precision val drop: Int = precision(hi, lo) - mcp var res: CommonBigDecimal? = null if (drop > 0 && drop < LONG_TEN_POWERS_TABLE.size) { scale = checkScaleNonZero(scale.toLong() - drop) - res = divideAndRound128( - hi, - lo, - LONG_TEN_POWERS_TABLE[drop], - sign, - scale, - mc.roundingMode.value, - scale - ) + res = + divideAndRound128( + hi, + lo, + LONG_TEN_POWERS_TABLE[drop], + sign, + scale, + mc.roundingMode.value, + scale, + ) } return if (res != null) { doRound(res, mc) @@ -4960,33 +5238,57 @@ internal class CommonBigDecimal : BigDecimal { } } - private val LONGLONG_TEN_POWERS_TABLE = arrayOf( - longArrayOf(0L, -0x7538dcfb76180000L), // 10^19 - longArrayOf(0x5L, 0x6bc75e2d63100000L), // 10^20 - longArrayOf(0x36L, 0x35c9adc5dea00000L), // 10^21 - longArrayOf(0x21eL, 0x19e0c9bab2400000L), // 10^22 - longArrayOf(0x152dL, 0x02c7e14af6800000L), // 10^23 - longArrayOf(0xd3c2L, 0x1bcecceda1000000L), // 10^24 - longArrayOf(0x84595L, 0x161401484a000000L), // 10^25 - longArrayOf(0x52b7d2L, -0x2337f32d1c000000L), // 10^26 - longArrayOf(0x33b2e3cL, -0x602f7fc318000000L), // 10^27 - longArrayOf(0x204fce5eL, 0x3e25026110000000L), // 10^28 - longArrayOf(0x1431e0faeL, 0x6d7217caa0000000L), // 10^29 - longArrayOf(0xc9f2c9cd0L, 0x4674edea40000000L), // 10^30 - longArrayOf(0x7e37be2022L, -0x3f6eb4d980000000L), // 10^31 - longArrayOf(0x4ee2d6d415bL, -0x7a53107f00000000L), // 10^32 - longArrayOf(0x314dc6448d93L, 0x38c15b0a00000000L), // 10^33 - longArrayOf(0x1ed09bead87c0L, 0x378d8e6400000000L), // 10^34 - longArrayOf(0x13426172c74d82L, 0x2b878fe800000000L), // 10^35 - longArrayOf(0xc097ce7bc90715L, -0x4cb460f000000000L), // 10^36 - longArrayOf(0x785ee10d5da46d9L, 0x00f436a000000000L), // 10^37 - longArrayOf(0x4b3b4ca85a86c47aL, 0x098a224000000000L) - ) // 10^38 + private val LONGLONG_TEN_POWERS_TABLE = + arrayOf( + // 10^19 + longArrayOf(0L, -0x7538dcfb76180000L), + // 10^20 + longArrayOf(0x5L, 0x6bc75e2d63100000L), + // 10^21 + longArrayOf(0x36L, 0x35c9adc5dea00000L), + // 10^22 + longArrayOf(0x21eL, 0x19e0c9bab2400000L), + // 10^23 + longArrayOf(0x152dL, 0x02c7e14af6800000L), + // 10^24 + longArrayOf(0xd3c2L, 0x1bcecceda1000000L), + // 10^25 + longArrayOf(0x84595L, 0x161401484a000000L), + // 10^26 + longArrayOf(0x52b7d2L, -0x2337f32d1c000000L), + // 10^27 + longArrayOf(0x33b2e3cL, -0x602f7fc318000000L), + // 10^28 + longArrayOf(0x204fce5eL, 0x3e25026110000000L), + // 10^29 + longArrayOf(0x1431e0faeL, 0x6d7217caa0000000L), + // 10^30 + longArrayOf(0xc9f2c9cd0L, 0x4674edea40000000L), + // 10^31 + longArrayOf(0x7e37be2022L, -0x3f6eb4d980000000L), + // 10^32 + longArrayOf(0x4ee2d6d415bL, -0x7a53107f00000000L), + // 10^33 + longArrayOf(0x314dc6448d93L, 0x38c15b0a00000000L), + // 10^34 + longArrayOf(0x1ed09bead87c0L, 0x378d8e6400000000L), + // 10^35 + longArrayOf(0x13426172c74d82L, 0x2b878fe800000000L), + // 10^36 + longArrayOf(0xc097ce7bc90715L, -0x4cb460f000000000L), + // 10^37 + longArrayOf(0x785ee10d5da46d9L, 0x00f436a000000000L), + // 10^38 + longArrayOf(0x4b3b4ca85a86c47aL, 0x098a224000000000L), + ) /* * returns _precision of 128-bit value */ - private fun precision(hi: Long, lo: Long): Int { + private fun precision( + hi: Long, + lo: Long, + ): Int { if (hi == 0L) { if (lo >= 0) { return longDigitLength(lo) @@ -4996,11 +5298,12 @@ internal class CommonBigDecimal : BigDecimal { } val r = ((128 - hi.numberOfLeadingZeros() + 1) * 1233).ushr(12) val idx = r - 19 - return if (idx >= LONGLONG_TEN_POWERS_TABLE.size || longLongCompareMagnitude( + return if (idx >= LONGLONG_TEN_POWERS_TABLE.size || + longLongCompareMagnitude( hi, lo, LONGLONG_TEN_POWERS_TABLE[idx][0], - LONGLONG_TEN_POWERS_TABLE[idx][1] + LONGLONG_TEN_POWERS_TABLE[idx][1], ) ) { r @@ -5013,7 +5316,12 @@ internal class CommonBigDecimal : BigDecimal { * returns true if 128 bit number is less than * hi0 & hi1 should be non-negative */ - private fun longLongCompareMagnitude(hi0: Long, lo0: Long, hi1: Long, lo1: Long): Boolean { + private fun longLongCompareMagnitude( + hi0: Long, + lo0: Long, + hi1: Long, + lo1: Long, + ): Boolean { return if (hi0 != hi1) { hi0 < hi1 } else { @@ -5027,7 +5335,7 @@ internal class CommonBigDecimal : BigDecimal { divisor: Long, divisorScale: Int, scale: Int, - roundingMode: Int + roundingMode: Int, ): CommonBigDecimal { if (checkScale(dividend, scale.toLong() + divisorScale) > dividendScale) { val newScale = scale + divisorScale @@ -5038,14 +5346,15 @@ internal class CommonBigDecimal : BigDecimal { if (xs != INFLATED) { return divideAndRound(xs, divisor, scale, roundingMode, scale) } - val q = multiplyDivideAndRound( - LONG_TEN_POWERS_TABLE[raise], - dividend, - divisor, - scale, - roundingMode, - scale - ) + val q = + multiplyDivideAndRound( + LONG_TEN_POWERS_TABLE[raise], + dividend, + divisor, + scale, + roundingMode, + scale, + ) if (q != null) { return q } @@ -5073,7 +5382,7 @@ internal class CommonBigDecimal : BigDecimal { divisor: Long, divisorScale: Int, scale: Int, - roundingMode: Int + roundingMode: Int, ): CommonBigDecimal { if (checkScale(dividend, scale.toLong() + divisorScale) > dividendScale) { val newScale = scale + divisorScale @@ -5101,7 +5410,7 @@ internal class CommonBigDecimal : BigDecimal { divisor: CommonBigInteger?, divisorScale: Int, scale: Int, - roundingMode: Int + roundingMode: Int, ): CommonBigDecimal { if (checkScale(dividend, scale.toLong() + divisorScale) > dividendScale) { val newScale = scale + divisorScale @@ -5122,7 +5431,7 @@ internal class CommonBigDecimal : BigDecimal { divisor: CommonBigInteger?, divisorScale: Int, scale: Int, - roundingMode: Int + roundingMode: Int, ): CommonBigDecimal { if (checkScale(dividend, scale.toLong() + divisorScale) > dividendScale) { val newScale = scale + divisorScale diff --git a/src/commonMain/kotlin/org/gciatto/kt/math/CommonBigInteger.kt b/src/commonMain/kotlin/org/gciatto/kt/math/CommonBigInteger.kt index a50bbe8..69088af 100644 --- a/src/commonMain/kotlin/org/gciatto/kt/math/CommonBigInteger.kt +++ b/src/commonMain/kotlin/org/gciatto/kt/math/CommonBigInteger.kt @@ -21,9 +21,7 @@ * 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. */ @@ -134,7 +132,6 @@ import kotlin.random.Random @Suppress("NAME_SHADOWING", "VARIABLE_WITH_REDUNDANT_INITIALIZER") internal class CommonBigInteger : BigInteger { - /** * The _signum of this BigInteger: -1 for negative, 0 for zero, or * 1 for positive. Note that the BigInteger zero *must* have @@ -202,8 +199,6 @@ internal class CommonBigInteger : BigInteger { * * @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 @@ -531,7 +526,7 @@ internal class CommonBigInteger : BigInteger { destructiveMulAdd( magnitude, intRadix[10], - groupVal + groupVal, ) } _mag = trustedStripLeadingZeroInts(magnitude) @@ -543,7 +538,11 @@ internal class CommonBigInteger : BigInteger { // 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 { + private fun parseInt( + source: CharArray, + start: Int, + end: Int, + ): Int { var result = source[start].toDigit(10) if (result == -1) { throw NumberFormatException(source.concatToString()) @@ -600,11 +599,12 @@ internal class CommonBigInteger : BigInteger { if (bitLength < 2) { throw ArithmeticException("bitLength < 2") } - prime = if (bitLength < SMALL_PRIME_THRESHOLD) { - smallPrime(bitLength, certainty, rnd) - } else { - largePrime(bitLength, certainty, rnd) - } + prime = + if (bitLength < SMALL_PRIME_THRESHOLD) { + smallPrime(bitLength, certainty, rnd) + } else { + largePrime(bitLength, certainty, rnd) + } _signum = 1 _mag = prime._mag } @@ -678,11 +678,12 @@ internal class CommonBigInteger : BigInteger { while (true) { val searchSieve = BitSieve(result, searchLen) - val candidate = searchSieve.retrieve( - result, - DEFAULT_PRIME_CERTAINTY, - null!! - ) + val candidate = + searchSieve.retrieve( + result, + DEFAULT_PRIME_CERTAINTY, + null!!, + ) if (candidate != null) { return candidate } @@ -704,7 +705,10 @@ internal class CommonBigInteger : BigInteger { * @return `true` if this BigInteger is probably prime, * `false` if it's definitely composite. */ - internal fun primeToCertainty(certainty: Int, random: Random?): Boolean { + internal fun primeToCertainty( + certainty: Int, + random: Random?, + ): Boolean { var rounds = 0 val n = (max(certainty, Int.MAX_VALUE - 1) + 1) / 2 @@ -766,7 +770,10 @@ internal class CommonBigInteger : BigInteger { * This BigInteger is a positive, odd number greater than 2. * iterations<=50. */ - private fun passesMillerRabin(iterations: Int, rnd: Random?): Boolean { + 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) @@ -883,11 +890,12 @@ internal class CommonBigInteger : BigInteger { if (cmp == 0) { return ZERO } - var resultMag = if (cmp > 0) { - subtract(_mag, other._mag) - } else { - subtract(other._mag, _mag) - } + var resultMag = + if (cmp > 0) { + subtract(_mag, other._mag) + } else { + subtract(other._mag, _mag) + } resultMag = trustedStripLeadingZeroInts(resultMag) return CommonBigInteger(resultMag, if (cmp == _signum) 1 else -1) @@ -911,14 +919,15 @@ internal class CommonBigInteger : BigInteger { if (cmp == 0) { return ZERO } - var resultMag = if (cmp > 0) { - subtract( - _mag, - other.absoluteValue - ) - } else { - subtract(other.absoluteValue, _mag) - } + var resultMag = + if (cmp > 0) { + subtract( + _mag, + other.absoluteValue, + ) + } else { + subtract(other.absoluteValue, _mag) + } resultMag = trustedStripLeadingZeroInts(resultMag) return CommonBigInteger(resultMag, if (cmp == _signum) 1 else -1) } @@ -946,11 +955,12 @@ internal class CommonBigInteger : BigInteger { if (cmp == 0) { return ZERO } - var resultMag = if (cmp > 0) { - subtract(_mag, other._mag) - } else { - subtract(other._mag, _mag) - } + var resultMag = + if (cmp > 0) { + subtract(_mag, other._mag) + } else { + subtract(other._mag, _mag) + } resultMag = trustedStripLeadingZeroInts(resultMag) return CommonBigInteger(resultMag, if (cmp == _signum) 1 else -1) } @@ -988,13 +998,14 @@ internal class CommonBigInteger : BigInteger { if (_mag.size == 1) { return multiplyByInt(other._mag, _mag[0], resultSign) } - var result = multiplyToLen( - _mag, - xlen, - other._mag, - ylen, - null - ) + var result = + multiplyToLen( + _mag, + xlen, + other._mag, + ylen, + null, + ) result = trustedStripLeadingZeroInts(result) return CommonBigInteger(result, resultSign) } else { @@ -1040,8 +1051,9 @@ internal class CommonBigInteger : BigInteger { 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 + val product = + (value[i].toLong() and LONG_MASK) * dh + + (rmag[rstart].toLong() and LONG_MASK) + carry rmag[rstart--] = product.toInt() carry = product.ushr(32) } @@ -1066,7 +1078,12 @@ internal class CommonBigInteger : BigInteger { * slices to the appropriate position when multiplying different-sized * numbers. */ - private fun getToomSlice(lowerSize: Int, upperSize: Int, slice: Int, fullsize: Int): CommonBigInteger { + private fun getToomSlice( + lowerSize: Int, + upperSize: Int, + slice: Int, + fullsize: Int, + ): CommonBigInteger { var start: Int val end: Int val sliceSize: Int @@ -1364,7 +1381,7 @@ internal class CommonBigInteger : BigInteger { val r = a.divideKnuth(b, q) return arrayOf( q.toBigInteger(if (this._signum == other._signum) 1 else -1), - r!!.toBigInteger(this._signum) + r!!.toBigInteger(this._signum), ) // result[0] = q.toBigInteger(if (this._signum == other._signum) 1 else -1) // result[1] = r!!.toBigInteger(this._signum) @@ -1425,8 +1442,9 @@ internal class CommonBigInteger : BigInteger { */ private fun divideAndRemainderBurnikelZiegler(other: CommonBigInteger): Array { val q = MutableBigInteger() - val r = MutableBigInteger(this) - .divideAndRemainderBurnikelZiegler(MutableBigInteger(other), q) + val r = + MutableBigInteger(this) + .divideAndRemainderBurnikelZiegler(MutableBigInteger(other), q) val qBigInt = if (q.isZero) ZERO else q.toBigInteger(_signum * other._signum) val rBigInt = if (r.isZero) ZERO else r.toBigInteger(_signum) return arrayOf(qBigInt, rBigInt) @@ -1695,7 +1713,10 @@ internal class CommonBigInteger : BigInteger { * prime* to `m`. * @see .modInverse */ - override fun modPow(exponent: BigInteger, modulus: BigInteger): CommonBigInteger { + override fun modPow( + exponent: BigInteger, + modulus: BigInteger, + ): CommonBigInteger { var exponent: CommonBigInteger = exponent.castTo() val modulus: CommonBigInteger = modulus.castTo() if (modulus._signum <= 0) { @@ -1724,11 +1745,12 @@ internal class CommonBigInteger : BigInteger { exponent = exponent.unaryMinus() } - val base = if (this._signum < 0 || this >= modulus) { - this.rem(modulus) - } else { - this - } + val base = + if (this._signum < 0 || this >= modulus) { + this.rem(modulus) + } else { + this + } val result: CommonBigInteger if (modulus.testBit(0)) { // odd modulus result = base.oddModPow(exponent, modulus) @@ -1746,18 +1768,20 @@ internal class CommonBigInteger : BigInteger { 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 - } + 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) - } + val a1 = + if (m1 == ONE) { + ZERO + } else { + base2.oddModPow(exponent, m1) + } // Calculate (this ** exponent) rem m2 val a2 = base.modPow2(exponent, p) @@ -1786,7 +1810,10 @@ internal class CommonBigInteger : BigInteger { * Returns a BigInteger whose value is x to the power of y rem z. * Assumes: z is odd && x < z. */ - private fun oddModPow(y: CommonBigInteger, z: CommonBigInteger): CommonBigInteger { + private fun oddModPow( + y: CommonBigInteger, + z: CommonBigInteger, + ): CommonBigInteger { /* * The algorithm is adapted from Colin Plumb's C library. * @@ -1844,7 +1871,6 @@ internal class CommonBigInteger : BigInteger { * 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 } @@ -2027,7 +2053,10 @@ internal class CommonBigInteger : BigInteger { /** * Returns a BigInteger whose value is (this ** exponent) rem (2**p) */ - private fun modPow2(exponent: CommonBigInteger, p: Int): CommonBigInteger { + private fun modPow2( + exponent: CommonBigInteger, + p: Int, + ): CommonBigInteger { /* * Perform exponentiation using repeated squaring trick, chopping off * high order bits as indicated by modulus. @@ -2347,7 +2376,10 @@ internal class CommonBigInteger : BigInteger { return testBit(n) } - override operator fun set(n: Int, b: Boolean): CommonBigInteger { + override operator fun set( + n: Int, + b: Boolean, + ): CommonBigInteger { return if (b) setBit(n) else clearBit(n) } @@ -2908,11 +2940,6 @@ internal class CommonBigInteger : BigInteger { 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. @@ -2922,13 +2949,13 @@ internal class CommonBigInteger : BigInteger { return bitLength.ushr(5) + 1 } - /* Returns sign bit */ + // Returns sign bit private val signBit: Int get() { return if (_signum < 0) 1 else 0 } - /* Returns an int of sign bits */ + // Returns an int of sign bits private val signInt: Int get() { return if (_signum < 0) -1 else 0 @@ -3099,7 +3126,6 @@ internal class CommonBigInteger : BigInteger { } companion object { - /** * This mask is used to obtain the value of an int as if it were unsigned. */ @@ -3194,48 +3220,53 @@ internal class CommonBigInteger : BigInteger { // 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 - ) + 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) { + 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 @@ -3260,7 +3291,10 @@ internal class CommonBigInteger : BigInteger { } } - private fun randomBits(numBits: Int, rnd: Random): ByteArray { + private fun randomBits( + numBits: Int, + rnd: Random, + ): ByteArray { if (numBits < 0) { throw IllegalArgumentException("numBits must be non-negative") } @@ -3299,7 +3333,10 @@ internal class CommonBigInteger : BigInteger { */ @JvmStatic @JsName("probablePrime") - fun probablePrime(bitLength: Int, rnd: Random): CommonBigInteger { + fun probablePrime( + bitLength: Int, + rnd: Random, + ): CommonBigInteger { if (bitLength < 2) { throw ArithmeticException("bitLength < 2") } @@ -3308,13 +3345,13 @@ internal class CommonBigInteger : BigInteger { smallPrime( bitLength, DEFAULT_PRIME_CERTAINTY, - rnd + rnd, ) } else { largePrime( bitLength, DEFAULT_PRIME_CERTAINTY, - rnd + rnd, ) } } @@ -3326,7 +3363,11 @@ internal class CommonBigInteger : BigInteger { * * This method assumes bitLength > 1. */ - private fun smallPrime(bitLength: Int, certainty: Int, rnd: Random): CommonBigInteger { + private fun smallPrime( + bitLength: Int, + certainty: Int, + rnd: Random, + ): CommonBigInteger { val magLen = (bitLength + 31).ushr(5) val temp = IntArray(magLen) val highBit = 1 shl (bitLength + 31 and 0x1f) // High bit of high int @@ -3374,7 +3415,11 @@ internal class CommonBigInteger : BigInteger { * a sieve to eliminate most composites before using a more expensive * test. */ - private fun largePrime(bitLength: Int, certainty: Int, rnd: Random): CommonBigInteger { + private fun largePrime( + bitLength: Int, + certainty: Int, + rnd: Random, + ): CommonBigInteger { var p: CommonBigInteger p = CommonBigInteger(bitLength, rnd).setBit(bitLength - 1) p._mag[p._mag.size - 1] = p._mag[p._mag.size - 1] and -0x2 @@ -3407,7 +3452,10 @@ internal class CommonBigInteger : BigInteger { * Computes Jacobi(p,n). * Assumes n positive, odd, n>=3. */ - private fun jacobiSymbol(p: Int, n: CommonBigInteger): Int { + private fun jacobiSymbol( + p: Int, + n: CommonBigInteger, + ): Int { var p = p if (p == 0) { return 0 @@ -3474,7 +3522,11 @@ internal class CommonBigInteger : BigInteger { return 0 } - private fun lucasLehmerSequence(z: Int, k: CommonBigInteger, n: CommonBigInteger): CommonBigInteger { + private fun lucasLehmerSequence( + z: Int, + k: CommonBigInteger, + n: CommonBigInteger, + ): CommonBigInteger { val d = of(z.toLong()) var u = ONE var u2: CommonBigInteger @@ -3561,7 +3613,10 @@ internal class CommonBigInteger : BigInteger { @JsName("parseWithRadix") @JvmStatic - fun of(value: String, radix: Int): CommonBigInteger { + fun of( + value: String, + radix: Int, + ): CommonBigInteger { return CommonBigInteger(value, radix) } @@ -3669,7 +3724,10 @@ internal class CommonBigInteger : BigInteger { * a reference to that array. Assumes x.length > 0 and val is * non-negative */ - private fun sum(x: IntArray, other: Long): IntArray { + private fun sum( + x: IntArray, + other: Long, + ): IntArray { var sum: Long = 0 var xIndex = x.size val result: IntArray @@ -3717,7 +3775,10 @@ internal class CommonBigInteger : BigInteger { * a new int array to hold the answer and returns a reference to that * array. */ - private fun sum(x: IntArray, y: IntArray): IntArray { + private fun sum( + x: IntArray, + y: IntArray, + ): IntArray { var x = x var y = y // If x is shorter, swap the two arrays @@ -3765,7 +3826,10 @@ internal class CommonBigInteger : BigInteger { return result } - private fun subtract(other: Long, little: IntArray): IntArray { + private fun subtract( + other: Long, + little: IntArray, + ): IntArray { val highWord = other.ushr(32).toInt() if (highWord == 0) { val result = IntArray(1) @@ -3802,7 +3866,10 @@ internal class CommonBigInteger : BigInteger { * answer. * assumes val >= 0 */ - private fun subtract(big: IntArray, other: Long): IntArray { + private fun subtract( + big: IntArray, + other: Long, + ): IntArray { val highWord = other.ushr(32).toInt() var bigIndex = big.size val result = IntArray(bigIndex) @@ -3839,7 +3906,10 @@ internal class CommonBigInteger : BigInteger { * than the second. This method allocates the space necessary to hold the * answer. */ - private fun subtract(big: IntArray, little: IntArray): IntArray { + private fun subtract( + big: IntArray, + little: IntArray, + ): IntArray { var bigIndex = big.size val result = IntArray(bigIndex) var littleIndex = little.size @@ -3867,14 +3937,18 @@ internal class CommonBigInteger : BigInteger { return result } - private fun multiplyByInt(x: IntArray, y: Int, sign: Int): CommonBigInteger { + private fun multiplyByInt( + x: IntArray, + y: Int, + sign: Int, + ): CommonBigInteger { if (y.bitCount() == 1) { return CommonBigInteger( shl( x, - y.numberOfTrailingZeros() + y.numberOfTrailingZeros(), ), - sign + sign, ) } val xlen = x.size @@ -3899,13 +3973,25 @@ internal class CommonBigInteger : BigInteger { * 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 { + 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 { + 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 @@ -3933,8 +4019,9 @@ internal class CommonBigInteger : BigInteger { 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 + 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-- @@ -3945,7 +4032,10 @@ internal class CommonBigInteger : BigInteger { return z } - private fun multiplyToLenCheck(array: IntArray, length: Int) { + private fun multiplyToLenCheck( + array: IntArray, + length: Int, + ) { if (length <= 0) { return // not an error because multiplyToLen won't execute if len <= 0 } @@ -3970,7 +4060,10 @@ internal class CommonBigInteger : BigInteger { * * See: http://en.wikipedia.org/wiki/Karatsuba_algorithm */ - private fun multiplyKaratsuba(x: CommonBigInteger, y: CommonBigInteger): CommonBigInteger { + private fun multiplyKaratsuba( + x: CommonBigInteger, + y: CommonBigInteger, + ): CommonBigInteger { val xlen = x._mag.size val ylen = y._mag.size @@ -4028,7 +4121,10 @@ internal class CommonBigInteger : BigInteger { * LNCS #4547. Springer, Madrid, Spain, June 21-22, 2007. * */ - private fun multiplyToomCook3(a: CommonBigInteger, b: CommonBigInteger): CommonBigInteger { + private fun multiplyToomCook3( + a: CommonBigInteger, + b: CommonBigInteger, + ): CommonBigInteger { val alen = a._mag.size val blen = b._mag.size @@ -4073,9 +4169,10 @@ internal class CommonBigInteger : BigInteger { 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) - ) + 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. @@ -4108,7 +4205,11 @@ internal class CommonBigInteger : BigInteger { * 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 { + private fun squareToLen( + x: IntArray, + len: Int, + z: IntArray?, + ): IntArray { var z = z val zlen = len shl 1 if (z == null || z.size < zlen) { @@ -4123,20 +4224,25 @@ internal class CommonBigInteger : BigInteger { /** * Parameters validation. */ - private fun implSquareToLenChecks(x: IntArray, len: Int, z: IntArray, zlen: Int) { + 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 + len + " > " + x.size, ) } if (len * 2 > z.size) { throw IllegalArgumentException( "input length out of bound: " + - len * 2 + " > " + z.size + len * 2 + " > " + z.size, ) } if (zlen < 1) { @@ -4145,7 +4251,7 @@ internal class CommonBigInteger : BigInteger { if (zlen > z.size) { throw IllegalArgumentException( "input length out of bound: " + - len + " > " + z.size + len + " > " + z.size, ) } } @@ -4153,7 +4259,12 @@ internal class CommonBigInteger : BigInteger { /** * Java Runtime may use intrinsic for this method. */ - private fun implSquareToLen(x: IntArray, len: Int, z: IntArray, zlen: Int): IntArray { + 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 @@ -4233,7 +4344,11 @@ internal class CommonBigInteger : BigInteger { * 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 { + 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]) @@ -4258,7 +4373,11 @@ internal class CommonBigInteger : BigInteger { } // shifts a up to len right n bits assumes no leading zeros, 0 MONTGOMERY_INTRINSIC_THRESHOLD) { @@ -4342,12 +4474,18 @@ internal class CommonBigInteger : BigInteger { n, len, inv, - materialize(product, len) + materialize(product, len), ) } } - private fun implMontgomeryMultiplyChecks(a: IntArray, b: IntArray, n: IntArray, len: Int, product: IntArray?) { + 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") } @@ -4368,7 +4506,10 @@ internal class CommonBigInteger : BigInteger { // 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 { + private fun materialize( + z: IntArray?, + len: Int, + ): IntArray { var z = z if (z == null || z.size < len) { z = IntArray(len) @@ -4384,14 +4525,20 @@ internal class CommonBigInteger : BigInteger { n: IntArray, len: Int, inv: Long, - product: IntArray + 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 { + 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()) @@ -4403,7 +4550,12 @@ internal class CommonBigInteger : BigInteger { * 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 { + private fun montReduce( + n: IntArray, + mod: IntArray, + mlen: Int, + inv: Int, + ): IntArray { var c = 0 var len = mlen var offset = 0 @@ -4428,7 +4580,11 @@ internal class CommonBigInteger : BigInteger { * 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 { + 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 @@ -4445,7 +4601,11 @@ internal class CommonBigInteger : BigInteger { /** * Subtracts two numbers of same length, returning borrow. */ - private fun subN(a: IntArray, b: IntArray, len: Int): Int { + private fun subN( + a: IntArray, + b: IntArray, + len: Int, + ): Int { var len = len var sum: Long = 0 @@ -4460,7 +4620,13 @@ internal class CommonBigInteger : BigInteger { /** * Multiply an array by one word k and plus to result, return the carry */ - private fun mulAdd(out: IntArray, `in`: IntArray, offset: Int, len: Int, k: Int): Int { + private 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) } @@ -4469,7 +4635,13 @@ internal class CommonBigInteger : BigInteger { * Parameters validation. */ @Suppress("UNUSED_PARAMETER") - private fun implMulAddCheck(out: IntArray, `in`: IntArray, offset: Int, len: Int, k: Int) { + 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) } @@ -4487,15 +4659,22 @@ internal class CommonBigInteger : BigInteger { /** * Java Runtime may use intrinsic for this method. */ - private fun implMulAdd(out: IntArray, `in`: IntArray, offset: Int, len: Int, k: Int): Int { + 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 + val product = + (`in`[j].toLong() and LONG_MASK) * kLong + + (out[offset].toLong() and LONG_MASK) + carry out[offset--] = product.toInt() carry = product.ushr(32) } @@ -4506,7 +4685,12 @@ internal class CommonBigInteger : BigInteger { * Add one word to the number a mlen words into a. Return the resulting * carry. */ - private fun addOne(a: IntArray, offset: Int, mlen: Int, carry: Int): Int { + private fun addOne( + a: IntArray, + offset: Int, + mlen: Int, + carry: Int, + ): Int { var offset = offset var mlen = mlen offset = a.size - 1 - mlen - offset @@ -4538,7 +4722,10 @@ internal class CommonBigInteger : BigInteger { * @param n unsigned shift distance, in bits. * @return `_mag << n` */ - private fun shl(mag: IntArray, n: Int): IntArray { + private fun shl( + mag: IntArray, + n: Int, + ): IntArray { val nInts = n.ushr(5) val nBits = n and 0x1f val magLen = mag.size @@ -4579,7 +4766,12 @@ internal class CommonBigInteger : BigInteger { * @param radix The base to convert to. * @param digits The minimum number of digits to pad to. */ - private fun toString(u: CommonBigInteger, sb: StringBuilder, radix: Int, digits: Int) { + private fun toString( + u: CommonBigInteger, + 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) { @@ -4624,7 +4816,10 @@ internal class CommonBigInteger : BigInteger { * This could be changed to a more complicated caching method using * `Future`. */ - private fun getRadixConversionCache(radix: Int, exponent: Int): CommonBigInteger { + private fun getRadixConversionCache( + radix: Int, + exponent: Int, + ): CommonBigInteger { // volatile read val cacheLine: Array? = powerCache[radix] if (exponent < cacheLine!!.size) { @@ -4646,7 +4841,7 @@ internal class CommonBigInteger : BigInteger { return cacheLine2[exponent]!! } - /* zero[i] is a string of i consecutive zeros. */ + // zero[i] is a string of i consecutive zeros. private val zeros = arrayOfNulls(64) init { @@ -4689,7 +4884,11 @@ internal class CommonBigInteger : BigInteger { /** * Returns a copy of the input array stripped of any leading zero bytes. */ - private fun stripLeadingZeroBytes(a: ByteArray, off: Int, len: Int): IntArray { + private fun stripLeadingZeroBytes( + a: ByteArray, + off: Int, + len: Int, + ): IntArray { val indexBound = off + len var keep: Int @@ -4720,7 +4919,11 @@ internal class CommonBigInteger : BigInteger { * 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 { + private fun makePositive( + a: ByteArray, + off: Int, + len: Int, + ): IntArray { var keep: Int var k: Int val indexBound = off + len @@ -4821,167 +5024,171 @@ internal class CommonBigInteger : BigInteger { * 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 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) - ) + 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 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 - ) + 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, + ) } } diff --git a/src/commonMain/kotlin/org/gciatto/kt/math/Lock.kt b/src/commonMain/kotlin/org/gciatto/kt/math/Lock.kt index 52bfa72..0500911 100644 --- a/src/commonMain/kotlin/org/gciatto/kt/math/Lock.kt +++ b/src/commonMain/kotlin/org/gciatto/kt/math/Lock.kt @@ -1,3 +1,6 @@ package org.gciatto.kt.math -expect inline fun lock(any: Any, action: () -> R): R +expect inline fun lock( + any: Any, + action: () -> R, +): R diff --git a/src/commonMain/kotlin/org/gciatto/kt/math/MathContext.kt b/src/commonMain/kotlin/org/gciatto/kt/math/MathContext.kt index 7f3687b..0ad7e87 100644 --- a/src/commonMain/kotlin/org/gciatto/kt/math/MathContext.kt +++ b/src/commonMain/kotlin/org/gciatto/kt/math/MathContext.kt @@ -21,9 +21,7 @@ * 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 IBM Corporation, 1997, 2001. All Rights Reserved. */ diff --git a/src/commonMain/kotlin/org/gciatto/kt/math/MutableBigInteger.kt b/src/commonMain/kotlin/org/gciatto/kt/math/MutableBigInteger.kt index 557a1fd..82809b8 100644 --- a/src/commonMain/kotlin/org/gciatto/kt/math/MutableBigInteger.kt +++ b/src/commonMain/kotlin/org/gciatto/kt/math/MutableBigInteger.kt @@ -222,7 +222,7 @@ internal open class MutableBigInteger { } else { CommonBigInteger( magnitudeArray, - sign + sign, ) } } @@ -239,7 +239,10 @@ internal open class MutableBigInteger { * Convert this MutableBigInteger to BigDecimal object with the specified sign * and setScale. */ - fun toBigDecimal(sign: Int, scale: Int): CommonBigDecimal { + fun toBigDecimal( + sign: Int, + scale: Int, + ): CommonBigDecimal { if (intLen == 0 || sign == 0) { return CommonBigDecimal.zeroValueOf(scale) } @@ -251,11 +254,12 @@ internal open class MutableBigInteger { if (len > 2 || d < 0 && len == 2) { return CommonBigDecimal(CommonBigInteger(mag, sign), INFLATED, scale, 0) } - val v = if (len == 2) { - mag[1].toLong() and LONG_MASK or (d.toLong() and LONG_MASK shl 32) - } else { - d.toLong() and LONG_MASK - } + val v = + if (len == 2) { + mag[1].toLong() and LONG_MASK or (d.toLong() and LONG_MASK shl 32) + } else { + d.toLong() and LONG_MASK + } return CommonBigDecimal.of(if (sign == -1) -v else v, scale) } @@ -276,11 +280,12 @@ internal open class MutableBigInteger { if (len > 2 || d < 0 && len == 2) { return INFLATED } - val v = if (len == 2) { - mag[1].toLong() and LONG_MASK or (d.toLong() and LONG_MASK shl 32) - } else { - d.toLong() and LONG_MASK - } + val v = + if (len == 2) { + mag[1].toLong() and LONG_MASK or (d.toLong() and LONG_MASK shl 32) + } else { + d.toLong() and LONG_MASK + } return if (sign == -1) -v else v } @@ -344,7 +349,10 @@ internal open class MutableBigInteger { * Returns a value equal to what `b.leftShift(32*ints); return compare(b);` * would return, but doesn't change the value of `b`. */ - private fun compareShifted(b: MutableBigInteger, ints: Int): Int { + private fun compareShifted( + b: MutableBigInteger, + ints: Int, + ): Int { val blen = b.intLen val alen = intLen - ints if (alen < blen) { @@ -493,7 +501,10 @@ internal open class MutableBigInteger { * This does not get inlined on all platforms so it is not used * as often as originally intended. */ - fun setInt(index: Int, `val`: Int) { + fun setInt( + index: Int, + `val`: Int, + ) { value[offset + index] = `val` } @@ -501,7 +512,10 @@ internal open class MutableBigInteger { * Sets this MutableBigInteger's value array to the specified array. * The intLen is set to the specified length. */ - fun setValue(`val`: IntArray, length: Int) { + fun setValue( + `val`: IntArray, + length: Int, + ) { value = `val` intLen = length offset = 0 @@ -647,12 +661,17 @@ internal open class MutableBigInteger { * divisor a back to the dividend result at a specified offset. It is used * when qhat was estimated too large, and must be adjusted. */ - private fun divadd(a: IntArray, result: IntArray, offset: Int): Int { + private fun divadd( + a: IntArray, + result: IntArray, + offset: Int, + ): Int { var carry: Long = 0 for (j in a.indices.reversed()) { - val sum = (a[j].toLong() and LONG_MASK) + - (result[j + offset].toLong() and LONG_MASK) + carry + val sum = + (a[j].toLong() and LONG_MASK) + + (result[j + offset].toLong() and LONG_MASK) + carry result[j + offset] = sum.toInt() carry = sum.ushr(32) } @@ -664,7 +683,13 @@ internal open class MutableBigInteger { * word input x, and subtracts the n word product from q. This is needed * when subtracting qhat*divisor from dividend. */ - private fun mulsub(q: IntArray, a: IntArray, x: Int, len: Int, offset: Int): Int { + private fun mulsub( + q: IntArray, + a: IntArray, + x: Int, + len: Int, + offset: Int, + ): Int { var offset = offset val xLong = x.toLong() and LONG_MASK var carry: Long = 0 @@ -674,11 +699,12 @@ internal open class MutableBigInteger { val product = (a[j].toLong() and LONG_MASK) * xLong + carry val difference = q[offset] - product q[offset--] = difference.toInt() - carry = product.ushr(32) + if (difference and LONG_MASK > product.toInt().inv().toLong() and LONG_MASK) { - 1 - } else { - 0 - } + carry = product.ushr(32) + + if (difference and LONG_MASK > product.toInt().inv().toLong() and LONG_MASK) { + 1 + } else { + 0 + } } return carry.toInt() } @@ -687,7 +713,13 @@ internal open class MutableBigInteger { * The method is the same as mulsun, except the fact that q array is not * updated, the only result of the method is borrow flag. */ - private fun mulsubBorrow(q: IntArray, a: IntArray, x: Int, len: Int, offset: Int): Int { + private fun mulsubBorrow( + q: IntArray, + a: IntArray, + x: Int, + len: Int, + offset: Int, + ): Int { var offset = offset val xLong = x.toLong() and LONG_MASK var carry: Long = 0 @@ -695,11 +727,12 @@ internal open class MutableBigInteger { for (j in len - 1 downTo 0) { val product = (a[j].toLong() and LONG_MASK) * xLong + carry val difference = q[offset--] - product - carry = product.ushr(32) + if (difference and LONG_MASK > product.toInt().inv().toLong() and LONG_MASK) { - 1 - } else { - 0 - } + carry = product.ushr(32) + + if (difference and LONG_MASK > product.toInt().inv().toLong() and LONG_MASK) { + 1 + } else { + 0 + } } return carry.toInt() } @@ -838,7 +871,10 @@ internal open class MutableBigInteger { * Has the same effect as `addend.leftShift(32*ints); plus(addend);` * but doesn't change the value of `addend`. */ - fun addShifted(addend: MutableBigInteger, n: Int) { + fun addShifted( + addend: MutableBigInteger, + n: Int, + ) { if (addend.isZero) { return } @@ -905,7 +941,10 @@ internal open class MutableBigInteger { * not be greater than `n`. In other words, concatenates `this` * and `addend`. */ - fun addDisjoint(addend: MutableBigInteger?, n: Int) { + fun addDisjoint( + addend: MutableBigInteger?, + n: Int, + ) { if (addend!!.isZero) { return } @@ -943,7 +982,10 @@ internal open class MutableBigInteger { /** * Adds the low `n` ints of `addend`. */ - fun addLower(addend: MutableBigInteger, n: Int) { + fun addLower( + addend: MutableBigInteger, + n: Int, + ) { val a = MutableBigInteger(addend) if (a.offset + a.intLen >= n) { a.offset = a.offset + a.intLen - n @@ -1052,7 +1094,10 @@ internal open class MutableBigInteger { * Multiply the contents of two MutableBigInteger objects. The result is * placed into MutableBigInteger z. The contents of y are not changed. */ - fun multiply(y: MutableBigInteger, z: MutableBigInteger) { + fun multiply( + y: MutableBigInteger, + z: MutableBigInteger, + ) { val xLen = intLen val yLen = y.intLen val newLen = xLen + yLen @@ -1070,8 +1115,9 @@ internal open class MutableBigInteger { var j = yLen - 1 var k = yLen + xLen - 1 while (j >= 0) { - val product = (y.value[j + y.offset].toLong() and LONG_MASK) * - (value[xLen - 1 + offset].toLong() and LONG_MASK) + carry + val product = + (y.value[j + y.offset].toLong() and LONG_MASK) * + (value[xLen - 1 + offset].toLong() and LONG_MASK) + carry z.value[k] = product.toInt() carry = product.ushr(32) j-- @@ -1086,9 +1132,10 @@ internal open class MutableBigInteger { var j = yLen - 1 var k = yLen + i while (j >= 0) { - val product = (y.value[j + y.offset].toLong() and LONG_MASK) * - (value[i + offset].toLong() and LONG_MASK) + - (z.value[k].toLong() and LONG_MASK) + carry + val product = + (y.value[j + y.offset].toLong() and LONG_MASK) * + (value[i + offset].toLong() and LONG_MASK) + + (z.value[k].toLong() and LONG_MASK) + carry z.value[k] = product.toInt() carry = product.ushr(32) j-- @@ -1105,7 +1152,10 @@ internal open class MutableBigInteger { * Multiply the contents of this MutableBigInteger by the word y. The * result is placed into z. */ - fun mul(y: Int, z: MutableBigInteger) { + fun mul( + y: Int, + z: MutableBigInteger, + ) { if (y == 1) { z.copyValue(this) return @@ -1118,11 +1168,12 @@ internal open class MutableBigInteger { // Perform the multiplication word by word val ylong = y.toLong() and LONG_MASK - val zval = if (z.value.size < intLen + 1) { - IntArray(intLen + 1) - } else { - z.value - } + val zval = + if (z.value.size < intLen + 1) { + IntArray(intLen + 1) + } else { + z.value + } var carry: Long = 0 for (i in intLen - 1 downTo 0) { val product = ylong * (value[i + offset].toLong() and LONG_MASK) + carry @@ -1148,7 +1199,10 @@ internal open class MutableBigInteger { * * @return the remainder of the division is returned. */ - fun divideOneWord(divisor: Int, quotient: MutableBigInteger): Int { + fun divideOneWord( + divisor: Int, + quotient: MutableBigInteger, + ): Int { val divisorLong = divisor.toLong() and LONG_MASK // Special case of one word dividend @@ -1205,7 +1259,11 @@ internal open class MutableBigInteger { } } - fun divide(b: MutableBigInteger, quotient: MutableBigInteger, needRemainder: Boolean = true): MutableBigInteger? { + fun divide( + b: MutableBigInteger, + quotient: MutableBigInteger, + needRemainder: Boolean = true, + ): MutableBigInteger? { val bLenBelowThreshold = b.intLen < CommonBigInteger.BURNIKEL_ZIEGLER_THRESHOLD val lenDiffIsZieglerOffset = intLen - b.intLen < CommonBigInteger.BURNIKEL_ZIEGLER_OFFSET return if (bLenBelowThreshold || lenDiffIsZieglerOffset) { @@ -1229,7 +1287,7 @@ internal open class MutableBigInteger { fun divideKnuth( b: MutableBigInteger, quotient: MutableBigInteger, - needRemainder: Boolean = true + needRemainder: Boolean = true, ): MutableBigInteger? { var b = b if (b.intLen == 0) { @@ -1297,7 +1355,10 @@ internal open class MutableBigInteger { * @param quotient output parameter for `this/b` * @return the remainder */ - fun divideAndRemainderBurnikelZiegler(b: MutableBigInteger, quotient: MutableBigInteger): MutableBigInteger { + fun divideAndRemainderBurnikelZiegler( + b: MutableBigInteger, + quotient: MutableBigInteger, + ): MutableBigInteger { val r = intLen val s = b.intLen @@ -1368,7 +1429,10 @@ internal open class MutableBigInteger { * @param quotient output parameter for `this/b` * @return `this%b` */ - private fun divide2n1n(b: MutableBigInteger, quotient: MutableBigInteger): MutableBigInteger? { + private fun divide2n1n( + b: MutableBigInteger, + quotient: MutableBigInteger, + ): MutableBigInteger? { val n = b.intLen // step 1: base case @@ -1403,7 +1467,10 @@ internal open class MutableBigInteger { * @param quotient output parameter for `this/b` * @return `this%b` */ - private fun divide3n2n(b: MutableBigInteger, quotient: MutableBigInteger): MutableBigInteger { + private fun divide3n2n( + b: MutableBigInteger, + quotient: MutableBigInteger, + ): MutableBigInteger { val n = b.intLen / 2 // half the length of b in ints // step 1: view this as [a1,a2,a3] where each ai is n ints or less; let a12=[a1,a2] @@ -1461,7 +1528,11 @@ internal open class MutableBigInteger { * @param blockLength length of one block in units of 32 bits * @return */ - private fun getBlock(index: Int, numBlocks: Int, blockLength: Int): MutableBigInteger { + private fun getBlock( + index: Int, + numBlocks: Int, + blockLength: Int, + ): MutableBigInteger { val blockStart = index * blockLength if (blockStart >= intLen) { return MutableBigInteger() @@ -1494,7 +1565,10 @@ internal open class MutableBigInteger { * * @return the remainder of the division will be returned. */ - fun divide(v: Long, quotient: MutableBigInteger): Long { + fun divide( + v: Long, + quotient: MutableBigInteger, + ): Long { var v = v if (v == 0L) { throw ArithmeticException("BigInteger div by zero") @@ -1528,7 +1602,7 @@ internal open class MutableBigInteger { private fun divideMagnitude( div: MutableBigInteger, quotient: MutableBigInteger, - needRemainder: Boolean + needRemainder: Boolean, ): MutableBigInteger? { // assert div.intLen > 1 // D1 normalize the divisor @@ -1738,7 +1812,10 @@ internal open class MutableBigInteger { * value. The quotient will be placed into the provided quotient object & * the remainder object is returned. */ - private fun divideLongMagnitude(ldivisor: Long, quotient: MutableBigInteger): MutableBigInteger { + private fun divideLongMagnitude( + ldivisor: Long, + quotient: MutableBigInteger, + ): MutableBigInteger { var ldivisor = ldivisor // Remainder starts as dividend with space for a leading zero val rem = MutableBigInteger(IntArray(intLen + 1)) @@ -1853,7 +1930,12 @@ internal open class MutableBigInteger { * Specialized version of the method divadd. * dh is a high part of the divisor, dl is a low part */ - private fun divaddLong(dh: Int, dl: Int, result: IntArray, offset: Int): Int { + private fun divaddLong( + dh: Int, + dl: Int, + result: IntArray, + offset: Int, + ): Int { var carry: Long = 0 var sum = (dl.toLong() and LONG_MASK) + (result[1 + offset].toLong() and LONG_MASK) @@ -1871,26 +1953,35 @@ internal open class MutableBigInteger { * dh is a high part of the divisor, dl is a low part */ @Suppress("UNUSED_CHANGED_VALUE") - private fun mulsubLong(q: IntArray, dh: Int, dl: Int, x: Int, offset: Int): Int { + private fun mulsubLong( + q: IntArray, + dh: Int, + dl: Int, + x: Int, + offset: Int, + ): Int { var offset = offset val xLong = x.toLong()and LONG_MASK offset += 2 var product = (dl.toLong()and LONG_MASK) * xLong var difference = q[offset] - product q[offset--] = difference.toInt() - var carry = product.ushr(32) + if (difference.toLong()and LONG_MASK > product.inv().toLong()and LONG_MASK) { - 1 - } else { - 0 - } + var carry = + product.ushr(32) + + if (difference.toLong()and LONG_MASK > product.inv().toLong()and LONG_MASK) { + 1 + } else { + 0 + } product = (dh.toLong()and LONG_MASK) * xLong + carry difference = q[offset] - product q[offset--] = difference.toInt() - carry = product.ushr(32) + if (difference.toLong()and LONG_MASK > product.inv().toLong()and LONG_MASK) { - 1 - } else { - 0 - } + carry = product.ushr(32) + + if (difference.toLong()and LONG_MASK > product.inv().toLong()and LONG_MASK) { + 1 + } else { + 0 + } return carry.toInt() } @@ -1898,7 +1989,10 @@ internal open class MutableBigInteger { * Compare two longs as if they were unsigned. * Returns true iff one is bigger than two. */ - private fun unsignedLongCompare(one: Long, two: Long): Boolean { + private fun unsignedLongCompare( + one: Long, + two: Long, + ): Boolean { return one + Long.MIN_VALUE > two + Long.MIN_VALUE } @@ -1938,8 +2032,8 @@ internal open class MutableBigInteger { return MutableBigInteger( intArrayOf( xk.ushr(32).toInt(), - (xk.toLong() and LONG_MASK).toInt() - ) + (xk.toLong() and LONG_MASK).toInt(), + ), ) } @@ -2305,8 +2399,6 @@ internal open class MutableBigInteger { } companion object { - - // Constants /** * MutableBigInteger with one element value array with the value 1. Used by * BigDecimal divideAndRound to increment the quotient. Use this constant @@ -2332,7 +2424,14 @@ internal open class MutableBigInteger { */ val KNUTH_POW2_THRESH_ZEROS = 3 - private fun copyAndShift(src: IntArray, srcFrom: Int, srcLen: Int, dst: IntArray, dstFrom: Int, shift: Int) { + private fun copyAndShift( + src: IntArray, + srcFrom: Int, + srcLen: Int, + dst: IntArray, + dstFrom: Int, + shift: Int, + ) { var srcFrom = srcFrom val n2 = 32 - shift var c = src[srcFrom] @@ -2351,7 +2450,10 @@ internal open class MutableBigInteger { * Returns long value where high 32 bits contain remainder value and * low 32 bits contain quotient value. */ - fun divWord(n: Long, d: Int): Long { + fun divWord( + n: Long, + d: Int, + ): Long { val dLong = d.toLong() and LONG_MASK var r: Long var q: Long @@ -2381,7 +2483,10 @@ internal open class MutableBigInteger { /** * Calculate GCD of a and b interpreted as unsigned integers. */ - fun binaryGcd(a: Int, b: Int): Int { + fun binaryGcd( + a: Int, + b: Int, + ): Int { var a = a var b = b if (b == 0) { @@ -2442,12 +2547,15 @@ internal open class MutableBigInteger { /** * Calculate the multiplicative inverse of 2^k rem rem, where rem is odd. */ - fun modInverseBP2(mod: MutableBigInteger, k: Int): MutableBigInteger { + fun modInverseBP2( + mod: MutableBigInteger, + k: Int, + ): MutableBigInteger { // Copy the rem to protect original return fixup( MutableBigInteger(1), MutableBigInteger(mod), - k + k, ) } @@ -2456,7 +2564,11 @@ internal open class MutableBigInteger { * Calculates X such that X = C * 2^(-k) (rem P) * Assumes C

*/ - fun fixup(c: MutableBigInteger, p: MutableBigInteger, k: Int): MutableBigInteger { + fun fixup( + c: MutableBigInteger, + p: MutableBigInteger, + k: Int, + ): MutableBigInteger { val temp = MutableBigInteger() // Set r to the multiplicative inverse of p rem 2^32 val r = -inverseMod32(p.value[p.offset + p.intLen - 1]) @@ -2493,11 +2605,3 @@ internal open class MutableBigInteger { } } } -/** - * Calculates the quotient of this div b and places the quotient in the - * provided MutableBigInteger objects and the remainder object is returned. - * - */ -/** - * @see .divideKnuth - */ diff --git a/src/commonMain/kotlin/org/gciatto/kt/math/RoundingMode.kt b/src/commonMain/kotlin/org/gciatto/kt/math/RoundingMode.kt index 373f01b..16b8373 100644 --- a/src/commonMain/kotlin/org/gciatto/kt/math/RoundingMode.kt +++ b/src/commonMain/kotlin/org/gciatto/kt/math/RoundingMode.kt @@ -21,9 +21,7 @@ * 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 IBM Corporation, 2001. All Rights Reserved. */ package org.gciatto.kt.math @@ -102,11 +100,11 @@ import kotlin.jvm.JvmStatic * @author Joseph D. Darcy * @since 1.5 */ -// Legacy rounding mode constants in BigDecimal @Suppress("DEPRECATION") @JsExport -enum class RoundingMode(@JsName("value") val value: Int) { - +enum class RoundingMode( + @JsName("value") val value: Int, +) { /** * Rounding mode to round away from zero. Always increments the * digit prior to a non-zero discarded fraction. Note that this @@ -354,10 +352,10 @@ enum class RoundingMode(@JsName("value") val value: Int) { * * */ - UNNECESSARY(7); + UNNECESSARY(7), + ; companion object { - /** * Returns the `RoundingMode` object corresponding to a * legacy integer rounding mode constant in [BigDecimal]. diff --git a/src/commonMain/kotlin/org/gciatto/kt/math/SignedMutableBigInteger.kt b/src/commonMain/kotlin/org/gciatto/kt/math/SignedMutableBigInteger.kt index d82beb3..fe5c3df 100644 --- a/src/commonMain/kotlin/org/gciatto/kt/math/SignedMutableBigInteger.kt +++ b/src/commonMain/kotlin/org/gciatto/kt/math/SignedMutableBigInteger.kt @@ -46,7 +46,6 @@ package org.gciatto.kt.math */ internal class SignedMutableBigInteger : MutableBigInteger { - /** * The sign of this MutableBigInteger. */ diff --git a/src/commonMain/kotlin/org/gciatto/kt/math/Utils.kt b/src/commonMain/kotlin/org/gciatto/kt/math/Utils.kt index 3123b05..4f7a603 100644 --- a/src/commonMain/kotlin/org/gciatto/kt/math/Utils.kt +++ b/src/commonMain/kotlin/org/gciatto/kt/math/Utils.kt @@ -28,19 +28,24 @@ internal fun String.getRadix(): Pair { } } -internal const val PI_STRING = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862" + - "803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895" + - "4930381964428810975665933446128475648233786783165271201909145648" +internal const val PI_STRING = + "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862" + + "803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895" + + "4930381964428810975665933446128475648233786783165271201909145648" -internal const val E_STRING = "2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571" + - "382178525166427427466391932003059921817413596629043572900334295260595630738132328627943490763233829880753195" + - "251019011573834187930702154089149934884167509244761460668082264" +internal const val E_STRING = + "2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571" + + "382178525166427427466391932003059921817413596629043572900334295260595630738132328627943490763233829880753195" + + "251019011573834187930702154089149934884167509244761460668082264" internal expect fun logImpl(lazyObject: () -> Any) internal expect inline fun T?.castTo(): U -internal expect fun bigProbablePrimeInteger(bitLength: Int, rnd: Random): BigInteger +internal expect fun bigProbablePrimeInteger( + bitLength: Int, + rnd: Random, +): BigInteger internal expect fun bigIntegerOf(value: Long): BigInteger @@ -48,33 +53,70 @@ internal expect fun bigIntegerOf(value: Int): BigInteger internal expect fun bigIntegerOf(value: String): BigInteger -internal expect fun bigIntegerOf(value: String, radix: Int): BigInteger +internal expect fun bigIntegerOf( + value: String, + radix: Int, +): BigInteger internal expect fun bigIntegerOf(value: IntArray): BigInteger -internal expect fun bigIntegerOf(signum: Int, magnitude: ByteArray, off: Int = 0, len: Int = magnitude.size): BigInteger +internal expect fun bigIntegerOf( + signum: Int, + magnitude: ByteArray, + off: Int = 0, + len: Int = magnitude.size, +): BigInteger -internal expect fun bigDecimalOf(unscaledVal: Long, scale: Int): BigDecimal +internal expect fun bigDecimalOf( + unscaledVal: Long, + scale: Int, +): BigDecimal -internal expect fun bigDecimalOf(unscaledVal: Long, scale: Int, prec: Int): BigDecimal +internal expect fun bigDecimalOf( + unscaledVal: Long, + scale: Int, + prec: Int, +): BigDecimal internal expect fun bigDecimalOf(`val`: Int): BigDecimal internal expect fun bigDecimalOf(`val`: Long): BigDecimal -internal expect fun bigDecimalOf(intVal: BigInteger, scale: Int, prec: Int): BigDecimal - -internal expect fun bigDecimalOf(`val`: Double, ctx: MathContext? = null): BigDecimal - -internal expect fun bigDecimalOf(`val`: Float, ctx: MathContext? = null): BigDecimal - -internal expect fun bigDecimalOf(`val`: String, ctx: MathContext? = null): BigDecimal - -internal expect fun bigDecimalOf(`val`: BigInteger, ctx: MathContext? = null): BigDecimal - -internal expect fun bigDecimalOf(`val`: Int, ctx: MathContext): BigDecimal - -internal expect fun bigDecimalOf(`val`: Long, ctx: MathContext): BigDecimal +internal expect fun bigDecimalOf( + intVal: BigInteger, + scale: Int, + prec: Int, +): BigDecimal + +internal expect fun bigDecimalOf( + `val`: Double, + ctx: MathContext? = null, +): BigDecimal + +internal expect fun bigDecimalOf( + `val`: Float, + ctx: MathContext? = null, +): BigDecimal + +internal expect fun bigDecimalOf( + `val`: String, + ctx: MathContext? = null, +): BigDecimal + +internal expect fun bigDecimalOf( + `val`: BigInteger, + ctx: MathContext? = null, +): BigDecimal + +internal expect fun bigDecimalOf( + `val`: Int, + ctx: MathContext, +): BigDecimal + +internal expect fun bigDecimalOf( + `val`: Long, + ctx: MathContext, +): BigDecimal internal expect object BigIntegers { val zero: BigInteger @@ -242,13 +284,25 @@ internal fun Char.toDigit(radix: Int): Int { return -1 } -internal fun arrayCopy(src: Array, srcIndex: Int, dest: Array, destIndex: Int, size: Int) { +internal fun arrayCopy( + src: Array, + srcIndex: Int, + dest: Array, + destIndex: Int, + size: Int, +) { for (i in 0 until size) { dest[destIndex + i] = src[srcIndex + i] } } -internal fun arrayCopy(src: IntArray, srcIndex: Int, dest: IntArray, destIndex: Int, size: Int) { +internal fun arrayCopy( + src: IntArray, + srcIndex: Int, + dest: IntArray, + destIndex: Int, + size: Int, +) { for (i in 0 until size) { dest[destIndex + i] = src[srcIndex + i] } @@ -273,11 +327,17 @@ internal fun Int.bitCount(): Int { return i and 0x3f } -internal fun StringBuilder.insertChar(index: Int, char: Char): StringBuilder { +internal fun StringBuilder.insertChar( + index: Int, + char: Char, +): StringBuilder { return this.insertCharSeq(index, char.toString()) } -internal fun StringBuilder.insertCharSeq(index: Int, string: CharSequence): StringBuilder { +internal fun StringBuilder.insertCharSeq( + index: Int, + string: CharSequence, +): StringBuilder { val temp = StringBuilder(this.subSequence(0, index)) temp.append(string) temp.append(this.subSequence(index, this.length)) @@ -292,14 +352,22 @@ internal fun IntArray.fill(x: Int): IntArray { return this.fill(0, this.size, x) } -internal fun IntArray.fill(from: Int, to: Int, x: Int): IntArray { +internal fun IntArray.fill( + from: Int, + to: Int, + x: Int, +): IntArray { for (i in from until to) { this[i] = x } return this } -internal fun StringBuilder.appendCharArray(char: CharArray, offset: Int, len: Int): StringBuilder { +internal fun StringBuilder.appendCharArray( + char: CharArray, + offset: Int, + len: Int, +): StringBuilder { for (i in offset until offset + len) { append(char[i]) } diff --git a/src/commonTest/kotlin/org/gciatto/kt/math/AbstractIntBenchmark.kt b/src/commonTest/kotlin/org/gciatto/kt/math/AbstractIntBenchmark.kt index 231a7e6..43545ac 100644 --- a/src/commonTest/kotlin/org/gciatto/kt/math/AbstractIntBenchmark.kt +++ b/src/commonTest/kotlin/org/gciatto/kt/math/AbstractIntBenchmark.kt @@ -9,7 +9,6 @@ expect val REPETITIONS: Int expect val N: Int abstract class AbstractIntBenchmark(private val algos: IntAlgos) { - protected abstract fun bigInt(value: Int): T @ExperimentalTime @@ -20,7 +19,10 @@ abstract class AbstractIntBenchmark(private val algos: IntAlgos) { } @ExperimentalTime - private inline fun benchmark(times: Int, f: () -> R): Duration { + private inline fun benchmark( + times: Int, + f: () -> R, + ): Duration { var cumulative = Duration.ZERO repeat(times) { cumulative += chrono(f).second @@ -30,17 +32,19 @@ abstract class AbstractIntBenchmark(private val algos: IntAlgos) { @ExperimentalTime open fun benchmarkSumsViaFibonacci() { - val avgTime = benchmark(REPETITIONS) { - algos.fibonacciBasedBenchmark(bigInt(N)) - } + val avgTime = + benchmark(REPETITIONS) { + algos.fibonacciBasedBenchmark(bigInt(N)) + } println("[Fibonacci] Average duration on $REPETITIONS repetitions: $avgTime") } @ExperimentalTime open fun benchmarkMultiplicationsViaFactorial() { - val avgTime = benchmark(REPETITIONS) { - algos.factorialBasedBenchmark(bigInt(N)) - } + val avgTime = + benchmark(REPETITIONS) { + algos.factorialBasedBenchmark(bigInt(N)) + } println("[Factorial] Average duration on $REPETITIONS repetitions: $avgTime") } } diff --git a/src/commonTest/kotlin/org/gciatto/kt/math/Assertions.kt b/src/commonTest/kotlin/org/gciatto/kt/math/Assertions.kt index daa427f..25e4c49 100644 --- a/src/commonTest/kotlin/org/gciatto/kt/math/Assertions.kt +++ b/src/commonTest/kotlin/org/gciatto/kt/math/Assertions.kt @@ -2,7 +2,11 @@ package org.gciatto.kt.math import kotlin.test.assertEquals -fun assertBigIntegersAreEquals(x: BigInteger, y: BigInteger, m: String? = "Failed: $x == $y") { +fun assertBigIntegersAreEquals( + x: BigInteger, + y: BigInteger, + m: String? = "Failed: $x == $y", +) { if (m === null) { assertEquals(0, x.compareTo(y)) assertEquals(0, y.compareTo(x)) @@ -12,7 +16,11 @@ fun assertBigIntegersAreEquals(x: BigInteger, y: BigInteger, m: String? = "Faile } } -fun assertReprEquals(repr: Any, obj: Any, m: String? = "Failed: $obj.toString() == $repr") { +fun assertReprEquals( + repr: Any, + obj: Any, + m: String? = "Failed: $obj.toString() == $repr", +) { if (m === null) { assertEquals(repr.toString().lowercase(), obj.toString().lowercase()) } else { @@ -23,7 +31,7 @@ fun assertReprEquals(repr: Any, obj: Any, m: String? = "Failed: $obj.toString() fun assertBigDecimalsAreEquals( x: BigDecimal, y: BigDecimal, - m: String? = "Failed: ${x.toPlainString()} == ${y.toPlainString()}" + m: String? = "Failed: ${x.toPlainString()} == ${y.toPlainString()}", ) { if (m === null) { assertEquals(0, x.compareTo(y)) diff --git a/src/commonTest/kotlin/org/gciatto/kt/math/Contants.kt b/src/commonTest/kotlin/org/gciatto/kt/math/Contants.kt index c8d21b1..3563e18 100644 --- a/src/commonTest/kotlin/org/gciatto/kt/math/Contants.kt +++ b/src/commonTest/kotlin/org/gciatto/kt/math/Contants.kt @@ -8,10 +8,12 @@ expect val FLOAT_MIN_VALUE_REPR: String expect val FLOAT_MAX_VALUE_REPR: String -const val PI_REPR = "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342" + - "11706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196" + - "4428810975665933446128475648233786783165271201909145648" +const val PI_REPR = + "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342" + + "11706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196" + + "4428810975665933446128475648233786783165271201909145648" -const val E_REPR = "2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251" + - "66427427466391932003059921817413596629043572900334295260595630738132328627943490763233829880753195251019011" + - "573834187930702154089149934884167509244761460668082264" +const val E_REPR = + "2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251" + + "66427427466391932003059921817413596629043572900334295260595630738132328627943490763233829880753195251019011" + + "573834187930702154089149934884167509244761460668082264" diff --git a/src/commonTest/kotlin/org/gciatto/kt/math/KtIntAlgos.kt b/src/commonTest/kotlin/org/gciatto/kt/math/KtIntAlgos.kt index 2566fe1..27be6fa 100644 --- a/src/commonTest/kotlin/org/gciatto/kt/math/KtIntAlgos.kt +++ b/src/commonTest/kotlin/org/gciatto/kt/math/KtIntAlgos.kt @@ -3,31 +3,33 @@ package org.gciatto.kt.math import kotlin.test.assertEquals object KtIntAlgos : IntAlgos { - override fun fibonacci(n: BigInteger): BigInteger = when { - n < BigInteger.ZERO -> throw IllegalArgumentException("Cannot compute the fibonacci($n)") - n <= BigInteger.ONE -> BigInteger.ONE - else -> { - var prev = BigInteger.ONE - var curr = BigInteger.ONE - for (i in BigInteger.TWO..n) { - val next = curr + prev - prev = curr - curr = next + override fun fibonacci(n: BigInteger): BigInteger = + when { + n < BigInteger.ZERO -> throw IllegalArgumentException("Cannot compute the fibonacci($n)") + n <= BigInteger.ONE -> BigInteger.ONE + else -> { + var prev = BigInteger.ONE + var curr = BigInteger.ONE + for (i in BigInteger.TWO..n) { + val next = curr + prev + prev = curr + curr = next + } + curr } - curr } - } - override fun factorial(n: BigInteger): BigInteger = when { - n < BigInteger.ZERO -> throw IllegalArgumentException("Cannot compute the factorial($n)") - else -> { - var curr = BigInteger.ONE - for (i in BigInteger.TWO..n) { - curr *= i + override fun factorial(n: BigInteger): BigInteger = + when { + n < BigInteger.ZERO -> throw IllegalArgumentException("Cannot compute the factorial($n)") + else -> { + var curr = BigInteger.ONE + for (i in BigInteger.TWO..n) { + curr *= i + } + curr } - curr } - } override fun fibonacciBasedBenchmark(max: BigInteger) { val sequence = (BigInteger.ZERO..max).map(this::fibonacci).toList() diff --git a/src/commonTest/kotlin/org/gciatto/kt/math/TestDecimals.kt b/src/commonTest/kotlin/org/gciatto/kt/math/TestDecimals.kt index f39739e..79cff0c 100644 --- a/src/commonTest/kotlin/org/gciatto/kt/math/TestDecimals.kt +++ b/src/commonTest/kotlin/org/gciatto/kt/math/TestDecimals.kt @@ -5,7 +5,6 @@ import kotlin.test.assertEquals import kotlin.test.assertFailsWith class TestDecimals { - @Test fun testSpecialDoubles() { assertFailsWith { BigDecimal.of(Double.NaN) } @@ -94,52 +93,52 @@ class TestDecimals { assertReprEquals( PI_REPR, - BigDecimal.PI + BigDecimal.ZERO + BigDecimal.PI + BigDecimal.ZERO, ) assertReprEquals( "4" + PI_REPR.subSequence(1, PI_REPR.length), - BigDecimal.PI + BigDecimal.ONE + BigDecimal.PI + BigDecimal.ONE, ) assertReprEquals( "5" + PI_REPR.subSequence(1, PI_REPR.length), - BigDecimal.PI + BigDecimal.TWO + BigDecimal.PI + BigDecimal.TWO, ) assertReprEquals( "13" + PI_REPR.subSequence(1, PI_REPR.length), - BigDecimal.PI + BigDecimal.TEN + BigDecimal.PI + BigDecimal.TEN, ) assertReprEquals( PI_REPR.replace(".1", ".6"), - BigDecimal.PI + BigDecimal.ONE_HALF + BigDecimal.PI + BigDecimal.ONE_HALF, ) assertReprEquals( PI_REPR.replace(".1", ".2"), - BigDecimal.PI + BigDecimal.ONE_TENTH + BigDecimal.PI + BigDecimal.ONE_TENTH, ) assertReprEquals( E_REPR, - BigDecimal.E + BigDecimal.ZERO + BigDecimal.E + BigDecimal.ZERO, ) assertReprEquals( "3" + E_REPR.subSequence(1, E_REPR.length), - BigDecimal.E + BigDecimal.ONE + BigDecimal.E + BigDecimal.ONE, ) assertReprEquals( "4" + E_REPR.subSequence(1, E_REPR.length), - BigDecimal.E + BigDecimal.TWO + BigDecimal.E + BigDecimal.TWO, ) assertReprEquals( "12" + E_REPR.subSequence(1, E_REPR.length), - BigDecimal.E + BigDecimal.TEN + BigDecimal.E + BigDecimal.TEN, ) assertReprEquals( E_REPR.replace("2.7", "3.2"), - BigDecimal.E + BigDecimal.ONE_HALF + BigDecimal.E + BigDecimal.ONE_HALF, ) assertReprEquals( E_REPR.replace(".7", ".8"), - BigDecimal.E + BigDecimal.ONE_TENTH + BigDecimal.E + BigDecimal.ONE_TENTH, ) } @@ -159,62 +158,62 @@ class TestDecimals { assertReprEquals( PI_REPR, - BigDecimal.PI - BigDecimal.ZERO + BigDecimal.PI - BigDecimal.ZERO, ) assertReprEquals( "2" + PI_REPR.subSequence(1, PI_REPR.length), - BigDecimal.PI - BigDecimal.ONE + BigDecimal.PI - BigDecimal.ONE, ) assertReprEquals( "1" + PI_REPR.subSequence(1, PI_REPR.length), - BigDecimal.PI - BigDecimal.TWO + BigDecimal.PI - BigDecimal.TWO, ) assertReprEquals( "-6.85840734641020676153735661672049711580283060062489417902505540769218359371379100137196517465788" + "293201785191348671769335290615539044941776827464059187151888254971589729806147889444035537705104" + "5069618035571189024334066553871524351766213216834728798090854352", - BigDecimal.PI - BigDecimal.TEN + BigDecimal.PI - BigDecimal.TEN, ) assertReprEquals( PI_REPR.replace("3.1", "2.6"), - BigDecimal.PI - BigDecimal.ONE_HALF + BigDecimal.PI - BigDecimal.ONE_HALF, ) assertReprEquals( PI_REPR.replace(".1", ".0"), - BigDecimal.PI - BigDecimal.ONE_TENTH + BigDecimal.PI - BigDecimal.ONE_TENTH, ) assertReprEquals( E_REPR, - BigDecimal.E - BigDecimal.ZERO + BigDecimal.E - BigDecimal.ZERO, ) assertReprEquals( E_REPR.replace("2.7", "1.7"), - BigDecimal.E - BigDecimal.ONE + BigDecimal.E - BigDecimal.ONE, ) assertReprEquals( E_REPR.replace("2.", "0."), - BigDecimal.E - BigDecimal.TWO + BigDecimal.E - BigDecimal.TWO, ) assertReprEquals( "-7.28171817154095476463971252864733750224275290630004042503303237227592336964645240542861782147483" + "357257253360806799694007818258640337095642709966570473940436926186767137205650923676617011924680" + "4748980988426165812069297845910850065115832490755238539331917736", - BigDecimal.E - BigDecimal.TEN + BigDecimal.E - BigDecimal.TEN, ) assertReprEquals( E_REPR.replace("2.7", "2.2"), - BigDecimal.E - BigDecimal.ONE_HALF + BigDecimal.E - BigDecimal.ONE_HALF, ) assertReprEquals( E_REPR.replace("2.7", "2.6"), - BigDecimal.E - BigDecimal.ONE_TENTH + BigDecimal.E - BigDecimal.ONE_TENTH, ) log { "Notice that Double.MIN_VALUE=${Double.MIN_VALUE}" } assertReprEquals( BigDecimal.of(DOUBLE_MIN_VALUE_REPR) - BigDecimal.ONE, - BigDecimal.of(Double.MIN_VALUE) - BigDecimal.ONE + BigDecimal.of(Double.MIN_VALUE) - BigDecimal.ONE, ) } @@ -234,24 +233,24 @@ class TestDecimals { assertBigDecimalsAreEquals( BigDecimal.PI, - BigDecimal.of(PI_REPR) + BigDecimal.of(PI_REPR), ) assertBigDecimalsAreEquals( -BigDecimal.PI, - BigDecimal.of("-$PI_REPR") + BigDecimal.of("-$PI_REPR"), ) assertBigDecimalsAreEquals( BigDecimal.E, - BigDecimal.of(E_REPR) + BigDecimal.of(E_REPR), ) assertBigDecimalsAreEquals( -BigDecimal.E, - BigDecimal.of("-$E_REPR") + BigDecimal.of("-$E_REPR"), ) assertBigDecimalsAreEquals( BigDecimal.of(1, 1000), - BigDecimal.of("0." + (0 until 999).map { "0" }.joinToString("") + "1") + BigDecimal.of("0." + (0 until 999).map { "0" }.joinToString("") + "1"), ) } diff --git a/src/commonTest/kotlin/org/gciatto/kt/math/TestIntegers.kt b/src/commonTest/kotlin/org/gciatto/kt/math/TestIntegers.kt index f11a30e..014ca4b 100644 --- a/src/commonTest/kotlin/org/gciatto/kt/math/TestIntegers.kt +++ b/src/commonTest/kotlin/org/gciatto/kt/math/TestIntegers.kt @@ -4,7 +4,6 @@ import kotlin.test.Test import kotlin.test.assertEquals class TestIntegers { - @Test fun testToChar() { assertEquals((0).toChar(), BigInteger.of(0).toChar()) diff --git a/src/jsMain/kotlin/org/gciatto/kt/math/JsUtils.kt b/src/jsMain/kotlin/org/gciatto/kt/math/JsUtils.kt index 5160429..756d347 100644 --- a/src/jsMain/kotlin/org/gciatto/kt/math/JsUtils.kt +++ b/src/jsMain/kotlin/org/gciatto/kt/math/JsUtils.kt @@ -10,7 +10,10 @@ internal actual inline fun T?.castTo(): U { return this.unsafeCast() } -internal actual fun bigProbablePrimeInteger(bitLength: Int, rnd: Random): BigInteger { +internal actual fun bigProbablePrimeInteger( + bitLength: Int, + rnd: Random, +): BigInteger { return CommonBigInteger.probablePrime(bitLength, rnd) } @@ -26,7 +29,10 @@ internal actual fun bigIntegerOf(value: Int): BigInteger { return CommonBigInteger.of(value) } -internal actual fun bigIntegerOf(value: String, radix: Int): BigInteger { +internal actual fun bigIntegerOf( + value: String, + radix: Int, +): BigInteger { return CommonBigInteger.of(value, radix) } @@ -34,11 +40,18 @@ internal actual fun bigIntegerOf(value: IntArray): BigInteger { return CommonBigInteger.of(value) } -internal actual fun bigDecimalOf(unscaledVal: Long, scale: Int): BigDecimal { +internal actual fun bigDecimalOf( + unscaledVal: Long, + scale: Int, +): BigDecimal { return CommonBigDecimal.of(unscaledVal, scale) } -internal actual fun bigDecimalOf(unscaledVal: Long, scale: Int, prec: Int): BigDecimal { +internal actual fun bigDecimalOf( + unscaledVal: Long, + scale: Int, + prec: Int, +): BigDecimal { return CommonBigDecimal.of(unscaledVal, scale, prec) } @@ -50,39 +63,62 @@ internal actual fun bigDecimalOf(`val`: Long): BigDecimal { return CommonBigDecimal.of(`val`) } -internal actual fun bigDecimalOf(intVal: BigInteger, scale: Int, prec: Int): BigDecimal { +internal actual fun bigDecimalOf( + intVal: BigInteger, + scale: Int, + prec: Int, +): BigDecimal { return CommonBigDecimal.of(intVal.castTo(), scale, prec) } private val exceptionalDoubles = setOf(Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY) -internal actual fun bigDecimalOf(`val`: Double, ctx: MathContext?): BigDecimal = when { - `val` in exceptionalDoubles -> throw NumberFormatException("Infinite or NaN") - ctx == null -> CommonBigDecimal(`val`) - else -> CommonBigDecimal.of(`val`, ctx) -} +internal actual fun bigDecimalOf( + `val`: Double, + ctx: MathContext?, +): BigDecimal = + when { + `val` in exceptionalDoubles -> throw NumberFormatException("Infinite or NaN") + ctx == null -> CommonBigDecimal(`val`) + else -> CommonBigDecimal.of(`val`, ctx) + } -internal actual fun bigDecimalOf(`val`: Float, ctx: MathContext?): BigDecimal = bigDecimalOf(`val`.toDouble(), ctx) +internal actual fun bigDecimalOf( + `val`: Float, + ctx: MathContext?, +): BigDecimal = bigDecimalOf(`val`.toDouble(), ctx) -internal actual fun bigDecimalOf(`val`: String, ctx: MathContext?): BigDecimal = if (ctx == null) { - CommonBigDecimal(`val`) -} else { - CommonBigDecimal.of(`val`, ctx) -} - -internal actual fun bigDecimalOf(`val`: BigInteger, ctx: MathContext?): BigDecimal { - @Suppress("NAME_SHADOWING") - val `val`: CommonBigInteger = `val`.castTo() - return if (ctx == null) { +internal actual fun bigDecimalOf( + `val`: String, + ctx: MathContext?, +): BigDecimal = + if (ctx == null) { CommonBigDecimal(`val`) } else { CommonBigDecimal.of(`val`, ctx) } + +internal actual fun bigDecimalOf( + `val`: BigInteger, + ctx: MathContext?, +): BigDecimal { + val value: CommonBigInteger = `val`.castTo() + return if (ctx == null) { + CommonBigDecimal(value) + } else { + CommonBigDecimal.of(value, ctx) + } } -internal actual fun bigDecimalOf(`val`: Int, ctx: MathContext): BigDecimal = CommonBigDecimal.of(`val`, ctx) +internal actual fun bigDecimalOf( + `val`: Int, + ctx: MathContext, +): BigDecimal = CommonBigDecimal.of(`val`, ctx) -internal actual fun bigDecimalOf(`val`: Long, ctx: MathContext): BigDecimal = CommonBigDecimal.of(`val`, ctx) +internal actual fun bigDecimalOf( + `val`: Long, + ctx: MathContext, +): BigDecimal = CommonBigDecimal.of(`val`, ctx) internal actual object BigDecimals { actual val zero: BigDecimal = CommonBigDecimal.ZERO @@ -114,5 +150,9 @@ internal actual object BigIntegers { actual val negativeOne: BigInteger = CommonBigInteger.NEGATIVE_ONE } -internal actual fun bigIntegerOf(signum: Int, magnitude: ByteArray, off: Int, len: Int): BigInteger = - CommonBigInteger(signum, magnitude, off, len) +internal actual fun bigIntegerOf( + signum: Int, + magnitude: ByteArray, + off: Int, + len: Int, +): BigInteger = CommonBigInteger(signum, magnitude, off, len) diff --git a/src/jsMain/kotlin/org/gciatto/kt/math/Lock.kt b/src/jsMain/kotlin/org/gciatto/kt/math/Lock.kt index 76235cc..e8c5f0f 100644 --- a/src/jsMain/kotlin/org/gciatto/kt/math/Lock.kt +++ b/src/jsMain/kotlin/org/gciatto/kt/math/Lock.kt @@ -1,5 +1,8 @@ package org.gciatto.kt.math -actual inline fun lock(any: Any, action: () -> R): R { +actual inline fun lock( + any: Any, + action: () -> R, +): R { return action() } diff --git a/src/jsTest/kotlin/org/gciatto/kt/math/ActualConstants.kt b/src/jsTest/kotlin/org/gciatto/kt/math/ActualConstants.kt index 7ce302f..87b4ebf 100644 --- a/src/jsTest/kotlin/org/gciatto/kt/math/ActualConstants.kt +++ b/src/jsTest/kotlin/org/gciatto/kt/math/ActualConstants.kt @@ -1,26 +1,29 @@ package org.gciatto.kt.math actual val DOUBLE_MIN_VALUE_REPR: String - get() = "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + - "00000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363" + - "61635992379796564695445717730926656710355939796398774796010781878126300713190311404527845817167848982103" + - "68871863605699873072305000638740915356498438731247339727316961514003171538539807412623856559117102665855" + - "66867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478" + - "69014726780159355238611550134803526493472019379026810710749170333222684475333572083243193609238289345836" + - "80601060115061698097530783422773183292479049825247307763759272478746560847782037344696995336470179726777" + - "17585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565" + - "229087538682506419718265533447265625" + get() = + "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363" + + "61635992379796564695445717730926656710355939796398774796010781878126300713190311404527845817167848982103" + + "68871863605699873072305000638740915356498438731247339727316961514003171538539807412623856559117102665855" + + "66867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478" + + "69014726780159355238611550134803526493472019379026810710749170333222684475333572083243193609238289345836" + + "80601060115061698097530783422773183292479049825247307763759272478746560847782037344696995336470179726777" + + "17585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565" + + "229087538682506419718265533447265625" actual val DOUBLE_MAX_VALUE_REPR: String - get() = "17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817154" + - "04589535143824642343213268894641827684675467035375169860499105765512820762454900903893289440758685084551" + - "33942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368" + get() = + "17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817154" + + "04589535143824642343213268894641827684675467035375169860499105765512820762454900903893289440758685084551" + + "33942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368" actual val FLOAT_MAX_VALUE_REPR: String get() = "340282349999999991754788743781432688640" actual val FLOAT_MIN_VALUE_REPR: String - get() = "0.000000000000000000000000000000000000000000001400000000000000071092506322110639229558746633362094787994" + - "165184876665218144790470755953483168542669764206193340505025857201104599880636669695377349853515625" + get() = + "0.000000000000000000000000000000000000000000001400000000000000071092506322110639229558746633362094787994" + + "165184876665218144790470755953483168542669764206193340505025857201104599880636669695377349853515625" diff --git a/src/jvmMain/kotlin/org/gciatto/kt/math/JavaBigDecimalAdapter.kt b/src/jvmMain/kotlin/org/gciatto/kt/math/JavaBigDecimalAdapter.kt index 2774975..799078f 100644 --- a/src/jvmMain/kotlin/org/gciatto/kt/math/JavaBigDecimalAdapter.kt +++ b/src/jvmMain/kotlin/org/gciatto/kt/math/JavaBigDecimalAdapter.kt @@ -3,16 +3,17 @@ package org.gciatto.kt.math import java.math.BigDecimal as JavaBigDecimal class JavaBigDecimalAdapter(val value: JavaBigDecimal) : BigDecimal { - private inline fun adapt(f: () -> JavaBigDecimal): JavaBigDecimalAdapter = JavaBigDecimalAdapter(f()) private inline fun adapt( other: JavaBigDecimalAdapter, - f: (JavaBigDecimal) -> JavaBigDecimal + f: (JavaBigDecimal) -> JavaBigDecimal, ): JavaBigDecimalAdapter = JavaBigDecimalAdapter(f(other.value)) - private inline fun adapt(other: BigDecimal?, f: (JavaBigDecimal) -> JavaBigDecimal): JavaBigDecimalAdapter = - adapt(other.castTo(), f) + private inline fun adapt( + other: BigDecimal?, + f: (JavaBigDecimal) -> JavaBigDecimal, + ): JavaBigDecimalAdapter = adapt(other.castTo(), f) override val absoluteValue: BigDecimal get() = adapt { value.abs() } @@ -29,53 +30,83 @@ class JavaBigDecimalAdapter(val value: JavaBigDecimal) : BigDecimal { override val unscaledValue: BigInteger get() = JavaBigIntegerAdapter(value.unscaledValue()) - override fun plus(augend: BigDecimal?): BigDecimal = adapt(augend) { - value.add(it) - } - - override fun plus(augend: BigDecimal?, mc: MathContext): BigDecimal = adapt(augend) { - value.add(it, mc.toJava()) - } - - override fun minus(subtrahend: BigDecimal): BigDecimal = adapt(subtrahend) { - value.subtract(it) - } - - override fun minus(subtrahend: BigDecimal, mc: MathContext): BigDecimal = adapt(subtrahend) { - value.subtract(it, mc.toJava()) - } - - override fun times(multiplicand: BigDecimal?): BigDecimal = adapt(multiplicand) { - value.multiply(it) - } - - override fun times(multiplicand: BigDecimal, mc: MathContext): BigDecimal = adapt(multiplicand) { - value.multiply(it, mc.toJava()) - } - - override fun div(divisor: BigDecimal): BigDecimal = adapt(divisor) { - value.divide(it) - } - - override fun div(divisor: BigDecimal, mc: MathContext): BigDecimal = adapt(divisor) { - value.divide(it, mc.toJava()) - } - - override fun divideToIntegralValue(divisor: BigDecimal): BigDecimal = adapt(divisor) { - value.divideToIntegralValue(it) - } - - override fun divideToIntegralValue(divisor: BigDecimal, mc: MathContext): BigDecimal = adapt(divisor) { - value.divideToIntegralValue(it, mc.toJava()) - } - - override fun rem(divisor: BigDecimal): BigDecimal = adapt(divisor) { - value.remainder(it) - } - - override fun rem(divisor: BigDecimal, mc: MathContext): BigDecimal = adapt(divisor) { - value.remainder(it, mc.toJava()) - } + override fun plus(augend: BigDecimal?): BigDecimal = + adapt(augend) { + value.add(it) + } + + override fun plus( + augend: BigDecimal?, + mc: MathContext, + ): BigDecimal = + adapt(augend) { + value.add(it, mc.toJava()) + } + + override fun minus(subtrahend: BigDecimal): BigDecimal = + adapt(subtrahend) { + value.subtract(it) + } + + override fun minus( + subtrahend: BigDecimal, + mc: MathContext, + ): BigDecimal = + adapt(subtrahend) { + value.subtract(it, mc.toJava()) + } + + override fun times(multiplicand: BigDecimal?): BigDecimal = + adapt(multiplicand) { + value.multiply(it) + } + + override fun times( + multiplicand: BigDecimal, + mc: MathContext, + ): BigDecimal = + adapt(multiplicand) { + value.multiply(it, mc.toJava()) + } + + override fun div(divisor: BigDecimal): BigDecimal = + adapt(divisor) { + value.divide(it) + } + + override fun div( + divisor: BigDecimal, + mc: MathContext, + ): BigDecimal = + adapt(divisor) { + value.divide(it, mc.toJava()) + } + + override fun divideToIntegralValue(divisor: BigDecimal): BigDecimal = + adapt(divisor) { + value.divideToIntegralValue(it) + } + + override fun divideToIntegralValue( + divisor: BigDecimal, + mc: MathContext, + ): BigDecimal = + adapt(divisor) { + value.divideToIntegralValue(it, mc.toJava()) + } + + override fun rem(divisor: BigDecimal): BigDecimal = + adapt(divisor) { + value.remainder(it) + } + + override fun rem( + divisor: BigDecimal, + mc: MathContext, + ): BigDecimal = + adapt(divisor) { + value.remainder(it, mc.toJava()) + } private fun Array.toKotlinPair(): Pair = this[0].toKotlin() to this[1].toKotlin() @@ -83,75 +114,101 @@ class JavaBigDecimalAdapter(val value: JavaBigDecimal) : BigDecimal { override fun divideAndRemainder(divisor: BigDecimal): Pair = value.divideAndRemainder(divisor.toJava()).toKotlinPair() - override fun divideAndRemainder(divisor: BigDecimal, mc: MathContext): Pair = - value.divideAndRemainder(divisor.toJava(), mc.toJava()).toKotlinPair() - - override fun sqrt(mc: MathContext): BigDecimal = adapt { - value.sqrt(mc.toJava()) - } - - override fun pow(n: Int): BigDecimal = adapt { - value.pow(n) - } - - override fun pow(n: Int, mc: MathContext): BigDecimal = adapt { - value.pow(n, mc.toJava()) - } - - override fun absoluteValue(mc: MathContext): BigDecimal = adapt { - value.abs(mc.toJava()) - } - - override fun unaryMinus(): BigDecimal = adapt { - value.negate() - } - - override fun unaryMinus(mc: MathContext): BigDecimal = adapt { - value.negate(mc.toJava()) - } + override fun divideAndRemainder( + divisor: BigDecimal, + mc: MathContext, + ): Pair = value.divideAndRemainder(divisor.toJava(), mc.toJava()).toKotlinPair() + + override fun sqrt(mc: MathContext): BigDecimal = + adapt { + value.sqrt(mc.toJava()) + } + + override fun pow(n: Int): BigDecimal = + adapt { + value.pow(n) + } + + override fun pow( + n: Int, + mc: MathContext, + ): BigDecimal = + adapt { + value.pow(n, mc.toJava()) + } + + override fun absoluteValue(mc: MathContext): BigDecimal = + adapt { + value.abs(mc.toJava()) + } + + override fun unaryMinus(): BigDecimal = + adapt { + value.negate() + } + + override fun unaryMinus(mc: MathContext): BigDecimal = + adapt { + value.negate(mc.toJava()) + } override fun unaryPlus(): BigDecimal = this - override fun unaryPlus(mc: MathContext): BigDecimal = adapt { - value.plus(mc.toJava()) - } + override fun unaryPlus(mc: MathContext): BigDecimal = + adapt { + value.plus(mc.toJava()) + } - override fun round(mc: MathContext): BigDecimal = adapt { - value.round(mc.toJava()) - } + override fun round(mc: MathContext): BigDecimal = + adapt { + value.round(mc.toJava()) + } - override fun setScale(newScale: Int, roundingMode: RoundingMode): BigDecimal = adapt { - value.setScale(newScale, roundingMode.toJava()) - } + override fun setScale( + newScale: Int, + roundingMode: RoundingMode, + ): BigDecimal = + adapt { + value.setScale(newScale, roundingMode.toJava()) + } @Suppress("DEPRECATION") @Deprecated( "The method {@link #setScale(int, RoundingMode)} should " + - "be used in preference to this legacy method." + "be used in preference to this legacy method.", ) - override fun setScale(newScale: Int, roundingMode: Int): BigDecimal = adapt { - value.setScale(newScale, roundingMode) - } - - override fun setScale(newScale: Int): BigDecimal = adapt { - value.setScale(newScale) - } - - override fun movePointLeft(n: Int): BigDecimal = adapt { - value.movePointLeft(n) - } - - override fun movePointRight(n: Int): BigDecimal = adapt { - value.movePointRight(n) - } - - override fun scaleByPowerOfTen(n: Int): BigDecimal = adapt { - value.scaleByPowerOfTen(n) - } - - override fun stripTrailingZeros(): BigDecimal = adapt { - value.stripTrailingZeros() - } + override fun setScale( + newScale: Int, + roundingMode: Int, + ): BigDecimal = + adapt { + value.setScale(newScale, roundingMode) + } + + override fun setScale(newScale: Int): BigDecimal = + adapt { + value.setScale(newScale) + } + + override fun movePointLeft(n: Int): BigDecimal = + adapt { + value.movePointLeft(n) + } + + override fun movePointRight(n: Int): BigDecimal = + adapt { + value.movePointRight(n) + } + + override fun scaleByPowerOfTen(n: Int): BigDecimal = + adapt { + value.scaleByPowerOfTen(n) + } + + override fun stripTrailingZeros(): BigDecimal = + adapt { + value.stripTrailingZeros() + } @Suppress("NAME_SHADOWING") override fun compareTo(other: BigDecimal): Int { @@ -159,13 +216,15 @@ class JavaBigDecimalAdapter(val value: JavaBigDecimal) : BigDecimal { return value.compareTo(other.value) } - override fun min(`val`: BigDecimal): BigDecimal = adapt(`val`) { - value.min(it) - } + override fun min(`val`: BigDecimal): BigDecimal = + adapt(`val`) { + value.min(it) + } - override fun max(`val`: BigDecimal): BigDecimal = adapt(`val`) { - value.max(it) - } + override fun max(`val`: BigDecimal): BigDecimal = + adapt(`val`) { + value.max(it) + } override fun toEngineeringString(): String = value.toEngineeringString() diff --git a/src/jvmMain/kotlin/org/gciatto/kt/math/JavaBigIntegerAdapter.kt b/src/jvmMain/kotlin/org/gciatto/kt/math/JavaBigIntegerAdapter.kt index 41f0366..04723a6 100644 --- a/src/jvmMain/kotlin/org/gciatto/kt/math/JavaBigIntegerAdapter.kt +++ b/src/jvmMain/kotlin/org/gciatto/kt/math/JavaBigIntegerAdapter.kt @@ -3,16 +3,17 @@ package org.gciatto.kt.math import java.math.BigInteger as JavaBigInteger internal class JavaBigIntegerAdapter(val value: JavaBigInteger) : BigInteger { - private inline fun adapt(f: () -> JavaBigInteger): JavaBigIntegerAdapter = JavaBigIntegerAdapter(f()) private inline fun adapt( other: JavaBigIntegerAdapter, - f: (JavaBigInteger) -> JavaBigInteger + f: (JavaBigInteger) -> JavaBigInteger, ): JavaBigIntegerAdapter = JavaBigIntegerAdapter(f(other.value)) - private inline fun adapt(other: BigInteger, f: (JavaBigInteger) -> JavaBigInteger): JavaBigIntegerAdapter = - adapt(other.castTo(), f) + private inline fun adapt( + other: BigInteger, + f: (JavaBigInteger) -> JavaBigInteger, + ): JavaBigIntegerAdapter = adapt(other.castTo(), f) private inline fun adaptAll(f: () -> Array): Array { val javaInts = f() @@ -21,7 +22,7 @@ internal class JavaBigIntegerAdapter(val value: JavaBigInteger) : BigInteger { private inline fun adaptAll( other: BigInteger, - f: (JavaBigInteger) -> Array + f: (JavaBigInteger) -> Array, ): Array { val javaInts = f(other.castTo()) return Array(javaInts.size) { index -> adapt { javaInts[index] } } @@ -39,9 +40,10 @@ internal class JavaBigIntegerAdapter(val value: JavaBigInteger) : BigInteger { override val bitCount: Int get() = value.bitCount() - override fun nextProbablePrime(): BigInteger = adapt { - value.nextProbablePrime() - } + override fun nextProbablePrime(): BigInteger = + adapt { + value.nextProbablePrime() + } override fun plus(other: BigInteger): BigInteger = adapt(other) { value.add(it) } @@ -51,9 +53,10 @@ internal class JavaBigIntegerAdapter(val value: JavaBigInteger) : BigInteger { override fun div(other: BigInteger): BigInteger = adapt(other) { value.divide(it) } - override fun divideAndRemainder(other: BigInteger): Array = adaptAll(other) { - value.divideAndRemainder(it) - } + override fun divideAndRemainder(other: BigInteger): Array = + adaptAll(other) { + value.divideAndRemainder(it) + } override fun remainder(other: BigInteger): BigInteger = adapt(other) { value.remainder(it) } @@ -71,9 +74,13 @@ internal class JavaBigIntegerAdapter(val value: JavaBigInteger) : BigInteger { override fun rem(modulus: BigInteger): BigInteger = adapt(modulus) { value.remainder(it) } - override fun modPow(exponent: BigInteger, modulus: BigInteger): BigInteger = adapt(exponent) { - value.modPow(it, modulus.castTo().value) - } + override fun modPow( + exponent: BigInteger, + modulus: BigInteger, + ): BigInteger = + adapt(exponent) { + value.modPow(it, modulus.castTo().value) + } override fun modInverse(modulus: BigInteger): BigInteger = adapt(modulus) { value.modInverse(it) } @@ -95,9 +102,13 @@ internal class JavaBigIntegerAdapter(val value: JavaBigInteger) : BigInteger { override fun get(n: Int): Boolean = testBit(n) - override fun set(n: Int, b: Boolean): BigInteger = adapt { - if (b) value.setBit(n) else value.clearBit(n) - } + override fun set( + n: Int, + b: Boolean, + ): BigInteger = + adapt { + if (b) value.setBit(n) else value.clearBit(n) + } override fun setBit(n: Int): BigInteger = adapt { value.setBit(n) } diff --git a/src/jvmMain/kotlin/org/gciatto/kt/math/JvmUtils.kt b/src/jvmMain/kotlin/org/gciatto/kt/math/JvmUtils.kt index c0e712e..ddc019e 100644 --- a/src/jvmMain/kotlin/org/gciatto/kt/math/JvmUtils.kt +++ b/src/jvmMain/kotlin/org/gciatto/kt/math/JvmUtils.kt @@ -13,15 +13,17 @@ internal actual fun logImpl(lazyObject: () -> Any) { System.err.println(lazyObject()) } -fun BigInteger.toJava(): JavaBigInteger = when (this) { - is JavaBigIntegerAdapter -> value - else -> JavaBigInteger(this.toByteArray()) -} - -fun BigDecimal.toJava(): JavaBigDecimal = when (this) { - is JavaBigDecimalAdapter -> value - else -> JavaBigDecimal(unscaledValue.toJava(), scale, JavaMathContext(precision, JavaRoundingMode.UNNECESSARY)) -} +fun BigInteger.toJava(): JavaBigInteger = + when (this) { + is JavaBigIntegerAdapter -> value + else -> JavaBigInteger(this.toByteArray()) + } + +fun BigDecimal.toJava(): JavaBigDecimal = + when (this) { + is JavaBigDecimalAdapter -> value + else -> JavaBigDecimal(unscaledValue.toJava(), scale, JavaMathContext(precision, JavaRoundingMode.UNNECESSARY)) + } fun JavaRoundingMode.toKotlin(): RoundingMode = RoundingMode.valueOf(ordinal) @@ -41,8 +43,10 @@ fun JavaBigDecimal.toKotlin(): BigDecimal = fromJava(this) internal actual inline fun T?.castTo(): U = this as U -internal actual fun bigProbablePrimeInteger(bitLength: Int, rnd: Random): BigInteger = - JavaBigIntegerAdapter(JavaBigInteger.probablePrime(bitLength, rnd.asJavaRandom())) +internal actual fun bigProbablePrimeInteger( + bitLength: Int, + rnd: Random, +): BigInteger = JavaBigIntegerAdapter(JavaBigInteger.probablePrime(bitLength, rnd.asJavaRandom())) internal actual fun bigIntegerOf(value: Long): BigInteger = JavaBigIntegerAdapter(JavaBigInteger.valueOf(value)) @@ -53,59 +57,93 @@ internal actual fun bigIntegerOf(value: String): BigInteger { internal actual fun bigIntegerOf(value: Int): BigInteger = JavaBigIntegerAdapter(JavaBigInteger.valueOf(value.toLong())) -internal actual fun bigIntegerOf(value: String, radix: Int): BigInteger = - JavaBigIntegerAdapter(JavaBigInteger(value, radix)) +internal actual fun bigIntegerOf( + value: String, + radix: Int, +): BigInteger = JavaBigIntegerAdapter(JavaBigInteger(value, radix)) internal actual fun bigIntegerOf(value: IntArray): BigInteger = JavaBigIntegerAdapter(CommonBigInteger.of(value).toJava()) -internal actual fun bigDecimalOf(unscaledVal: Long, scale: Int): BigDecimal = - JavaBigDecimalAdapter(JavaBigDecimal.valueOf(unscaledVal, scale)) - -internal actual fun bigDecimalOf(unscaledVal: Long, scale: Int, prec: Int): BigDecimal = JavaBigDecimalAdapter( - JavaBigDecimal( - JavaBigInteger.valueOf(unscaledVal), - scale, - JavaMathContext(prec, JavaRoundingMode.UNNECESSARY) +internal actual fun bigDecimalOf( + unscaledVal: Long, + scale: Int, +): BigDecimal = JavaBigDecimalAdapter(JavaBigDecimal.valueOf(unscaledVal, scale)) + +internal actual fun bigDecimalOf( + unscaledVal: Long, + scale: Int, + prec: Int, +): BigDecimal = + JavaBigDecimalAdapter( + JavaBigDecimal( + JavaBigInteger.valueOf(unscaledVal), + scale, + JavaMathContext(prec, JavaRoundingMode.UNNECESSARY), + ), ) -) internal actual fun bigDecimalOf(`val`: Int): BigDecimal = JavaBigDecimalAdapter(JavaBigDecimal.valueOf(`val`.toLong())) internal actual fun bigDecimalOf(`val`: Long): BigDecimal = JavaBigDecimalAdapter(JavaBigDecimal.valueOf(`val`)) -internal actual fun bigDecimalOf(intVal: BigInteger, scale: Int, prec: Int): BigDecimal = JavaBigDecimalAdapter( - JavaBigDecimal( - intVal.toJava(), - scale, - JavaMathContext(prec, JavaRoundingMode.UNNECESSARY) +internal actual fun bigDecimalOf( + intVal: BigInteger, + scale: Int, + prec: Int, +): BigDecimal = + JavaBigDecimalAdapter( + JavaBigDecimal( + intVal.toJava(), + scale, + JavaMathContext(prec, JavaRoundingMode.UNNECESSARY), + ), ) -) - -internal actual fun bigDecimalOf(`val`: Double, ctx: MathContext?): BigDecimal = if (ctx == null) { - JavaBigDecimalAdapter(JavaBigDecimal(`val`)) -} else { - JavaBigDecimalAdapter(JavaBigDecimal(`val`, ctx.toJava())) -} - -internal actual fun bigDecimalOf(`val`: Float, ctx: MathContext?): BigDecimal = bigDecimalOf(`val`.toDouble(), ctx) - -internal actual fun bigDecimalOf(`val`: String, ctx: MathContext?): BigDecimal = if (ctx == null) { - JavaBigDecimalAdapter(JavaBigDecimal(`val`)) -} else { - JavaBigDecimalAdapter(JavaBigDecimal(`val`, ctx.toJava())) -} - -internal actual fun bigDecimalOf(`val`: BigInteger, ctx: MathContext?): BigDecimal = if (ctx == null) { - JavaBigDecimalAdapter(JavaBigDecimal(`val`.toJava())) -} else { - JavaBigDecimalAdapter(JavaBigDecimal(`val`.toJava(), ctx.toJava())) -} - -internal actual fun bigDecimalOf(`val`: Int, ctx: MathContext): BigDecimal = bigDecimalOf(`val`.toLong(), ctx) -internal actual fun bigDecimalOf(`val`: Long, ctx: MathContext): BigDecimal = - JavaBigDecimalAdapter(JavaBigDecimal(`val`, ctx.toJava())) +internal actual fun bigDecimalOf( + `val`: Double, + ctx: MathContext?, +): BigDecimal = + if (ctx == null) { + JavaBigDecimalAdapter(JavaBigDecimal(`val`)) + } else { + JavaBigDecimalAdapter(JavaBigDecimal(`val`, ctx.toJava())) + } + +internal actual fun bigDecimalOf( + `val`: Float, + ctx: MathContext?, +): BigDecimal = bigDecimalOf(`val`.toDouble(), ctx) + +internal actual fun bigDecimalOf( + `val`: String, + ctx: MathContext?, +): BigDecimal = + if (ctx == null) { + JavaBigDecimalAdapter(JavaBigDecimal(`val`)) + } else { + JavaBigDecimalAdapter(JavaBigDecimal(`val`, ctx.toJava())) + } + +internal actual fun bigDecimalOf( + `val`: BigInteger, + ctx: MathContext?, +): BigDecimal = + if (ctx == null) { + JavaBigDecimalAdapter(JavaBigDecimal(`val`.toJava())) + } else { + JavaBigDecimalAdapter(JavaBigDecimal(`val`.toJava(), ctx.toJava())) + } + +internal actual fun bigDecimalOf( + `val`: Int, + ctx: MathContext, +): BigDecimal = bigDecimalOf(`val`.toLong(), ctx) + +internal actual fun bigDecimalOf( + `val`: Long, + ctx: MathContext, +): BigDecimal = JavaBigDecimalAdapter(JavaBigDecimal(`val`, ctx.toJava())) internal actual object BigDecimals { actual val zero: BigDecimal = JavaBigDecimal.ZERO.toKotlin() @@ -137,5 +175,9 @@ internal actual object BigIntegers { actual val negativeOne: BigInteger = JavaBigInteger.ONE.negate().toKotlin() } -internal actual fun bigIntegerOf(signum: Int, magnitude: ByteArray, off: Int, len: Int): BigInteger = - CommonBigInteger(signum, magnitude, off, len).toJava().toKotlin() +internal actual fun bigIntegerOf( + signum: Int, + magnitude: ByteArray, + off: Int, + len: Int, +): BigInteger = CommonBigInteger(signum, magnitude, off, len).toJava().toKotlin() diff --git a/src/jvmMain/kotlin/org/gciatto/kt/math/Lock.kt b/src/jvmMain/kotlin/org/gciatto/kt/math/Lock.kt index aed97a2..28de1f8 100644 --- a/src/jvmMain/kotlin/org/gciatto/kt/math/Lock.kt +++ b/src/jvmMain/kotlin/org/gciatto/kt/math/Lock.kt @@ -1,5 +1,8 @@ package org.gciatto.kt.math -actual inline fun lock(any: Any, action: () -> R): R { +actual inline fun lock( + any: Any, + action: () -> R, +): R { return synchronized(any, action) } diff --git a/src/jvmTest/kotlin/org/gciatto/kt/math/ActualConstants.kt b/src/jvmTest/kotlin/org/gciatto/kt/math/ActualConstants.kt index 07e3149..6808c5d 100644 --- a/src/jvmTest/kotlin/org/gciatto/kt/math/ActualConstants.kt +++ b/src/jvmTest/kotlin/org/gciatto/kt/math/ActualConstants.kt @@ -1,26 +1,29 @@ package org.gciatto.kt.math actual val DOUBLE_MIN_VALUE_REPR: String - get() = "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + - "00000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363" + - "61635992379796564695445717730926656710355939796398774796010781878126300713190311404527845817167848982103" + - "68871863605699873072305000638740915356498438731247339727316961514003171538539807412623856559117102665855" + - "66867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478" + - "69014726780159355238611550134803526493472019379026810710749170333222684475333572083243193609238289345836" + - "80601060115061698097530783422773183292479049825247307763759272478746560847782037344696995336470179726777" + - "17585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565" + - "229087538682506419718265533447265625" + get() = + "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363" + + "61635992379796564695445717730926656710355939796398774796010781878126300713190311404527845817167848982103" + + "68871863605699873072305000638740915356498438731247339727316961514003171538539807412623856559117102665855" + + "66867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478" + + "69014726780159355238611550134803526493472019379026810710749170333222684475333572083243193609238289345836" + + "80601060115061698097530783422773183292479049825247307763759272478746560847782037344696995336470179726777" + + "17585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565" + + "229087538682506419718265533447265625" actual val DOUBLE_MAX_VALUE_REPR: String - get() = "17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817154" + - "04589535143824642343213268894641827684675467035375169860499105765512820762454900903893289440758685084551" + - "33942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368" + get() = + "17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817154" + + "04589535143824642343213268894641827684675467035375169860499105765512820762454900903893289440758685084551" + + "33942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368" actual val FLOAT_MAX_VALUE_REPR: String get() = "340282346638528859811704183484516925440" actual val FLOAT_MIN_VALUE_REPR: String - get() = "0.000000000000000000000000000000000000000000001401298464324817070923729583289916131280261941876515771757" + - "06828388979108268586060148663818836212158203125" + get() = + "0.000000000000000000000000000000000000000000001401298464324817070923729583289916131280261941876515771757" + + "06828388979108268586060148663818836212158203125" diff --git a/src/jvmTest/kotlin/org/gciatto/kt/math/JvmIntAlgos.kt b/src/jvmTest/kotlin/org/gciatto/kt/math/JvmIntAlgos.kt index 3a8a908..8a5617d 100644 --- a/src/jvmTest/kotlin/org/gciatto/kt/math/JvmIntAlgos.kt +++ b/src/jvmTest/kotlin/org/gciatto/kt/math/JvmIntAlgos.kt @@ -4,35 +4,39 @@ import java.math.BigInteger import kotlin.test.assertEquals object JvmIntAlgos : IntAlgos { - - private fun bigIntRange(min: Int, maxIncl: BigInteger): Sequence = + private fun bigIntRange( + min: Int, + maxIncl: BigInteger, + ): Sequence = generateSequence(BigInteger.valueOf(min.toLong())) { it + BigInteger.ONE }.takeWhile { it <= maxIncl } - override fun fibonacci(n: BigInteger): BigInteger = when { - n < BigInteger.ZERO -> throw IllegalArgumentException("Cannot compute the fibonacci($n)") - n <= BigInteger.ONE -> BigInteger.ONE - else -> { - var prev = BigInteger.ONE - var curr = BigInteger.ONE - for (i in bigIntRange(2, n)) { - val next = curr + prev - prev = curr - curr = next + override fun fibonacci(n: BigInteger): BigInteger = + when { + n < BigInteger.ZERO -> throw IllegalArgumentException("Cannot compute the fibonacci($n)") + n <= BigInteger.ONE -> BigInteger.ONE + else -> { + var prev = BigInteger.ONE + var curr = BigInteger.ONE + for (i in bigIntRange(2, n)) { + val next = curr + prev + prev = curr + curr = next + } + curr } - curr } - } - override fun factorial(n: BigInteger): BigInteger = when { - n < BigInteger.ZERO -> throw IllegalArgumentException("Cannot compute the factorial($n)") - else -> { - var curr = BigInteger.ONE - for (i in bigIntRange(2, n)) { - curr *= i + override fun factorial(n: BigInteger): BigInteger = + when { + n < BigInteger.ZERO -> throw IllegalArgumentException("Cannot compute the factorial($n)") + else -> { + var curr = BigInteger.ONE + for (i in bigIntRange(2, n)) { + curr *= i + } + curr } - curr } - } override fun fibonacciBasedBenchmark(max: BigInteger) { val sequence = bigIntRange(0, max).map(this::fibonacci).toList() diff --git a/src/jvmTest/kotlin/org/gciatto/kt/math/JvmIntBenchmark.kt b/src/jvmTest/kotlin/org/gciatto/kt/math/JvmIntBenchmark.kt index f2a6c54..7d5a0c4 100644 --- a/src/jvmTest/kotlin/org/gciatto/kt/math/JvmIntBenchmark.kt +++ b/src/jvmTest/kotlin/org/gciatto/kt/math/JvmIntBenchmark.kt @@ -1,8 +1,8 @@ package org.gciatto.kt.math +import java.math.BigInteger import kotlin.test.Test import kotlin.time.ExperimentalTime -import java.math.BigInteger class JvmIntBenchmark : AbstractIntBenchmark(JvmIntAlgos) { override fun bigInt(value: Int): BigInteger = BigInteger.valueOf(value.toLong()) diff --git a/src/jvmTest/kotlin/org/gciatto/kt/math/TestRoundingMode.kt b/src/jvmTest/kotlin/org/gciatto/kt/math/TestRoundingMode.kt index 2f64ba7..648306b 100644 --- a/src/jvmTest/kotlin/org/gciatto/kt/math/TestRoundingMode.kt +++ b/src/jvmTest/kotlin/org/gciatto/kt/math/TestRoundingMode.kt @@ -2,7 +2,6 @@ package org.gciatto.kt.math import kotlin.test.Test import kotlin.test.assertEquals - import java.math.RoundingMode as JavaRoundingMode class TestRoundingMode { @@ -20,12 +19,13 @@ class TestRoundingMode { } private val JavaRoundingMode.value: Int - get() = JavaRoundingMode::class.java.getDeclaredField("oldMode").let { - if (it.trySetAccessible()) { - it.getInt(this) - } else { - System.err.println("w: cannot get $this.oldValue") - this.ordinal + get() = + JavaRoundingMode::class.java.getDeclaredField("oldMode").let { + if (it.trySetAccessible()) { + it.getInt(this) + } else { + System.err.println("w: cannot get $this.oldValue") + this.ordinal + } } - } }