Karatsuba added, 2 bugs are fixed #328
@ -10,10 +10,7 @@ import kotlinx.benchmark.Blackhole
|
|||||||
import org.openjdk.jmh.annotations.Benchmark
|
import org.openjdk.jmh.annotations.Benchmark
|
||||||
import org.openjdk.jmh.annotations.Scope
|
import org.openjdk.jmh.annotations.Scope
|
||||||
import org.openjdk.jmh.annotations.State
|
import org.openjdk.jmh.annotations.State
|
||||||
import space.kscience.kmath.operations.BigInt
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.operations.BigIntField
|
|
||||||
import space.kscience.kmath.operations.JBigIntegerField
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
|
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
@ -64,4 +61,24 @@ internal class BigIntBenchmark {
|
|||||||
fun jvmPower(blackhole: Blackhole) = JBigIntegerField {
|
fun jvmPower(blackhole: Blackhole) = JBigIntegerField {
|
||||||
blackhole.consume(jvmNumber.pow(bigExponent))
|
blackhole.consume(jvmNumber.pow(bigExponent))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun kmParsing16(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume("0x7f57ed8b89c29a3b9a85c7a5b84ca3929c7b7488593".parseBigInteger())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun kmParsing10(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume("236656783929183747565738292847574838922010".parseBigInteger())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun jvmParsing10(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume("236656783929183747565738292847574838922010".toBigInteger(10))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun jvmParsing16(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume("7f57ed8b89c29a3b9a85c7a5b84ca3929c7b7488593".toBigInteger(16))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -441,13 +441,6 @@ public fun UIntArray.toBigInt(sign: Byte): BigInt {
|
|||||||
return BigInt(sign, copyOf())
|
return BigInt(sign, copyOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
private val hexChToInt: MutableMap<Char, UInt> = hashMapOf(
|
|
||||||
'0' to 0U, '1' to 1U, '2' to 2U, '3' to 3U,
|
|
||||||
'4' to 4U, '5' to 5U, '6' to 6U, '7' to 7U,
|
|
||||||
'8' to 8U, '9' to 9U, 'A' to 10U, 'B' to 11U,
|
|
||||||
'C' to 12U, 'D' to 13U, 'E' to 14U, 'F' to 15U
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns null if a valid number can not be read from a string
|
* Returns null if a valid number can not be read from a string
|
||||||
*/
|
*/
|
||||||
@ -475,7 +468,7 @@ public fun String.parseBigInteger(): BigInt? {
|
|||||||
return if (this.startsWith("0X", startIndex = positivePartIndex, ignoreCase = true)) {
|
return if (this.startsWith("0X", startIndex = positivePartIndex, ignoreCase = true)) {
|
||||||
// hex representation
|
// hex representation
|
||||||
|
|
||||||
val uInts = mutableListOf(0U)
|
val uInts = ArrayList<UInt>(length).apply { add(0U) }
|
||||||
var offset = 0
|
var offset = 0
|
||||||
fun addDigit(value: UInt) {
|
fun addDigit(value: UInt) {
|
||||||
uInts[uInts.lastIndex] += value shl offset
|
uInts[uInts.lastIndex] += value shl offset
|
||||||
@ -502,22 +495,34 @@ public fun String.parseBigInteger(): BigInt? {
|
|||||||
|
|
||||||
if (isEmpty) null else BigInt(sign.toByte(), uInts.toUIntArray())
|
if (isEmpty) null else BigInt(sign.toByte(), uInts.toUIntArray())
|
||||||
} else {
|
} else {
|
||||||
// hex representation
|
// decimal representation
|
||||||
var res = BigInt.ZERO
|
|
||||||
var digitValue = BigInt.ONE
|
|
||||||
for (index in lastIndex downTo positivePartIndex) {
|
|
||||||
val ch = this[index]
|
|
||||||
// decimal representation
|
|
||||||
if (ch == '_') continue
|
|
||||||
if (ch !in '0'..'9') {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
res += digitValue * (ch.code - '0'.code)
|
|
||||||
isEmpty = false
|
|
||||||
digitValue *= 10.toBigInt()
|
|
||||||
|
|
||||||
|
val positivePart = buildList(length) {
|
||||||
|
for (index in positivePartIndex until length)
|
||||||
|
when (val a = this@parseBigInteger[index]) {
|
||||||
|
'_' -> continue
|
||||||
|
in '0'..'9' -> add(a)
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val offset = positivePart.size % 9
|
||||||
|
isEmpty = offset == 0
|
||||||
|
|
||||||
|
fun parseUInt(fromIndex: Int, toIndex: Int): UInt? {
|
||||||
|
var res = 0U
|
||||||
|
for (i in fromIndex until toIndex) {
|
||||||
|
res = res * 10U + (positivePart[i].digitToIntOrNull()?.toUInt() ?: return null)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = parseUInt(0, offset)?.toBigInt() ?: return null
|
||||||
|
|
||||||
|
for (index in offset..positivePart.lastIndex step 9) {
|
||||||
|
isEmpty = false
|
||||||
|
res = res * 1_000_000_000U + (parseUInt(index, index + 9) ?: return null).toBigInt()
|
||||||
|
}
|
||||||
if (isEmpty) null else res * sign
|
if (isEmpty) null else res * sign
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import kotlin.test.assertNull
|
|||||||
class BigIntConversionsTest {
|
class BigIntConversionsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun emptyString() {
|
fun testEmptyString() {
|
||||||
assertNull("".parseBigInteger())
|
assertNull("".parseBigInteger())
|
||||||
assertNull("+".parseBigInteger())
|
assertNull("+".parseBigInteger())
|
||||||
assertNull("-".parseBigInteger())
|
assertNull("-".parseBigInteger())
|
||||||
@ -38,6 +38,12 @@ class BigIntConversionsTest {
|
|||||||
assertEquals("0x10", x.toString())
|
assertEquals("0x10", x.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testUnderscores() {
|
||||||
|
assertEquals("0x10", "0x_1_0_".parseBigInteger().toString())
|
||||||
|
assertEquals("0xa", "_1_0_".parseBigInteger().toString())
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testToString0x17ffffffd() {
|
fun testToString0x17ffffffd() {
|
||||||
val x = 0x17ffffffdL.toBigInt()
|
val x = 0x17ffffffdL.toBigInt()
|
||||||
|
Loading…
Reference in New Issue
Block a user