-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Kotlin/Native implementation of BigDecimal and BigInteger #1200
base: kn-main
Are you sure you want to change the base?
Changes from 3 commits
66c7e83
ca1c1f1
1679172
5698dc3
5d492c3
16c85d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,33 +4,52 @@ | |
*/ | ||
package aws.smithy.kotlin.runtime.content | ||
|
||
public actual class BigDecimal actual constructor(public val value: String) : | ||
import java.math.BigDecimal as JvmBigDecimal | ||
|
||
public actual class BigDecimal private constructor(private val delegate: JvmBigDecimal) : | ||
Number(), | ||
Comparable<BigDecimal> { | ||
private val delegate = java.math.BigDecimal(value) | ||
|
||
public actual constructor(mantissa: BigInteger, exponent: Int) : this( | ||
java.math.BigDecimal( | ||
java.math.BigInteger(mantissa.toString()), | ||
exponent, | ||
).toPlainString(), | ||
) | ||
private companion object { | ||
/** | ||
* Returns a new or existing [BigDecimal] wrapper for the given delegate [value] | ||
* @param value The delegate value to wrap | ||
* @param left A candidate wrapper which may already contain [value] | ||
* @param right A candidate wrapper which may already contain [value] | ||
*/ | ||
fun coalesceOrCreate(value: JvmBigDecimal, left: BigDecimal, right: BigDecimal): BigDecimal = when (value) { | ||
left.delegate -> left | ||
right.delegate -> right | ||
else -> BigDecimal(value) | ||
} | ||
} | ||
|
||
public actual constructor(value: String) : this(JvmBigDecimal(value)) | ||
public actual constructor(mantissa: BigInteger, exponent: Int) : this(JvmBigDecimal(mantissa.delegate, exponent)) | ||
|
||
public actual fun toPlainString(): String = delegate.toPlainString() | ||
actual override fun toByte(): Byte = delegate.toByte() | ||
actual override fun toDouble(): Double = delegate.toDouble() | ||
actual override fun toFloat(): Float = delegate.toFloat() | ||
actual override fun toInt(): Int = delegate.toInt() | ||
actual override fun toLong(): Long = delegate.toLong() | ||
actual override fun toShort(): Short = delegate.toShort() | ||
public actual override fun toString(): String = delegate.toString() | ||
public actual override fun toByte(): Byte = delegate.toByte() | ||
public actual override fun toDouble(): Double = delegate.toDouble() | ||
public actual override fun toFloat(): Float = delegate.toFloat() | ||
public actual override fun toInt(): Int = delegate.toInt() | ||
public actual override fun toLong(): Long = delegate.toLong() | ||
public actual override fun toShort(): Short = delegate.toShort() | ||
|
||
actual override fun equals(other: Any?): Boolean = other is BigDecimal && delegate == other.delegate | ||
public actual override fun equals(other: Any?): Boolean = other is BigDecimal && delegate == other.delegate | ||
public actual override fun hashCode(): Int = 31 + delegate.hashCode() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Usually 31 is multiplied in these hashCode implementations, is this intentional addition? Is there any reason we can't just take the delegate's hash code? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I intentionally used addition instead of multiplication although either should work. I wanted to avoid using the unmodified hash code from the delegate because that would bin them the same if they were both added to a hashed container (e.g., |
||
|
||
public actual val mantissa: BigInteger | ||
get() = BigInteger(delegate.unscaledValue().toString()) | ||
get() = BigInteger(delegate.unscaledValue()) | ||
|
||
public actual val exponent: Int | ||
get() = delegate.scale() | ||
|
||
public actual operator fun plus(other: BigDecimal): BigDecimal = | ||
coalesceOrCreate(delegate + other.delegate, this, other) | ||
|
||
public actual operator fun minus(other: BigDecimal): BigDecimal = | ||
coalesceOrCreate(delegate - other.delegate, this, other) | ||
Comment on lines
+48
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice 👍 |
||
|
||
actual override fun compareTo(other: BigDecimal): Int = delegate.compareTo(other.delegate) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,25 +4,47 @@ | |
*/ | ||
package aws.smithy.kotlin.runtime.content | ||
|
||
public actual class BigInteger actual constructor(public val value: String) : | ||
import java.math.BigInteger as JvmBigInteger | ||
|
||
public actual class BigInteger internal constructor(internal val delegate: JvmBigInteger) : | ||
Number(), | ||
Comparable<BigInteger> { | ||
private val delegate = java.math.BigInteger(value) | ||
|
||
public actual constructor(bytes: ByteArray) : this(java.math.BigInteger(bytes).toString()) | ||
private companion object { | ||
/** | ||
* Returns a new or existing [BigInteger] wrapper for the given delegate [value] | ||
* @param value The delegate value to wrap | ||
* @param left A candidate wrapper which may already contain [value] | ||
* @param right A candidate wrapper which may already contain [value] | ||
*/ | ||
fun coalesceOrCreate(value: JvmBigInteger, left: BigInteger, right: BigInteger): BigInteger = when (value) { | ||
left.delegate -> left | ||
right.delegate -> right | ||
else -> BigInteger(value) | ||
} | ||
} | ||
|
||
public actual constructor(value: String) : this(JvmBigInteger(value)) | ||
public actual constructor(bytes: ByteArray) : this(JvmBigInteger(bytes)) | ||
|
||
public actual override fun toByte(): Byte = delegate.toByte() | ||
public actual override fun toLong(): Long = delegate.toLong() | ||
public actual override fun toShort(): Short = delegate.toShort() | ||
public actual override fun toInt(): Int = delegate.toInt() | ||
public actual override fun toFloat(): Float = delegate.toFloat() | ||
public actual override fun toDouble(): Double = delegate.toDouble() | ||
public actual override fun toString(): String = delegate.toString() | ||
public actual override fun hashCode(): Int = delegate.hashCode() | ||
public actual override fun toString(): String = toString(10) | ||
public actual fun toString(radix: Int): String = delegate.toString(radix) | ||
|
||
public actual override fun hashCode(): Int = 17 + delegate.hashCode() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same question about adding 17, can we just take the delegate's hash code? |
||
public actual override fun equals(other: Any?): Boolean = other is BigInteger && delegate == other.delegate | ||
|
||
public actual operator fun plus(other: BigInteger): BigInteger = BigInteger((delegate + other.delegate).toString()) | ||
public actual operator fun minus(other: BigInteger): BigInteger = BigInteger((delegate - other.delegate).toString()) | ||
public actual operator fun plus(other: BigInteger): BigInteger = | ||
coalesceOrCreate(delegate + other.delegate, this, other) | ||
|
||
public actual operator fun minus(other: BigInteger): BigInteger = | ||
coalesceOrCreate(delegate - other.delegate, this, other) | ||
|
||
public actual override operator fun compareTo(other: BigInteger): Int = delegate.compareTo(other.delegate) | ||
public actual fun toByteArray(): ByteArray = delegate.toByteArray() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Were you able to get better stack traces with this enabled? I remember you said it didn't help, so I'd rather leave it off if it's not working as expected
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, will remove. I eventually discovered that full stack traces are available in the build artifacts (e.g., build/reports/tests/linuxX64Test/index.html) just not in the console output.