diff --git a/README.md b/README.md
index 7c6f7ea2b..90ab524e2 100644
--- a/README.md
+++ b/README.md
@@ -200,6 +200,12 @@ One can still use generic algebras though.
> **Maturity**: PROTOTYPE
+* ### [kmath-jafama](kmath-jafama)
+>
+>
+> **Maturity**: PROTOTYPE
+
+
* ### [kmath-jupyter](kmath-jupyter)
>
>
diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts
index 98ffc5a96..182c182d9 100644
--- a/benchmarks/build.gradle.kts
+++ b/benchmarks/build.gradle.kts
@@ -30,6 +30,7 @@ kotlin {
implementation(project(":kmath-stat"))
implementation(project(":kmath-dimensions"))
implementation(project(":kmath-for-real"))
+ implementation(project(":kmath-jafama"))
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.0")
}
}
@@ -42,7 +43,6 @@ kotlin {
implementation(project(":kmath-kotlingrad"))
implementation(project(":kmath-viktor"))
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
-
// uncomment if your system supports AVX2
// val os = System.getProperty("os.name")
//
@@ -95,6 +95,11 @@ benchmark {
commonConfiguration()
include("BigIntBenchmark")
}
+
+ configurations.register("jafamaDouble") {
+ commonConfiguration()
+ include("JafamaBenchmark")
+ }
}
// Fix kotlinx-benchmarks bug
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt
new file mode 100644
index 000000000..e998054fb
--- /dev/null
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.benchmarks
+
+import kotlinx.benchmark.Blackhole
+import org.openjdk.jmh.annotations.Benchmark
+import org.openjdk.jmh.annotations.Scope
+import org.openjdk.jmh.annotations.State
+import space.kscience.kmath.jafama.JafamaDoubleField
+import space.kscience.kmath.jafama.StrictJafamaDoubleField
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.operations.invoke
+import kotlin.math.cos
+import kotlin.math.exp
+import kotlin.math.pow
+
+
+@State(Scope.Benchmark)
+internal class JafamaBenchmark {
+ @Benchmark
+ fun jafamaBench(blackhole: Blackhole) = invokeBenchmarks(jafama, blackhole)
+
+ @Benchmark
+ fun coreBench(blackhole: Blackhole) = invokeBenchmarks(core,blackhole)
+
+ @Benchmark
+ fun strictJafamaBench(blackhole: Blackhole) = invokeBenchmarks(strictJafama,blackhole)
+
+ @Benchmark
+ fun kotlinMathBench(blackhole: Blackhole) = invokeBenchmarks(kotlinMath, blackhole)
+
+ private fun invokeBenchmarks(expr: Double, blackhole: Blackhole) {
+ blackhole.consume(expr)
+ }
+
+ private companion object {
+ private val x: Double = Double.MAX_VALUE
+
+ private val jafama = JafamaDoubleField{
+ x * power(x, 1_000_000) * exp(x) / cos(x)
+ }
+
+ private val kotlinMath = x * x.pow(1_000_000) * exp(x) / cos(x)
+
+ private val core = DoubleField {
+ x * power(x, 1_000_000) * exp(x) / cos(x)
+ }
+
+ private val strictJafama = StrictJafamaDoubleField {
+ x * power(x, 1_000_000) * exp(x) / cos(x)
+ }
+ }
+}
diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts
index 568bde153..406b8f470 100644
--- a/examples/build.gradle.kts
+++ b/examples/build.gradle.kts
@@ -44,6 +44,8 @@ dependencies {
implementation("org.slf4j:slf4j-simple:1.7.30")
// plotting
implementation("space.kscience:plotlykt-server:0.4.0")
+ //jafama
+ implementation(project(":kmath-jafama"))
}
kotlin.sourceSets.all {
diff --git a/examples/src/main/kotlin/space/kscience/kmath/jafama/KMathaJafamaDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/jafama/KMathaJafamaDemo.kt
new file mode 100644
index 000000000..879aab08f
--- /dev/null
+++ b/examples/src/main/kotlin/space/kscience/kmath/jafama/KMathaJafamaDemo.kt
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.jafama
+
+import net.jafama.FastMath
+
+
+fun main(){
+ val a = JafamaDoubleField.number(2.0)
+ val b = StrictJafamaDoubleField.power(FastMath.E,a)
+
+ println(JafamaDoubleField.add(b,a))
+ println(StrictJafamaDoubleField.ln(b))
+}
diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md
new file mode 100644
index 000000000..d170f6591
--- /dev/null
+++ b/kmath-jafama/README.md
@@ -0,0 +1,80 @@
+# Module kmath-jafama
+
+Jafama based implementation of DoubleField of kmath-operations.
+
+- JafamaDoubleField : DoubleField implementation using FastMath
+- StrictJafamaDoubleField - DoubleField implementation using StrictFastMath
+
+## Examples
+
+Different Operations on DoubleField
+
+```kotlin
+package space.kscience.kmath.jafama
+
+import net.jafama.FastMath
+
+
+fun main(){
+ val a = JafamaDoubleField.number(2.0)
+ val b = StrictJafamaDoubleField.power(FastMath.E,a)
+ println(JafamaDoubleField.add(b,a))
+ println(StrictJafamaDoubleField.ln(b))
+}
+```
+
+## Benchmarks
+Comparing Operations on DoubleField and JafamaDoubleField
+```bash
+jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench
+
+Warm-up 1: 384414358.081 ops/s
+Iteration 1: 374827571.951 ops/s
+Iteration 2: 479335182.332 ops/s
+Iteration 3: 475483069.577 ops/s
+Iteration 4: 478235949.414 ops/s
+Iteration 5: 472256385.114 ops/s
+
+456027631.678 ±(99.9%) 175106815.384 ops/s [Average]
+ (min, avg, max) = (374827571.951, 456027631.678, 479335182.332), stdev = 45474683.880
+ CI (99.9%): [280920816.294, 631134447.061] (assumes normal distribution)
+
+jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench
+
+Warm-up 1: 359418665.041 ops/s
+Iteration 1: 335704885.798 ops/s
+Iteration 2: 427684801.542 ops/s
+Iteration 3: 452193034.265 ops/s
+Iteration 4: 433855064.931 ops/s
+Iteration 5: 453863386.566 ops/s
+
+420660234.620 ±(99.9%) 188028426.875 ops/s [Average]
+ (min, avg, max) = (335704885.798, 420660234.620, 453863386.566), stdev = 48830385.349
+ CI (99.9%): [232631807.746, 608688661.495] (assumes normal distribution)
+
+jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.kotlinMathBench
+
+Warm-up 1: 371570418.113 ops/s
+Iteration 1: 379281146.127 ops/s
+Iteration 2: 465234403.109 ops/s
+Iteration 3: 470621634.240 ops/s
+Iteration 4: 467074553.006 ops/s
+Iteration 5: 466424840.144 ops/s
+
+449727315.325 ±(99.9%) 151837475.500 ops/s [Average]
+ (min, avg, max) = (379281146.127, 449727315.325, 470621634.240), stdev = 39431710.207
+ CI (99.9%): [297889839.825, 601564790.825] (assumes normal distribution)
+
+jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench
+
+Warm-up 1: 371241281.065 ops/s
+Iteration 1: 374490259.387 ops/s
+Iteration 2: 464995837.424 ops/s
+Iteration 3: 469788706.385 ops/s
+Iteration 4: 469528470.682 ops/s
+Iteration 5: 456727921.978 ops/s
+
+447106239.171 ±(99.9%) 157629035.980 ops/s [Average]
+ (min, avg, max) = (374490259.387, 447106239.171, 469788706.385), stdev = 40935760.071
+ CI (99.9%): [289477203.192, 604735275.151] (assumes normal distribution)
+```
diff --git a/kmath-jafama/build.gradle.kts b/kmath-jafama/build.gradle.kts
new file mode 100644
index 000000000..f31f2602f
--- /dev/null
+++ b/kmath-jafama/build.gradle.kts
@@ -0,0 +1,20 @@
+plugins {
+ id("ru.mipt.npm.gradle.jvm")
+}
+
+dependencies {
+ api(project(":kmath-core"))
+ api("net.jafama:jafama:2.3.2")
+}
+
+repositories {
+ mavenCentral()
+}
+
+readme {
+ maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
+}
+
+kotlin.sourceSets.all {
+ languageSettings.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI")
+}
diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt
new file mode 100644
index 000000000..f37d8e7b3
--- /dev/null
+++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt
@@ -0,0 +1,106 @@
+package space.kscience.kmath.jafama
+
+import space.kscience.kmath.operations.*
+import net.jafama.*
+
+/**
+ * A field for [Double] (using FastMath) without boxing. Does not produce appropriate field element.
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
+public object JafamaDoubleField : ExtendedField, Norm, ScaleOperations {
+ public override val zero: Double get() = 0.0
+ public override val one: Double get() = 1.0
+
+ public override fun number(value: Number): Double = value.toDouble()
+
+ public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
+ when (operation) {
+ PowerOperations.POW_OPERATION -> ::power
+ else -> super.binaryOperationFunction(operation)
+ }
+
+ public override fun add(a: Double, b: Double): Double = a + b
+
+ public override fun multiply(a: Double, b: Double): Double = a * b
+ public override fun divide(a: Double, b: Double): Double = a / b
+
+ public override fun scale(a: Double, value: Double): Double = a * value
+
+ public override fun sin(arg: Double): Double = FastMath.sin(arg)
+ public override fun cos(arg: Double): Double = FastMath.cos(arg)
+ public override fun tan(arg: Double): Double = FastMath.tan(arg)
+ public override fun acos(arg: Double): Double = FastMath.acos(arg)
+ public override fun asin(arg: Double): Double = FastMath.asin(arg)
+ public override fun atan(arg: Double): Double = FastMath.atan(arg)
+
+ public override fun sinh(arg: Double): Double = FastMath.sinh(arg)
+ public override fun cosh(arg: Double): Double = FastMath.cosh(arg)
+ public override fun tanh(arg: Double): Double = FastMath.tanh(arg)
+ public override fun asinh(arg: Double): Double = FastMath.asinh(arg)
+ public override fun acosh(arg: Double): Double = FastMath.acosh(arg)
+ public override fun atanh(arg: Double): Double = FastMath.atanh(arg)
+
+ public override fun power(arg: Double, pow: Number): Double = FastMath.pow(arg, pow.toDouble())
+ public override fun exp(arg: Double): Double = FastMath.exp(arg)
+ public override fun ln(arg: Double): Double = FastMath.log(arg)
+
+ public override fun norm(arg: Double): Double = FastMath.abs(arg)
+
+ public override fun Double.unaryMinus(): Double = -this
+ public override fun Double.plus(b: Double): Double = this + b
+ public override fun Double.minus(b: Double): Double = this - b
+ public override fun Double.times(b: Double): Double = this * b
+ public override fun Double.div(b: Double): Double = this / b
+}
+
+/**
+ * A field for [Double] (using StrictMath) without boxing. Does not produce appropriate field element.
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
+public object StrictJafamaDoubleField : ExtendedField, Norm, ScaleOperations {
+ public override val zero: Double get() = 0.0
+ public override val one: Double get() = 1.0
+
+ public override fun number(value: Number): Double = value.toDouble()
+
+ public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
+ when (operation) {
+ PowerOperations.POW_OPERATION -> ::power
+ else -> super.binaryOperationFunction(operation)
+ }
+
+ public override fun add(a: Double, b: Double): Double = a + b
+
+ public override fun multiply(a: Double, b: Double): Double = a * b
+ public override fun divide(a: Double, b: Double): Double = a / b
+
+ public override fun scale(a: Double, value: Double): Double = a * value
+
+ public override fun sin(arg: Double): Double = StrictFastMath.sin(arg)
+ public override fun cos(arg: Double): Double = StrictFastMath.cos(arg)
+ public override fun tan(arg: Double): Double = StrictFastMath.tan(arg)
+ public override fun acos(arg: Double): Double = StrictFastMath.acos(arg)
+ public override fun asin(arg: Double): Double = StrictFastMath.asin(arg)
+ public override fun atan(arg: Double): Double = StrictFastMath.atan(arg)
+
+ public override fun sinh(arg: Double): Double = StrictFastMath.sinh(arg)
+ public override fun cosh(arg: Double): Double = StrictFastMath.cosh(arg)
+ public override fun tanh(arg: Double): Double = StrictFastMath.tanh(arg)
+ public override fun asinh(arg: Double): Double = StrictFastMath.asinh(arg)
+ public override fun acosh(arg: Double): Double = StrictFastMath.acosh(arg)
+ public override fun atanh(arg: Double): Double = StrictFastMath.atanh(arg)
+
+ public override fun power(arg: Double, pow: Number): Double = StrictFastMath.pow(arg, pow.toDouble())
+ public override fun exp(arg: Double): Double = StrictFastMath.exp(arg)
+ public override fun ln(arg: Double): Double = StrictFastMath.log(arg)
+
+ public override fun norm(arg: Double): Double = StrictFastMath.abs(arg)
+
+ public override fun Double.unaryMinus(): Double = -this
+ public override fun Double.plus(b: Double): Double = this + b
+ public override fun Double.minus(b: Double): Double = this - b
+ public override fun Double.times(b: Double): Double = this * b
+ public override fun Double.div(b: Double): Double = this / b
+}
+
+
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 661afa67c..15a6a176c 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -43,6 +43,7 @@ include(
":kmath-tensors",
":kmath-jupyter",
":kmath-symja",
+ ":kmath-jafama",
":examples",
":benchmarks"
)