diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index c7079902b..00b9f9fc2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -452,6 +452,7 @@ private val hexChToInt: MutableMap = hashMapOf( * Returns null if a valid number can not be read from a string */ public fun String.parseBigInteger(): BigInt? { + if (this.isEmpty()) return null val sign: Int val sPositive: String //TODO substring = O(n). Can be replaced by some drop that is O(1) @@ -473,15 +474,18 @@ public fun String.parseBigInteger(): BigInt? { var res = BigInt.ZERO var digitValue = BigInt.ONE val sPositiveUpper = sPositive.uppercase() + var isEmpty = true if (sPositiveUpper.startsWith("0X")) { // hex representation val sHex = sPositiveUpper.substring(2) + if (this.isEmpty()) return null // TODO optimize O(n2) -> O(n) for (ch in sHex.reversed()) { if (ch == '_') continue res += digitValue * (hexChToInt[ch] ?: return null) + isEmpty = false digitValue *= 16.toBigInt() } } else for (ch in sPositiveUpper.reversed()) { @@ -491,10 +495,11 @@ public fun String.parseBigInteger(): BigInt? { return null } res += digitValue * (ch.code - '0'.code) + isEmpty = false digitValue *= 10.toBigInt() } - return res * sign + return if (isEmpty) null else res * sign } public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer = diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt index a2832e531..1feaae808 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt @@ -7,9 +7,31 @@ package space.kscience.kmath.operations import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertNull @kotlin.ExperimentalUnsignedTypes class BigIntConversionsTest { + + @Test + fun emptyString() { + assertNull("".parseBigInteger()) + assertNull("+".parseBigInteger()) + assertNull("-".parseBigInteger()) + + assertNull("0x".parseBigInteger()) + assertNull("+0x".parseBigInteger()) + assertNull("-0x".parseBigInteger()) + + + assertNull("_".parseBigInteger()) + assertNull("+_".parseBigInteger()) + assertNull("-_".parseBigInteger()) + + assertNull("0x_".parseBigInteger()) + assertNull("+0x_".parseBigInteger()) + assertNull("-0x_".parseBigInteger()) + } + @Test fun testToString0x10() { val x = 0x10.toBigInt()