Skip to content

Commit 022ee8e

Browse files
feat(core): implement gcd & lcm
1 parent b8e1c56 commit 022ee8e

12 files changed

Lines changed: 109 additions & 0 deletions

File tree

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ actual class KBigInt private constructor(private var value: BigInteger) : Compar
6767

6868
actual infix fun xor(other: KBigInt) = KBigInt(value xor other.value)
6969

70+
actual fun gcd(other: KBigInt) = KBigInt(value.gcd(other.value))
71+
72+
actual fun lcm(other: KBigInt): KBigInt {
73+
val a = value.abs()
74+
val b = other.value.abs()
75+
return KBigInt(a * b / a.gcd(b))
76+
}
77+
7078
@JvmName("shiftLeft")
7179
actual infix fun shl(n: Int) = KBigInt(value shl n)
7280

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ actual class KBigIntTest {
7575
assertEquals(KBigInt(2147483649L), -long.inv())
7676
}
7777

78+
@Test
79+
actual fun testGcdLcm() {
80+
val a = KBigInt(-4)
81+
val b = KBigInt(10)
82+
83+
assertEquals(KBigInt(2), a.gcd(b))
84+
assertEquals(KBigInt(20), a.lcm(b))
85+
}
86+
7887
@Test
7988
actual fun testPow() {
8089
assertEquals(KBigInt("4611686018427387904"), long pow 2)

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ expect class KBigInt : Comparable<KBigInt> {
6262
/** Perform a bitwise `XOR` operation. */
6363
infix fun xor(other: KBigInt): KBigInt
6464

65+
/** Find the (absolute) Greatest Common Divisor of two values. */
66+
fun gcd(other: KBigInt): KBigInt
67+
68+
/** Find the (absolute) Least Common Multiplier of two values. */
69+
fun lcm(other: KBigInt): KBigInt
70+
6571
/** Shift the value to the left by [n]. */
6672
infix fun shl(n: Int): KBigInt
6773

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ expect class KBigIntTest {
1212
fun testBitOps()
1313
fun testShifts()
1414
fun testInvert()
15+
fun testGcdLcm()
1516
fun testPow()
1617
fun testSqrt()
1718
fun testAbs()

kbigint/src/javascript/kbigint-utils.mjs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@ export function cmp(a, b) {
6969
return a === b ? 0 : a < b ? -1 : 1;
7070
}
7171

72+
/**
73+
* Find the Greatest Common Divisor
74+
*
75+
* @param {bigint} a
76+
* @param {bigint} b
77+
* @returns {bigint}
78+
*/
79+
export function gcd(a, b) {
80+
if (b === 0n) return a;
81+
return gcd(b, a % b);
82+
}
83+
7284
/**
7385
* Raise the value to the `n`-th power.
7486
*

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ actual class KBigInt private constructor(@JsExternalArgument private var value:
9797
return KBigInt(js("a ^ b").unsafeCast<BigInt>())
9898
}
9999

100+
actual fun gcd(other: KBigInt): KBigInt {
101+
val gcd = KBigIntUtils.gcd(value, other.value)
102+
return KBigInt(KBigIntUtils.abs(gcd))
103+
}
104+
105+
actual fun lcm(other: KBigInt): KBigInt {
106+
val a = this.value
107+
val b = other.value
108+
val c = KBigIntUtils.gcd(a, b)
109+
val lcm = js("a * b / c").unsafeCast<BigInt>()
110+
return KBigInt(KBigIntUtils.abs(lcm))
111+
}
112+
100113
@JsName("shiftLeft")
101114
actual infix fun shl(n: Int): KBigInt {
102115
val a = this.value

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ internal external object KBigIntUtils {
1515
fun bitLength(value: BigInt): Int
1616
fun bitCount(value: BigInt): Int
1717
fun cmp(a: BigInt, b: BigInt): Int
18+
fun gcd(a: BigInt, b: BigInt): BigInt
1819
fun pow(value: BigInt, n: Int): BigInt
1920
fun toByteArray(value: BigInt): ByteArray
2021
fun fromByteArray(bytes: ByteArray): BigInt

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ actual class KBigIntTest {
7575
assertEquals(KBigInt(2147483649L), -long.inv())
7676
}
7777

78+
@Test
79+
actual fun testGcdLcm() {
80+
val a = KBigInt(-4)
81+
val b = KBigInt(10)
82+
83+
assertEquals(KBigInt(2), a.gcd(b))
84+
assertEquals(KBigInt(20), a.lcm(b))
85+
}
86+
7887
@Test
7988
actual fun testPow() {
8089
assertEquals(KBigInt("4611686018427387904"), long pow 2)

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ actual class KBigInt private constructor(private var value: BigInteger) : Compar
6565

6666
actual infix fun xor(other: KBigInt) = KBigInt(value xor other.value)
6767

68+
actual fun gcd(other: KBigInt) = KBigInt(value.gcd(other.value))
69+
70+
actual fun lcm(other: KBigInt): KBigInt {
71+
val a = value.abs()
72+
val b = other.value.abs()
73+
return KBigInt(a * b / a.gcd(b))
74+
}
75+
6876
@JvmName("shiftLeft")
6977
actual infix fun shl(n: Int) = KBigInt(value shl n)
7078

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ actual class KBigIntTest {
7575
assertEquals(KBigInt(2147483649L), -long.inv())
7676
}
7777

78+
@Test
79+
actual fun testGcdLcm() {
80+
val a = KBigInt(-4)
81+
val b = KBigInt(10)
82+
83+
assertEquals(KBigInt(2), a.gcd(b))
84+
assertEquals(KBigInt(20), a.lcm(b))
85+
}
86+
7887
@Test
7988
actual fun testPow() {
8089
assertEquals(KBigInt("4611686018427387904"), long pow 2)

0 commit comments

Comments
 (0)