From 3b52eb7ac183fc8c14efb16c4c13df0870691e61 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 12 Sep 2020 18:22:59 +0700 Subject: [PATCH] Implement bignum module and write basic benchmark --- examples/build.gradle.kts | 2 + .../ast/ExpressionsInterpretersBenchmark.kt | 3 +- .../kmath/bignum/BigIntegerBenchmark.kt | 61 +++++++++++++++++++ kmath-bignum/build.gradle.kts | 10 +++ .../scientifik/kmath/bignum/BigIntegerRing.kt | 23 +++++++ settings.gradle.kts | 1 + 6 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 examples/src/main/kotlin/scientifik/kmath/bignum/BigIntegerBenchmark.kt create mode 100644 kmath-bignum/build.gradle.kts create mode 100644 kmath-bignum/src/commonMain/kotlin/scientifik/kmath/bignum/BigIntegerRing.kt diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index f5a4d5831..3f3c06764 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -32,6 +32,8 @@ dependencies { implementation(project(":kmath-koma")) implementation(project(":kmath-viktor")) implementation(project(":kmath-dimensions")) + implementation(project(":kmath-bignum")) + implementation(project(":kmath-memory")) implementation("com.kyonifer:koma-core-ejml:0.12") implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.2.0-npm-dev-6") implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-8") diff --git a/examples/src/main/kotlin/scientifik/kmath/ast/ExpressionsInterpretersBenchmark.kt b/examples/src/main/kotlin/scientifik/kmath/ast/ExpressionsInterpretersBenchmark.kt index 17a70a4aa..d941fb2c7 100644 --- a/examples/src/main/kotlin/scientifik/kmath/ast/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/main/kotlin/scientifik/kmath/ast/ExpressionsInterpretersBenchmark.kt @@ -9,8 +9,9 @@ import scientifik.kmath.operations.RealField import kotlin.random.Random import kotlin.system.measureTimeMillis -class ExpressionsInterpretersBenchmark { +private class ExpressionsInterpretersBenchmark { private val algebra: Field = RealField + fun functionalExpression() { val expr = algebra.expressionInField { variable("x") * const(2.0) + const(2.0) / variable("x") - const(16.0) diff --git a/examples/src/main/kotlin/scientifik/kmath/bignum/BigIntegerBenchmark.kt b/examples/src/main/kotlin/scientifik/kmath/bignum/BigIntegerBenchmark.kt new file mode 100644 index 000000000..069fb628e --- /dev/null +++ b/examples/src/main/kotlin/scientifik/kmath/bignum/BigIntegerBenchmark.kt @@ -0,0 +1,61 @@ +package scientifik.kmath.bignum + +import com.ionspin.kotlin.bignum.integer.BigInteger +import scientifik.kmath.operations.BigIntField +import scientifik.kmath.operations.invoke +import kotlin.concurrent.thread +import kotlin.random.Random +import kotlin.system.measureTimeMillis + +private class BigIntegerBenchmark { + fun java() { + invokeAndSum { l, l2 -> (l.toBigInteger() * l2.toBigInteger()).toLong() } + } + + fun bignum() { + invokeAndSum { l, l2 -> (BigInteger.fromLong(l) * BigInteger.fromLong(l2)).longValue() } + } + + fun bigint() { + invokeAndSum { l, l2 -> BigIntField { number(l) * number(l2) }.toString().toLong() } + } + + fun long() { + invokeAndSum { l, l2 -> l * l2 } + } + + private fun invokeAndSum(op: (Long, Long) -> Long) { + val random = Random(0) + var sum = 0.0 + + repeat(1000000) { + sum += op(random.nextInt().toLong(), random.nextInt().toLong()) + } + + println(sum) + } +} + +fun main() { + val benchmark = BigIntegerBenchmark() + + thread { + val java = measureTimeMillis(benchmark::java) + println("java=$java") + } + + thread { + val bignum = measureTimeMillis(benchmark::bignum) + println("bignum=$bignum") + } + + thread { + val bigint = measureTimeMillis(benchmark::bigint) + println("bigint=$bigint") + } + + thread { + val long = measureTimeMillis(benchmark::long) + println("long=$long") + } +} diff --git a/kmath-bignum/build.gradle.kts b/kmath-bignum/build.gradle.kts new file mode 100644 index 000000000..cb23be68b --- /dev/null +++ b/kmath-bignum/build.gradle.kts @@ -0,0 +1,10 @@ +plugins { id("scientifik.mpp") } + +kotlin.sourceSets { + commonMain { + dependencies { + api("com.ionspin.kotlin:bignum:0.2.0") + api(project(":kmath-core")) + } + } +} diff --git a/kmath-bignum/src/commonMain/kotlin/scientifik/kmath/bignum/BigIntegerRing.kt b/kmath-bignum/src/commonMain/kotlin/scientifik/kmath/bignum/BigIntegerRing.kt new file mode 100644 index 000000000..f32ed61eb --- /dev/null +++ b/kmath-bignum/src/commonMain/kotlin/scientifik/kmath/bignum/BigIntegerRing.kt @@ -0,0 +1,23 @@ +package scientifik.kmath.bignum + +import com.ionspin.kotlin.bignum.integer.BigInteger +import scientifik.kmath.operations.Ring + +class BigIntegerRing : Ring { + override val zero: BigInteger + get() = BigInteger.ZERO + + override val one: BigInteger + get() = BigInteger.ONE + + override fun number(value: Number): BigInteger = BigInteger.fromLong(value.toLong()) + override fun add(a: BigInteger, b: BigInteger): BigInteger = a + b + override fun multiply(a: BigInteger, k: Number): BigInteger = a * (number(k)) + override fun multiply(a: BigInteger, b: BigInteger): BigInteger = a * b + override fun BigInteger.unaryMinus(): BigInteger = negate() + override fun BigInteger.minus(b: BigInteger): BigInteger = minus(b) + override fun BigInteger.plus(b: Number): BigInteger = plus(number(b)) + override fun BigInteger.minus(b: Number): BigInteger = minus(number(b)) + override fun BigInteger.div(k: Number): BigInteger = divide(number(k)) + override fun BigInteger.times(k: Number): BigInteger = multiply(number(k)) +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 487e1d87f..e902b70bb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -47,5 +47,6 @@ include( ":kmath-for-real", ":kmath-geometry", ":kmath-ast", + ":kmath-bignum", ":examples" )