From 4daa4f6b04ffa61dcf28c95f08b44c1f2c866b24 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Fri, 20 Aug 2021 16:43:26 +0200 Subject: [PATCH] Fix long narrowing loosing sign, remove signum from bigdecimal toDouble because it was now being applied twice. Add some tests, update changelog. --- CHANGELOG.md | 3 ++- .../kotlin/bignum/decimal/BigDecimal.kt | 2 +- .../kotlin/bignum/integer/BigInteger.kt | 2 +- .../kotlin/bignum/integer/BigIntegerTest.kt | 18 ++++++++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4b570d5..da2e7a3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,10 @@ - Added kotlinx serialization support library - Enabled gradle dependencies verification (bootstrapped) - Fix for losing decimal mode when using unary minus (#184) +- Fix for losing sign when narrowing to long from big integer (#186) -##### 0.3.1 +##### 0.3.1 - 10.5.2021 - Fix for #176, a case of unclear API. Methods `roundToDigitPositionAfterDecimalPoint` and `roundToDigitPosition` would set decimal precision to the number of digits present in the result after the rounding was completed. Now they only set decimal precision if it's explicitly set, otherwise it stays unlimited. - Bump to 1.5.0 diff --git a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/decimal/BigDecimal.kt b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/decimal/BigDecimal.kt index 773582db..f4283f50 100644 --- a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/decimal/BigDecimal.kt +++ b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/decimal/BigDecimal.kt @@ -1877,7 +1877,7 @@ class BigDecimal private constructor( val divExponent = precision - 1 - exponent val l = this.significand.longValue(exactRequired) return if (l.toDouble().toLong() == l && divExponent >= 0 && divExponent < double10pow.size) { - (l / double10pow[divExponent.toInt()]) * signum() + (l / double10pow[divExponent.toInt()]) } else { toString().toDouble() } diff --git a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/BigInteger.kt b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/BigInteger.kt index 4e416b66..90233424 100644 --- a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/BigInteger.kt +++ b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/BigInteger.kt @@ -764,7 +764,7 @@ class BigInteger internal constructor(wordArray: WordArray, requestedSign: Sign) val firstBit = magnitude[1] shl 63 (magnitude[0].toLong() or firstBit.toLong()) * signum() } else { - return magnitude[0].toLong() + return magnitude[0].toLong() * signum() } } diff --git a/bignum/src/commonTest/kotlin/com/ionspin/kotlin/bignum/integer/BigIntegerTest.kt b/bignum/src/commonTest/kotlin/com/ionspin/kotlin/bignum/integer/BigIntegerTest.kt index ca5904eb..f40179dd 100644 --- a/bignum/src/commonTest/kotlin/com/ionspin/kotlin/bignum/integer/BigIntegerTest.kt +++ b/bignum/src/commonTest/kotlin/com/ionspin/kotlin/bignum/integer/BigIntegerTest.kt @@ -252,20 +252,38 @@ BigIntegerTest { val a = 2.toBigInteger() a.intValue(exactRequired = true) == 2 } + assertTrue { + val a = (-2).toBigInteger() + a.intValue(exactRequired = true) == -2 + } assertTrue { val a = 2.toBigInteger() val short: Short = 2 a.shortValue(exactRequired = true) == short } + assertTrue { + val a = (-2).toBigInteger() + val short: Short = -2 + a.shortValue(exactRequired = true) == short + } assertTrue { val a = 2.toBigInteger() val byte: Byte = 2 a.byteValue(exactRequired = true) == byte } + assertTrue { + val a = (-2).toBigInteger() + val byte: Byte = -2 + a.byteValue(exactRequired = true) == byte + } assertTrue { val a = 2.toBigInteger() a.longValue(exactRequired = true) == 2L } + assertTrue { + val a = (-2).toBigInteger() + a.longValue(exactRequired = true) == -2L + } assertTrue { val a = 2.toBigInteger() a.uintValue(exactRequired = true) == 2U