Skip to content

Commit db16a74

Browse files
feat(core): implement divRem
This is an optimisation on JVM & native.
1 parent 150efdc commit db16a74

9 files changed

Lines changed: 70 additions & 0 deletions

File tree

  • kbigint/src
    • androidMain/kotlin/io/github/observeroftime/kbigint
    • androidUnitTest/kotlin/io/github/observeroftime/kbigint
    • commonMain/kotlin/io/github/observeroftime/kbigint
    • jsMain/kotlin/io/github/observeroftime/kbigint
    • jsTest/kotlin/io/github/observeroftime/kbigint
    • jvmMain/kotlin/io/github/observeroftime/kbigint
    • jvmTest/kotlin/io/github/observeroftime/kbigint
    • nativeMain/kotlin/io/github/observeroftime/kbigint
    • nativeTest/kotlin/io/github/observeroftime/kbigint

kbigint/src/androidMain/kotlin/io/github/observeroftime/kbigint/KBigInt.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,18 @@ actual class KBigInt private constructor(private var value: BigInteger) : Compar
9898
/** Perform a bitwise `XOR` operation. */
9999
actual infix fun xor(other: KBigInt) = KBigInt(value xor other.value)
100100

101+
/**
102+
* Divide two [KBigInt] values and include the remainder.
103+
*
104+
* @since 0.5.0
105+
* @return a `(quotient, remainder)` pair
106+
*/
107+
@JvmName("divideAndRemainder")
108+
actual fun divRem(other: KBigInt): Pair<KBigInt, KBigInt> {
109+
val (quotient, remainder) = value.divideAndRemainder(other.value)
110+
return Pair(KBigInt(quotient), KBigInt(remainder))
111+
}
112+
101113
/**
102114
* Find the (absolute) GCD of two [KBigInt] values.
103115
*

kbigint/src/androidUnitTest/kotlin/io/github/observeroftime/kbigint/KBigIntTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ actual class KBigIntTest {
4242
assertEquals(KBigInt("19807040628566084398385987584"), string * long)
4343
assertEquals(KBigInt(4294967296L), string / long)
4444
assertEquals(KBigInt(0), string % long)
45+
46+
assertEquals(Pair(KBigInt(4294967296L), KBigInt(0)), string.divRem(long))
4547
}
4648

4749
@Test

kbigint/src/commonMain/kotlin/io/github/observeroftime/kbigint/KBigInt.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ expect class KBigInt : Comparable<KBigInt> {
7575
/** Perform a bitwise `XOR` operation. */
7676
infix fun xor(other: KBigInt): KBigInt
7777

78+
/**
79+
* Divide two [KBigInt] values and include the remainder.
80+
*
81+
* @since 0.5.0
82+
* @return a `(quotient, remainder)` pair
83+
*/
84+
fun divRem(other: KBigInt): Pair<KBigInt, KBigInt>
85+
7886
/**
7987
* Find the (absolute) GCD of two [KBigInt] values.
8088
*

kbigint/src/jsMain/kotlin/io/github/observeroftime/kbigint/KBigInt.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,22 @@ actual class KBigInt private constructor(@JsExternalArgument private var value:
135135
return KBigInt(js("a ^ b").unsafeCast<BigInt>())
136136
}
137137

138+
/**
139+
* Divide two [KBigInt] values and include the remainder.
140+
*
141+
* @since 0.5.0
142+
* @return a `(quotient, remainder)` pair
143+
*/
144+
@JsName("_divideAndRemainder")
145+
@Suppress("NON_EXPORTABLE_TYPE")
146+
actual fun divRem(other: KBigInt): Pair<KBigInt, KBigInt> {
147+
val a = this.value
148+
val b = other.value
149+
val quotient = js("a / b").unsafeCast<BigInt>()
150+
val remainder = js("a % b").unsafeCast<BigInt>()
151+
return Pair(KBigInt(quotient), KBigInt(remainder))
152+
}
153+
138154
/**
139155
* Find the (absolute) GCD of two [KBigInt] values.
140156
*

kbigint/src/jsTest/kotlin/io/github/observeroftime/kbigint/KBigIntTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ actual class KBigIntTest {
4343
assertEquals(KBigInt("19807040628566084398385987584"), string * long)
4444
assertEquals(KBigInt(4294967296L), string / long)
4545
assertEquals(KBigInt(0), string % long)
46+
47+
assertEquals(Pair(KBigInt(4294967296L), KBigInt(0)), string.divRem(long))
4648
}
4749

4850
@Test

kbigint/src/jvmMain/kotlin/io/github/observeroftime/kbigint/KBigInt.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,18 @@ actual class KBigInt private constructor(private var value: BigInteger) : Compar
9696
/** Perform a bitwise `XOR` operation. */
9797
actual infix fun xor(other: KBigInt) = KBigInt(value xor other.value)
9898

99+
/**
100+
* Divide two [KBigInt] values and include the remainder.
101+
*
102+
* @since 0.5.0
103+
* @return a `(quotient, remainder)` pair
104+
*/
105+
@JvmName("divideAndRemainder")
106+
actual fun divRem(other: KBigInt): Pair<KBigInt, KBigInt> {
107+
val (quotient, remainder) = value.divideAndRemainder(other.value)
108+
return Pair(KBigInt(quotient), KBigInt(remainder))
109+
}
110+
99111
/**
100112
* Find the (absolute) GCD of two [KBigInt] values.
101113
*

kbigint/src/jvmTest/kotlin/io/github/observeroftime/kbigint/KBigIntTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ actual class KBigIntTest {
4343
assertEquals(KBigInt("19807040628566084398385987584"), string * long)
4444
assertEquals(KBigInt(4294967296L), string / long)
4545
assertEquals(KBigInt(0), string % long)
46+
47+
assertEquals(Pair(KBigInt(4294967296L), KBigInt(0)), string.divRem(long))
4648
}
4749

4850
@Test

kbigint/src/nativeMain/kotlin/io/github/observeroftime/kbigint/KBigInt.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,20 @@ actual class KBigInt private constructor(private var value: mp_int) : Comparable
297297
KBigInt(result.ptr)
298298
}
299299

300+
/**
301+
* Divide two [KBigInt] values and include the remainder.
302+
*
303+
* @since 0.5.0
304+
* @return a `(quotient, remainder)` pair
305+
*/
306+
@ObjCName("divideAndRemainder")
307+
actual fun divRem(other: KBigInt) = memScoped {
308+
val quotient = alloc<mp_int>()
309+
val remainder = alloc<mp_int>()
310+
mp_div(value.ptr, other.value.ptr, quotient.ptr, remainder.ptr).check()
311+
Pair(KBigInt(quotient.ptr), KBigInt(remainder.ptr))
312+
}
313+
300314
/**
301315
* Find the (absolute) GCM of two [KBigInt] values.
302316
*

kbigint/src/nativeTest/kotlin/io/github/observeroftime/kbigint/KBigIntTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ actual class KBigIntTest {
5050
assertEquals(KBigInt("19807040628566084398385987584"), string * long)
5151
assertEquals(KBigInt(4294967296L), string / long)
5252
assertEquals(KBigInt(0), string % long)
53+
54+
assertEquals(Pair(KBigInt(4294967296L), KBigInt(0)), string.divRem(long))
5355
}
5456

5557
@Test

0 commit comments

Comments
 (0)