Update Jafama module documentation with some minor code amendments #368
@ -175,7 +175,7 @@ One can still use generic algebras though.
|
|||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-functions](kmath-functions)
|
* ### [kmath-functions](kmath-functions)
|
||||||
> Functions, integration and interpolation
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
>
|
>
|
||||||
@ -204,6 +204,10 @@ One can still use generic algebras though.
|
|||||||
>
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
|
>
|
||||||
|
> **Features:**
|
||||||
|
> - [jafama-double](kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/) : Double ExtendedField implementations based on Jafama
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-jupyter](kmath-jupyter)
|
* ### [kmath-jupyter](kmath-jupyter)
|
||||||
|
@ -12,6 +12,7 @@ repositories {
|
|||||||
maven("https://repo.kotlin.link")
|
maven("https://repo.kotlin.link")
|
||||||
maven("https://clojars.org/repo")
|
maven("https://clojars.org/repo")
|
||||||
maven("https://jitpack.io")
|
maven("https://jitpack.io")
|
||||||
|
|
||||||
maven("http://logicrunch.research.it.uu.se/maven") {
|
maven("http://logicrunch.research.it.uu.se/maven") {
|
||||||
isAllowInsecureProtocol = true
|
isAllowInsecureProtocol = true
|
||||||
}
|
}
|
||||||
|
@ -13,44 +13,27 @@ import space.kscience.kmath.jafama.JafamaDoubleField
|
|||||||
import space.kscience.kmath.jafama.StrictJafamaDoubleField
|
import space.kscience.kmath.jafama.StrictJafamaDoubleField
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.math.cos
|
import kotlin.random.Random
|
||||||
import kotlin.math.exp
|
|
||||||
import kotlin.math.pow
|
|
||||||
|
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
internal class JafamaBenchmark {
|
internal class JafamaBenchmark {
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun jafamaBench(blackhole: Blackhole) = invokeBenchmarks(jafama, blackhole)
|
fun jafamaBench(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
|
||||||
|
JafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
|
||||||
@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 {
|
@Benchmark
|
||||||
private val x: Double = Double.MAX_VALUE
|
fun coreBench(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
|
||||||
|
DoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
|
||||||
|
}
|
||||||
|
|
||||||
private val jafama = JafamaDoubleField{
|
@Benchmark
|
||||||
x * power(x, 1_000_000) * exp(x) / cos(x)
|
fun strictJafamaBench(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
|
||||||
}
|
StrictJafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
|
||||||
|
}
|
||||||
|
|
||||||
private val kotlinMath = x * x.pow(1_000_000) * exp(x) / cos(x)
|
private inline fun invokeBenchmarks(blackhole: Blackhole, expr: (Double) -> Double) {
|
||||||
|
val rng = Random(0)
|
||||||
private val core = DoubleField {
|
repeat(1000000) { blackhole.consume(expr(rng.nextDouble())) }
|
||||||
x * power(x, 1_000_000) * exp(x) / cos(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val strictJafama = StrictJafamaDoubleField {
|
|
||||||
x * power(x, 1_000_000) * exp(x) / cos(x)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,10 +37,9 @@ kotlin.sourceSets {
|
|||||||
|
|
||||||
jsMain {
|
jsMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(npm("astring", "1.7.4"))
|
implementation(npm("astring", "1.7.5"))
|
||||||
implementation(npm("binaryen", "100.0"))
|
implementation(npm("binaryen", "101.0.0"))
|
||||||
implementation(npm("js-base64", "3.6.0"))
|
implementation(npm("js-base64", "3.6.1"))
|
||||||
implementation(npm("webassembly", "0.11.0"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import space.kscience.kmath.expressions.MstExtendedField
|
|||||||
import space.kscience.kmath.expressions.Symbol.Companion.x
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.bindSymbol
|
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
@ -64,7 +64,7 @@ public object DoubleField : ExtendedField<Double>, Norm<Double, Double>, ScaleOp
|
|||||||
public override inline val zero: Double get() = 0.0
|
public override inline val zero: Double get() = 0.0
|
||||||
public override inline val one: Double get() = 1.0
|
public override inline val one: Double get() = 1.0
|
||||||
|
|
||||||
public override fun number(value: Number): Double = value.toDouble()
|
public override inline fun number(value: Number): Double = value.toDouble()
|
||||||
|
|
||||||
public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
|
public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
|
||||||
when (operation) {
|
when (operation) {
|
||||||
@ -77,7 +77,7 @@ public object DoubleField : ExtendedField<Double>, Norm<Double, Double>, ScaleOp
|
|||||||
public override inline fun multiply(a: Double, b: Double): Double = a * b
|
public override inline fun multiply(a: Double, b: Double): Double = a * b
|
||||||
public override inline fun divide(a: Double, b: Double): Double = a / b
|
public override inline fun divide(a: Double, b: Double): Double = a / b
|
||||||
|
|
||||||
public override fun scale(a: Double, value: Double): Double = a * value
|
public override inline fun scale(a: Double, value: Double): Double = a * value
|
||||||
|
|
||||||
public override inline fun sin(arg: Double): Double = kotlin.math.sin(arg)
|
public override inline fun sin(arg: Double): Double = kotlin.math.sin(arg)
|
||||||
public override inline fun cos(arg: Double): Double = kotlin.math.cos(arg)
|
public override inline fun cos(arg: Double): Double = kotlin.math.cos(arg)
|
||||||
@ -93,6 +93,7 @@ public object DoubleField : ExtendedField<Double>, Norm<Double, Double>, ScaleOp
|
|||||||
public override inline fun acosh(arg: Double): Double = kotlin.math.acosh(arg)
|
public override inline fun acosh(arg: Double): Double = kotlin.math.acosh(arg)
|
||||||
public override inline fun atanh(arg: Double): Double = kotlin.math.atanh(arg)
|
public override inline fun atanh(arg: Double): Double = kotlin.math.atanh(arg)
|
||||||
|
|
||||||
|
public override inline fun sqrt(arg: Double): Double = kotlin.math.sqrt(arg)
|
||||||
public override inline fun power(arg: Double, pow: Number): Double = arg.kpow(pow.toDouble())
|
public override inline fun power(arg: Double, pow: Number): Double = arg.kpow(pow.toDouble())
|
||||||
public override inline fun exp(arg: Double): Double = kotlin.math.exp(arg)
|
public override inline fun exp(arg: Double): Double = kotlin.math.exp(arg)
|
||||||
public override inline fun ln(arg: Double): Double = kotlin.math.ln(arg)
|
public override inline fun ln(arg: Double): Double = kotlin.math.ln(arg)
|
||||||
@ -143,6 +144,7 @@ public object FloatField : ExtendedField<Float>, Norm<Float, Float> {
|
|||||||
public override inline fun acosh(arg: Float): Float = kotlin.math.acosh(arg)
|
public override inline fun acosh(arg: Float): Float = kotlin.math.acosh(arg)
|
||||||
public override inline fun atanh(arg: Float): Float = kotlin.math.atanh(arg)
|
public override inline fun atanh(arg: Float): Float = kotlin.math.atanh(arg)
|
||||||
|
|
||||||
|
public override inline fun sqrt(arg: Float): Float = kotlin.math.sqrt(arg)
|
||||||
public override inline fun power(arg: Float, pow: Number): Float = arg.kpow(pow.toFloat())
|
public override inline fun power(arg: Float, pow: Number): Float = arg.kpow(pow.toFloat())
|
||||||
public override inline fun exp(arg: Float): Float = kotlin.math.exp(arg)
|
public override inline fun exp(arg: Float): Float = kotlin.math.exp(arg)
|
||||||
public override inline fun ln(arg: Float): Float = kotlin.math.ln(arg)
|
public override inline fun ln(arg: Float): Float = kotlin.math.ln(arg)
|
||||||
|
@ -3,6 +3,8 @@ plugins {
|
|||||||
id("ru.mipt.npm.gradle.common")
|
id("ru.mipt.npm.gradle.common")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
description = "Functions, integration and interpolation"
|
||||||
|
|
||||||
kotlin.sourceSets.commonMain {
|
kotlin.sourceSets.commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":kmath-core"))
|
api(project(":kmath-core"))
|
||||||
@ -10,7 +12,6 @@ kotlin.sourceSets.commonMain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readme {
|
readme {
|
||||||
description = "Functions, integration and interpolation"
|
|
||||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||||
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
||||||
|
|
||||||
|
@ -1,80 +1,144 @@
|
|||||||
# Module kmath-jafama
|
# Module kmath-jafama
|
||||||
|
|
||||||
Jafama based implementation of DoubleField of kmath-operations.
|
Integration with [Jafama](https://github.com/jeffhain/jafama).
|
||||||
|
|
||||||
- JafamaDoubleField : DoubleField implementation using FastMath
|
- [jafama-double](src/main/kotlin/space/kscience/kmath/jafama/) : Double ExtendedField implementations based on Jafama
|
||||||
- StrictJafamaDoubleField - DoubleField implementation using StrictFastMath
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
Different Operations on DoubleField
|
## Artifact:
|
||||||
|
|
||||||
|
The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.0-dev-13`.
|
||||||
|
|
||||||
|
**Gradle:**
|
||||||
|
```gradle
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-jafama:0.3.0-dev-13'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
package space.kscience.kmath.jafama
|
repositories {
|
||||||
|
maven("https://repo.kotlin.link")
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
import net.jafama.FastMath
|
dependencies {
|
||||||
|
implementation("space.kscience:kmath-jafama:0.3.0-dev-13")
|
||||||
|
|
||||||
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
|
## Example usage
|
||||||
Comparing Operations on DoubleField and JafamaDoubleField
|
|
||||||
```bash
|
All the `DoubleField` uses can be replaced with `JafamaDoubleField` or `StrictJafamaDoubleField`.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
import space.kscience.kmath.jafama.*
|
||||||
|
import space.kscience.kmath.operations.*
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val a = 2.0
|
||||||
|
val b = StrictJafamaDoubleField { exp(a) }
|
||||||
|
println(JafamaDoubleField { b + a })
|
||||||
|
println(StrictJafamaDoubleField { ln(b) })
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
According to benchmarking data, on Hotspot Jafama functions are 20% faster than JDK math. On GraalVM, they are slower.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Raw data:</summary>
|
||||||
|
|
||||||
|
**Hotspot**
|
||||||
|
|
||||||
|
```
|
||||||
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench
|
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench
|
||||||
|
|
||||||
Warm-up 1: 384414358.081 ops/s
|
Warm-up 1: 11.447 ops/s
|
||||||
Iteration 1: 374827571.951 ops/s
|
Iteration 1: 13.354 ops/s
|
||||||
Iteration 2: 479335182.332 ops/s
|
Iteration 2: 14.237 ops/s
|
||||||
Iteration 3: 475483069.577 ops/s
|
Iteration 3: 14.708 ops/s
|
||||||
Iteration 4: 478235949.414 ops/s
|
Iteration 4: 14.629 ops/s
|
||||||
Iteration 5: 472256385.114 ops/s
|
Iteration 5: 14.692 ops/s
|
||||||
|
|
||||||
456027631.678 ±(99.9%) 175106815.384 ops/s [Average]
|
14.324 ±(99.9%) 2.217 ops/s [Average]
|
||||||
(min, avg, max) = (374827571.951, 456027631.678, 479335182.332), stdev = 45474683.880
|
(min, avg, max) = (13.354, 14.324, 14.708), stdev = 0.576
|
||||||
CI (99.9%): [280920816.294, 631134447.061] (assumes normal distribution)
|
CI (99.9%): [12.107, 16.541] (assumes normal distribution)
|
||||||
|
|
||||||
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench
|
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench
|
||||||
|
|
||||||
Warm-up 1: 359418665.041 ops/s
|
Warm-up 1: 15.628 ops/s
|
||||||
Iteration 1: 335704885.798 ops/s
|
Iteration 1: 15.991 ops/s
|
||||||
Iteration 2: 427684801.542 ops/s
|
Iteration 2: 16.633 ops/s
|
||||||
Iteration 3: 452193034.265 ops/s
|
Iteration 3: 16.583 ops/s
|
||||||
Iteration 4: 433855064.931 ops/s
|
Iteration 4: 16.716 ops/s
|
||||||
Iteration 5: 453863386.566 ops/s
|
Iteration 5: 16.762 ops/s
|
||||||
|
|
||||||
420660234.620 ±(99.9%) 188028426.875 ops/s [Average]
|
16.537 ±(99.9%) 1.205 ops/s [Average]
|
||||||
(min, avg, max) = (335704885.798, 420660234.620, 453863386.566), stdev = 48830385.349
|
(min, avg, max) = (15.991, 16.537, 16.762), stdev = 0.313
|
||||||
CI (99.9%): [232631807.746, 608688661.495] (assumes normal distribution)
|
CI (99.9%): [15.332, 17.743] (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
|
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench
|
||||||
|
|
||||||
Warm-up 1: 371241281.065 ops/s
|
Warm-up 1: 13.378 ops/s
|
||||||
Iteration 1: 374490259.387 ops/s
|
Iteration 1: 15.049 ops/s
|
||||||
Iteration 2: 464995837.424 ops/s
|
Iteration 2: 14.468 ops/s
|
||||||
Iteration 3: 469788706.385 ops/s
|
Iteration 3: 14.469 ops/s
|
||||||
Iteration 4: 469528470.682 ops/s
|
Iteration 4: 14.753 ops/s
|
||||||
Iteration 5: 456727921.978 ops/s
|
Iteration 5: 14.958 ops/s
|
||||||
|
|
||||||
447106239.171 ±(99.9%) 157629035.980 ops/s [Average]
|
14.739 ±(99.9%) 1.038 ops/s [Average]
|
||||||
(min, avg, max) = (374490259.387, 447106239.171, 469788706.385), stdev = 40935760.071
|
(min, avg, max) = (14.468, 14.739, 15.049), stdev = 0.269
|
||||||
CI (99.9%): [289477203.192, 604735275.151] (assumes normal distribution)
|
CI (99.9%): [13.701, 15.777] (assumes normal distribution)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**GraalVM**
|
||||||
|
|
||||||
|
```
|
||||||
|
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench
|
||||||
|
|
||||||
|
Warm-up 1: 14.357 ops/s
|
||||||
|
Iteration 1: 14.768 ops/s
|
||||||
|
Iteration 2: 14.922 ops/s
|
||||||
|
Iteration 3: 14.966 ops/s
|
||||||
|
Iteration 4: 14.805 ops/s
|
||||||
|
Iteration 5: 14.520 ops/s
|
||||||
|
|
||||||
|
14.796 ±(99.9%) 0.671 ops/s [Average]
|
||||||
|
(min, avg, max) = (14.520, 14.796, 14.966), stdev = 0.174
|
||||||
|
CI (99.9%): [14.125, 15.468] (assumes normal distribution)
|
||||||
|
|
||||||
|
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench
|
||||||
|
|
||||||
|
Warm-up 1: 11.592 ops/s
|
||||||
|
Iteration 1: 12.174 ops/s
|
||||||
|
Iteration 2: 11.734 ops/s
|
||||||
|
Iteration 3: 11.939 ops/s
|
||||||
|
Iteration 4: 12.026 ops/s
|
||||||
|
Iteration 5: 12.221 ops/s
|
||||||
|
|
||||||
|
12.019 ±(99.9%) 0.752 ops/s [Average]
|
||||||
|
(min, avg, max) = (11.734, 12.019, 12.221), stdev = 0.195
|
||||||
|
CI (99.9%): [11.267, 12.771] (assumes normal distribution)
|
||||||
|
|
||||||
|
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench
|
||||||
|
|
||||||
|
Warm-up 1: 12.097 ops/s
|
||||||
|
Iteration 1: 13.072 ops/s
|
||||||
|
Iteration 2: 13.112 ops/s
|
||||||
|
Iteration 3: 13.103 ops/s
|
||||||
|
Iteration 4: 12.950 ops/s
|
||||||
|
Iteration 5: 13.011 ops/s
|
||||||
|
|
||||||
|
13.049 ±(99.9%) 0.263 ops/s [Average]
|
||||||
|
(min, avg, max) = (12.950, 13.049, 13.112), stdev = 0.068
|
||||||
|
CI (99.9%): [12.787, 13.312] (assumes normal distribution)
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
@ -2,6 +2,8 @@ plugins {
|
|||||||
id("ru.mipt.npm.gradle.jvm")
|
id("ru.mipt.npm.gradle.jvm")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
description = "Jafama integration module"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":kmath-core"))
|
api(project(":kmath-core"))
|
||||||
api("net.jafama:jafama:2.3.2")
|
api("net.jafama:jafama:2.3.2")
|
||||||
@ -13,6 +15,11 @@ repositories {
|
|||||||
|
|
||||||
readme {
|
readme {
|
||||||
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
||||||
|
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
||||||
|
|
||||||
|
feature("jafama-double", "src/main/kotlin/space/kscience/kmath/jafama/") {
|
||||||
|
"Double ExtendedField implementations based on Jafama"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin.sourceSets.all {
|
kotlin.sourceSets.all {
|
||||||
|
118
kmath-jafama/docs/README-TEMPLATE.md
Normal file
118
kmath-jafama/docs/README-TEMPLATE.md
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# Module kmath-jafama
|
||||||
|
|
||||||
|
Integration with [Jafama](https://github.com/jeffhain/jafama).
|
||||||
|
|
||||||
|
${features}
|
||||||
|
|
||||||
|
${artifact}
|
||||||
|
|
||||||
|
## Example usage
|
||||||
|
|
||||||
|
All the `DoubleField` uses can be replaced with `JafamaDoubleField` or `StrictJafamaDoubleField`.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
import space.kscience.kmath.jafama.*
|
||||||
|
import space.kscience.kmath.operations.*
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val a = 2.0
|
||||||
|
val b = StrictJafamaDoubleField { exp(a) }
|
||||||
|
println(JafamaDoubleField { b + a })
|
||||||
|
println(StrictJafamaDoubleField { ln(b) })
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
According to benchmarking data, on Hotspot Jafama functions are 20% faster than JDK math. On GraalVM, they are slower.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Raw data:</summary>
|
||||||
|
|
||||||
|
**Hotspot**
|
||||||
|
|
||||||
|
```
|
||||||
|
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench
|
||||||
|
|
||||||
|
Warm-up 1: 11.447 ops/s
|
||||||
|
Iteration 1: 13.354 ops/s
|
||||||
|
Iteration 2: 14.237 ops/s
|
||||||
|
Iteration 3: 14.708 ops/s
|
||||||
|
Iteration 4: 14.629 ops/s
|
||||||
|
Iteration 5: 14.692 ops/s
|
||||||
|
|
||||||
|
14.324 ±(99.9%) 2.217 ops/s [Average]
|
||||||
|
(min, avg, max) = (13.354, 14.324, 14.708), stdev = 0.576
|
||||||
|
CI (99.9%): [12.107, 16.541] (assumes normal distribution)
|
||||||
|
|
||||||
|
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench
|
||||||
|
|
||||||
|
Warm-up 1: 15.628 ops/s
|
||||||
|
Iteration 1: 15.991 ops/s
|
||||||
|
Iteration 2: 16.633 ops/s
|
||||||
|
Iteration 3: 16.583 ops/s
|
||||||
|
Iteration 4: 16.716 ops/s
|
||||||
|
Iteration 5: 16.762 ops/s
|
||||||
|
|
||||||
|
16.537 ±(99.9%) 1.205 ops/s [Average]
|
||||||
|
(min, avg, max) = (15.991, 16.537, 16.762), stdev = 0.313
|
||||||
|
CI (99.9%): [15.332, 17.743] (assumes normal distribution)
|
||||||
|
|
||||||
|
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench
|
||||||
|
|
||||||
|
Warm-up 1: 13.378 ops/s
|
||||||
|
Iteration 1: 15.049 ops/s
|
||||||
|
Iteration 2: 14.468 ops/s
|
||||||
|
Iteration 3: 14.469 ops/s
|
||||||
|
Iteration 4: 14.753 ops/s
|
||||||
|
Iteration 5: 14.958 ops/s
|
||||||
|
|
||||||
|
14.739 ±(99.9%) 1.038 ops/s [Average]
|
||||||
|
(min, avg, max) = (14.468, 14.739, 15.049), stdev = 0.269
|
||||||
|
CI (99.9%): [13.701, 15.777] (assumes normal distribution)
|
||||||
|
```
|
||||||
|
|
||||||
|
**GraalVM**
|
||||||
|
|
||||||
|
```
|
||||||
|
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench
|
||||||
|
|
||||||
|
Warm-up 1: 14.357 ops/s
|
||||||
|
Iteration 1: 14.768 ops/s
|
||||||
|
Iteration 2: 14.922 ops/s
|
||||||
|
Iteration 3: 14.966 ops/s
|
||||||
|
Iteration 4: 14.805 ops/s
|
||||||
|
Iteration 5: 14.520 ops/s
|
||||||
|
|
||||||
|
14.796 ±(99.9%) 0.671 ops/s [Average]
|
||||||
|
(min, avg, max) = (14.520, 14.796, 14.966), stdev = 0.174
|
||||||
|
CI (99.9%): [14.125, 15.468] (assumes normal distribution)
|
||||||
|
|
||||||
|
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench
|
||||||
|
|
||||||
|
Warm-up 1: 11.592 ops/s
|
||||||
|
Iteration 1: 12.174 ops/s
|
||||||
|
Iteration 2: 11.734 ops/s
|
||||||
|
Iteration 3: 11.939 ops/s
|
||||||
|
Iteration 4: 12.026 ops/s
|
||||||
|
Iteration 5: 12.221 ops/s
|
||||||
|
|
||||||
|
12.019 ±(99.9%) 0.752 ops/s [Average]
|
||||||
|
(min, avg, max) = (11.734, 12.019, 12.221), stdev = 0.195
|
||||||
|
CI (99.9%): [11.267, 12.771] (assumes normal distribution)
|
||||||
|
|
||||||
|
jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench
|
||||||
|
|
||||||
|
Warm-up 1: 12.097 ops/s
|
||||||
|
Iteration 1: 13.072 ops/s
|
||||||
|
Iteration 2: 13.112 ops/s
|
||||||
|
Iteration 3: 13.103 ops/s
|
||||||
|
Iteration 4: 12.950 ops/s
|
||||||
|
Iteration 5: 13.011 ops/s
|
||||||
|
|
||||||
|
13.049 ±(99.9%) 0.263 ops/s [Average]
|
||||||
|
(min, avg, max) = (12.950, 13.049, 13.112), stdev = 0.068
|
||||||
|
CI (99.9%): [12.787, 13.312] (assumes normal distribution)
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
@ -1,17 +1,21 @@
|
|||||||
package space.kscience.kmath.jafama
|
package space.kscience.kmath.jafama
|
||||||
|
|
||||||
import space.kscience.kmath.operations.*
|
import net.jafama.FastMath
|
||||||
import net.jafama.*
|
import net.jafama.StrictFastMath
|
||||||
|
import space.kscience.kmath.operations.ExtendedField
|
||||||
|
import space.kscience.kmath.operations.Norm
|
||||||
|
import space.kscience.kmath.operations.PowerOperations
|
||||||
|
import space.kscience.kmath.operations.ScaleOperations
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A field for [Double] (using FastMath) without boxing. Does not produce appropriate field element.
|
* 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")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||||
public object JafamaDoubleField : ExtendedField<Double>, Norm<Double, Double>, ScaleOperations<Double> {
|
public object JafamaDoubleField : ExtendedField<Double>, Norm<Double, Double>, ScaleOperations<Double> {
|
||||||
public override val zero: Double get() = 0.0
|
public override inline val zero: Double get() = 0.0
|
||||||
public override val one: Double get() = 1.0
|
public override inline val one: Double get() = 1.0
|
||||||
|
|
||||||
public override fun number(value: Number): Double = value.toDouble()
|
public override inline fun number(value: Number): Double = value.toDouble()
|
||||||
|
|
||||||
public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
|
public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
|
||||||
when (operation) {
|
when (operation) {
|
||||||
@ -19,38 +23,39 @@ public object JafamaDoubleField : ExtendedField<Double>, Norm<Double, Double>, S
|
|||||||
else -> super<ExtendedField>.binaryOperationFunction(operation)
|
else -> super<ExtendedField>.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun add(a: Double, b: Double): Double = a + b
|
public override inline fun add(a: Double, b: Double): Double = a + b
|
||||||
|
|
||||||
public override fun multiply(a: Double, b: Double): Double = a * b
|
public override inline fun multiply(a: Double, b: Double): Double = a * b
|
||||||
public override fun divide(a: Double, b: Double): Double = a / b
|
public override inline fun divide(a: Double, b: Double): Double = a / b
|
||||||
|
|
||||||
public override fun scale(a: Double, value: Double): Double = a * value
|
public override inline fun scale(a: Double, value: Double): Double = a * value
|
||||||
|
|
||||||
public override fun sin(arg: Double): Double = FastMath.sin(arg)
|
public override inline fun sin(arg: Double): Double = FastMath.sin(arg)
|
||||||
public override fun cos(arg: Double): Double = FastMath.cos(arg)
|
public override inline fun cos(arg: Double): Double = FastMath.cos(arg)
|
||||||
public override fun tan(arg: Double): Double = FastMath.tan(arg)
|
public override inline fun tan(arg: Double): Double = FastMath.tan(arg)
|
||||||
public override fun acos(arg: Double): Double = FastMath.acos(arg)
|
public override inline fun acos(arg: Double): Double = FastMath.acos(arg)
|
||||||
public override fun asin(arg: Double): Double = FastMath.asin(arg)
|
public override inline fun asin(arg: Double): Double = FastMath.asin(arg)
|
||||||
public override fun atan(arg: Double): Double = FastMath.atan(arg)
|
public override inline fun atan(arg: Double): Double = FastMath.atan(arg)
|
||||||
|
|
||||||
public override fun sinh(arg: Double): Double = FastMath.sinh(arg)
|
public override inline fun sinh(arg: Double): Double = FastMath.sinh(arg)
|
||||||
public override fun cosh(arg: Double): Double = FastMath.cosh(arg)
|
public override inline fun cosh(arg: Double): Double = FastMath.cosh(arg)
|
||||||
public override fun tanh(arg: Double): Double = FastMath.tanh(arg)
|
public override inline fun tanh(arg: Double): Double = FastMath.tanh(arg)
|
||||||
public override fun asinh(arg: Double): Double = FastMath.asinh(arg)
|
public override inline fun asinh(arg: Double): Double = FastMath.asinh(arg)
|
||||||
public override fun acosh(arg: Double): Double = FastMath.acosh(arg)
|
public override inline fun acosh(arg: Double): Double = FastMath.acosh(arg)
|
||||||
public override fun atanh(arg: Double): Double = FastMath.atanh(arg)
|
public override inline fun atanh(arg: Double): Double = FastMath.atanh(arg)
|
||||||
|
|
||||||
public override fun power(arg: Double, pow: Number): Double = FastMath.pow(arg, pow.toDouble())
|
public override inline fun sqrt(arg: Double): Double = FastMath.sqrt(arg)
|
||||||
public override fun exp(arg: Double): Double = FastMath.exp(arg)
|
public override inline fun power(arg: Double, pow: Number): Double = FastMath.pow(arg, pow.toDouble())
|
||||||
public override fun ln(arg: Double): Double = FastMath.log(arg)
|
public override inline fun exp(arg: Double): Double = FastMath.exp(arg)
|
||||||
|
public override inline fun ln(arg: Double): Double = FastMath.log(arg)
|
||||||
|
|
||||||
public override fun norm(arg: Double): Double = FastMath.abs(arg)
|
public override inline fun norm(arg: Double): Double = FastMath.abs(arg)
|
||||||
|
|
||||||
public override fun Double.unaryMinus(): Double = -this
|
public override inline fun Double.unaryMinus(): Double = -this
|
||||||
public override fun Double.plus(b: Double): Double = this + b
|
public override inline fun Double.plus(b: Double): Double = this + b
|
||||||
public override fun Double.minus(b: Double): Double = this - b
|
public override inline fun Double.minus(b: Double): Double = this - b
|
||||||
public override fun Double.times(b: Double): Double = this * b
|
public override inline fun Double.times(b: Double): Double = this * b
|
||||||
public override fun Double.div(b: Double): Double = this / b
|
public override inline fun Double.div(b: Double): Double = this / b
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,10 +63,10 @@ public object JafamaDoubleField : ExtendedField<Double>, Norm<Double, Double>, S
|
|||||||
*/
|
*/
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||||
public object StrictJafamaDoubleField : ExtendedField<Double>, Norm<Double, Double>, ScaleOperations<Double> {
|
public object StrictJafamaDoubleField : ExtendedField<Double>, Norm<Double, Double>, ScaleOperations<Double> {
|
||||||
public override val zero: Double get() = 0.0
|
public override inline val zero: Double get() = 0.0
|
||||||
public override val one: Double get() = 1.0
|
public override inline val one: Double get() = 1.0
|
||||||
|
|
||||||
public override fun number(value: Number): Double = value.toDouble()
|
public override inline fun number(value: Number): Double = value.toDouble()
|
||||||
|
|
||||||
public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
|
public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
|
||||||
when (operation) {
|
when (operation) {
|
||||||
@ -69,38 +74,37 @@ public object StrictJafamaDoubleField : ExtendedField<Double>, Norm<Double, Doub
|
|||||||
else -> super<ExtendedField>.binaryOperationFunction(operation)
|
else -> super<ExtendedField>.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun add(a: Double, b: Double): Double = a + b
|
public override inline fun add(a: Double, b: Double): Double = a + b
|
||||||
|
|
||||||
public override fun multiply(a: Double, b: Double): Double = a * b
|
public override inline fun multiply(a: Double, b: Double): Double = a * b
|
||||||
public override fun divide(a: Double, b: Double): Double = a / b
|
public override inline fun divide(a: Double, b: Double): Double = a / b
|
||||||
|
|
||||||
public override fun scale(a: Double, value: Double): Double = a * value
|
public override inline fun scale(a: Double, value: Double): Double = a * value
|
||||||
|
|
||||||
public override fun sin(arg: Double): Double = StrictFastMath.sin(arg)
|
public override inline fun sin(arg: Double): Double = StrictFastMath.sin(arg)
|
||||||
public override fun cos(arg: Double): Double = StrictFastMath.cos(arg)
|
public override inline fun cos(arg: Double): Double = StrictFastMath.cos(arg)
|
||||||
public override fun tan(arg: Double): Double = StrictFastMath.tan(arg)
|
public override inline fun tan(arg: Double): Double = StrictFastMath.tan(arg)
|
||||||
public override fun acos(arg: Double): Double = StrictFastMath.acos(arg)
|
public override inline fun acos(arg: Double): Double = StrictFastMath.acos(arg)
|
||||||
public override fun asin(arg: Double): Double = StrictFastMath.asin(arg)
|
public override inline fun asin(arg: Double): Double = StrictFastMath.asin(arg)
|
||||||
public override fun atan(arg: Double): Double = StrictFastMath.atan(arg)
|
public override inline fun atan(arg: Double): Double = StrictFastMath.atan(arg)
|
||||||
|
|
||||||
public override fun sinh(arg: Double): Double = StrictFastMath.sinh(arg)
|
public override inline fun sinh(arg: Double): Double = StrictFastMath.sinh(arg)
|
||||||
public override fun cosh(arg: Double): Double = StrictFastMath.cosh(arg)
|
public override inline fun cosh(arg: Double): Double = StrictFastMath.cosh(arg)
|
||||||
public override fun tanh(arg: Double): Double = StrictFastMath.tanh(arg)
|
public override inline fun tanh(arg: Double): Double = StrictFastMath.tanh(arg)
|
||||||
public override fun asinh(arg: Double): Double = StrictFastMath.asinh(arg)
|
public override inline fun asinh(arg: Double): Double = StrictFastMath.asinh(arg)
|
||||||
public override fun acosh(arg: Double): Double = StrictFastMath.acosh(arg)
|
public override inline fun acosh(arg: Double): Double = StrictFastMath.acosh(arg)
|
||||||
public override fun atanh(arg: Double): Double = StrictFastMath.atanh(arg)
|
public override inline fun atanh(arg: Double): Double = StrictFastMath.atanh(arg)
|
||||||
|
|
||||||
public override fun power(arg: Double, pow: Number): Double = StrictFastMath.pow(arg, pow.toDouble())
|
public override inline fun sqrt(arg: Double): Double = StrictFastMath.sqrt(arg)
|
||||||
public override fun exp(arg: Double): Double = StrictFastMath.exp(arg)
|
public override inline fun power(arg: Double, pow: Number): Double = StrictFastMath.pow(arg, pow.toDouble())
|
||||||
public override fun ln(arg: Double): Double = StrictFastMath.log(arg)
|
public override inline fun exp(arg: Double): Double = StrictFastMath.exp(arg)
|
||||||
|
public override inline fun ln(arg: Double): Double = StrictFastMath.log(arg)
|
||||||
|
|
||||||
public override fun norm(arg: Double): Double = StrictFastMath.abs(arg)
|
public override inline fun norm(arg: Double): Double = StrictFastMath.abs(arg)
|
||||||
|
|
||||||
public override fun Double.unaryMinus(): Double = -this
|
public override inline fun Double.unaryMinus(): Double = -this
|
||||||
public override fun Double.plus(b: Double): Double = this + b
|
public override inline fun Double.plus(b: Double): Double = this + b
|
||||||
public override fun Double.minus(b: Double): Double = this - b
|
public override inline fun Double.minus(b: Double): Double = this - b
|
||||||
public override fun Double.times(b: Double): Double = this * b
|
public override inline fun Double.times(b: Double): Double = this * b
|
||||||
public override fun Double.div(b: Double): Double = this / b
|
public override inline fun Double.div(b: Double): Double = this / b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user