forked from kscience/kmath
Parser optimization
This commit is contained in:
parent
74d14970b9
commit
9184bd55de
@ -441,11 +441,11 @@ public fun UIntArray.toBigInt(sign: Byte): BigInt {
|
|||||||
return BigInt(sign, copyOf())
|
return BigInt(sign, copyOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
private val hexChToInt: MutableMap<Char, Int> = hashMapOf(
|
private val hexChToInt: MutableMap<Char, UInt> = hashMapOf(
|
||||||
'0' to 0, '1' to 1, '2' to 2, '3' to 3,
|
'0' to 0U, '1' to 1U, '2' to 2U, '3' to 3U,
|
||||||
'4' to 4, '5' to 5, '6' to 6, '7' to 7,
|
'4' to 4U, '5' to 5U, '6' to 6U, '7' to 7U,
|
||||||
'8' to 8, '9' to 9, 'A' to 10, 'B' to 11,
|
'8' to 8U, '9' to 9U, 'A' to 10U, 'B' to 11U,
|
||||||
'C' to 12, 'D' to 13, 'E' to 14, 'F' to 15
|
'C' to 12U, 'D' to 13U, 'E' to 14U, 'F' to 15U
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -454,41 +454,59 @@ private val hexChToInt: MutableMap<Char, Int> = hashMapOf(
|
|||||||
public fun String.parseBigInteger(): BigInt? {
|
public fun String.parseBigInteger(): BigInt? {
|
||||||
if (this.isEmpty()) return null
|
if (this.isEmpty()) return null
|
||||||
val sign: Int
|
val sign: Int
|
||||||
val sPositive: String
|
|
||||||
//TODO substring = O(n). Can be replaced by some drop that is O(1)
|
val positivePartIndex = when (this[0]) {
|
||||||
when {
|
'+' -> {
|
||||||
this[0] == '+' -> {
|
|
||||||
sign = +1
|
sign = +1
|
||||||
sPositive = this.substring(1)
|
1
|
||||||
}
|
}
|
||||||
this[0] == '-' -> {
|
'-' -> {
|
||||||
sign = -1
|
sign = -1
|
||||||
sPositive = this.substring(1)
|
1
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
sPositive = this
|
|
||||||
sign = +1
|
sign = +1
|
||||||
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var res = BigInt.ZERO
|
|
||||||
var digitValue = BigInt.ONE
|
|
||||||
val sPositiveUpper = sPositive.uppercase()
|
|
||||||
var isEmpty = true
|
var isEmpty = true
|
||||||
|
|
||||||
if (sPositiveUpper.startsWith("0X")) {
|
return if (this.startsWith("0X", startIndex = positivePartIndex, ignoreCase = true)) {
|
||||||
// hex representation
|
// hex representation
|
||||||
val sHex = sPositiveUpper.substring(2)
|
|
||||||
if (this.isEmpty()) return null
|
|
||||||
// TODO optimize O(n2) -> O(n)
|
|
||||||
|
|
||||||
for (ch in sHex.reversed()) {
|
val uInts = mutableListOf(0U)
|
||||||
if (ch == '_') continue
|
var offset = 0
|
||||||
res += digitValue * (hexChToInt[ch] ?: return null)
|
fun addDigit(value: UInt) {
|
||||||
isEmpty = false
|
uInts[uInts.lastIndex] += value shl offset
|
||||||
digitValue *= 16.toBigInt()
|
offset += 4
|
||||||
|
if (offset == 32) {
|
||||||
|
uInts.add(0U)
|
||||||
|
offset = 0
|
||||||
}
|
}
|
||||||
} else for (ch in sPositiveUpper.reversed()) {
|
}
|
||||||
|
|
||||||
|
for (index in lastIndex downTo positivePartIndex + 2) {
|
||||||
|
when (val ch = this[index]) {
|
||||||
|
'_' -> continue
|
||||||
|
in '0'..'9' -> addDigit((ch - '0').toUInt())
|
||||||
|
in 'A'..'F' -> addDigit((ch - 'A').toUInt() + 10U)
|
||||||
|
in 'a'..'f' -> addDigit((ch - 'a').toUInt() + 10U)
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
isEmpty = false
|
||||||
|
}
|
||||||
|
|
||||||
|
while (uInts.isNotEmpty() && uInts.last() == 0U)
|
||||||
|
uInts.removeLast()
|
||||||
|
|
||||||
|
if (isEmpty) null else BigInt(sign.toByte(), uInts.toUIntArray())
|
||||||
|
} else {
|
||||||
|
// hex representation
|
||||||
|
var res = BigInt.ZERO
|
||||||
|
var digitValue = BigInt.ONE
|
||||||
|
for (index in lastIndex downTo positivePartIndex) {
|
||||||
|
val ch = this[index]
|
||||||
// decimal representation
|
// decimal representation
|
||||||
if (ch == '_') continue
|
if (ch == '_') continue
|
||||||
if (ch !in '0'..'9') {
|
if (ch !in '0'..'9') {
|
||||||
@ -497,9 +515,11 @@ public fun String.parseBigInteger(): BigInt? {
|
|||||||
res += digitValue * (ch.code - '0'.code)
|
res += digitValue * (ch.code - '0'.code)
|
||||||
isEmpty = false
|
isEmpty = false
|
||||||
digitValue *= 10.toBigInt()
|
digitValue *= 10.toBigInt()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (isEmpty) null else res * sign
|
if (isEmpty) null else res * sign
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer<BigInt> =
|
public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer<BigInt> =
|
||||||
|
Loading…
Reference in New Issue
Block a user