Open hgourvest opened 2 months ago
I've run extensive tests on these functions, and it's reliable.
inline fun fromBigInteger(value: BigInteger, block: (a:Long, b:Long) -> Unit) {
val words = value.getBackingArrayCopy().toLongArray()
val v0: Long = words[0]
val v1: Long = if (words.size > 1) words[1] else 0L
when (value.getSign()) {
Sign.POSITIVE -> {
if (v1 == 0L) {
block(v0, 0L)
} else {
if (v1 % 2 == 0L) {
block(v0, v1 / 2)
} else {
block(Long.MIN_VALUE + v0, (v1 - 1) / 2)
}
}
}
Sign.NEGATIVE -> {
if (v1 == 0L) {
block(-v0, -1L)
} else {
if (v0 == 0L) {
if (v1 % 2 == 0L)
block(0L, -(v1 / 2))
else
block(Long.MIN_VALUE, -(v1 + 1) / 2)
} else {
if (v1 % 2 == 0L)
block(-v0, -(v1 / 2) - 1)
else
block(Long.MAX_VALUE - v0 + 1, -(v1 + 1) / 2)
}
}
}
Sign.ZERO -> ZERO
}
}
fun toBigInteger(a: Long, b: Long): BigInteger {
val sign = when {
b == 0L -> if (a == 0L) Sign.ZERO else Sign.POSITIVE
b > 0L -> Sign.POSITIVE
else -> Sign.NEGATIVE
}
return when (sign) {
Sign.POSITIVE ->
createFromWordArray((if (a < 0)
longArrayOf(a - Long.MIN_VALUE, b * 2 + 1)
else if (b == 0L)
longArrayOf(a)
else
longArrayOf(a, b * 2)).toULongArray(), sign)
Sign.NEGATIVE ->
createFromWordArray((when {
a == 0L -> longArrayOf(0L, -b * 2)
a == Long.MIN_VALUE -> longArrayOf(0L, (-b - 1) * 2 + 1)
a < 0L -> {
val v2 = (-b - 1)
if (v2 == 0L)
longArrayOf(-a)
else
longArrayOf(-a, v2 * 2)
}
else ->
longArrayOf(Long.MAX_VALUE - a + 1, (-b - 1) * 2 + 1)
}).toULongArray(), sign)
Sign.ZERO -> BigInteger.ZERO
}
}
Hi @hgourvest ,
I'll be traveling next two weeks so I probably won't have time to tackle this until I get back, but I'm sure we can figure something out, I feel like both options are possible, it's just deciding which approach is better.
Thanks, nothing urge.
The "inline" function saves an Object because of the Lambda function, but does not allow access to the class's private elements. So if you integrate this function in "inline" mode, you'll still need to make the "magnitude" variable public.
I just released the FirebirdClient library, feel free to get what you need. https://github.com/hgourvest/Firebird-Client-KMP/blob/main/library-ext/src/commonMain/kotlin/com/progdigy/fbclient/ext/BigInteger.kt
Thanks and congrats on the release!
Is your feature request related to a problem? Please describe. I need to convert a biginteger value to another format to be stored in a database that stores a 128 integer in two 64-bit integers. I've written two conversion functions, but as this code will be run intensively, I don't like having to create unnecessary objects using the "getBackingArrayCopy" function.
Describe the solution you'd like I would like to have direct access to the "magnitude" value.
Describe alternatives you've considered If you think that these conversion functions can be integrated into your library, I can also provide you with the conversion functions. The database is called Firebird SQL and uses "libtommath" to manipulate 128bit signed integers without needing to manage the sign separately.