From fa9ff4c9787ef18cacbcb4ea38aa30bedf7de681 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 9 Nov 2021 17:56:53 +0300 Subject: [PATCH] Minor refactoring --- .../kmath/benchmarks/BufferBenchmark.kt | 36 ++++++++++++++++++- .../space/kscience/kmath/series/analyzeDif.kt | 3 ++ .../kscience/kmath/structures/BufferView.kt | 18 +++++++--- .../kmath/structures/bufferPrimitiveAccess.kt | 5 +-- .../kscience/kmath/stat/StatisticalAlgebra.kt | 25 ++++++++----- 5 files changed, 71 insertions(+), 16 deletions(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt index f196e21c5..6eb61e2fc 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt @@ -15,11 +15,24 @@ import space.kscience.kmath.complex.complex import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.getDouble +import space.kscience.kmath.structures.permute @State(Scope.Benchmark) internal class BufferBenchmark { + @Benchmark - fun genericDoubleBufferReadWrite(blackhole: Blackhole) { + fun doubleArrayReadWrite(blackhole: Blackhole) { + val buffer = DoubleArray(size) { it.toDouble() } + var res = 0.0 + (0 until size).forEach { + res += buffer[it] + } + blackhole.consume(res) + } + + @Benchmark + fun doubleBufferReadWrite(blackhole: Blackhole) { val buffer = DoubleBuffer(size) { it.toDouble() } var res = 0.0 (0 until size).forEach { @@ -28,6 +41,26 @@ internal class BufferBenchmark { blackhole.consume(res) } + @Benchmark + fun bufferViewReadWrite(blackhole: Blackhole) { + val buffer = DoubleBuffer(size) { it.toDouble() }.permute(reversedIndices) + var res = 0.0 + (0 until size).forEach { + res += buffer[it] + } + blackhole.consume(res) + } + + @Benchmark + fun bufferViewReadWriteSpecialized(blackhole: Blackhole) { + val buffer = DoubleBuffer(size) { it.toDouble() }.permute(reversedIndices) + var res = 0.0 + (0 until size).forEach { + res += buffer.getDouble(it) + } + blackhole.consume(res) + } + @Benchmark fun complexBufferReadWrite(blackhole: Blackhole) = ComplexField { val buffer = Buffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) } @@ -42,5 +75,6 @@ internal class BufferBenchmark { private companion object { private const val size = 100 + private val reversedIndices = IntArray(size){it}.apply { reverse() } } } diff --git a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt index 9b7493438..b9c3141dd 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt @@ -5,6 +5,7 @@ import kotlinx.html.FlowContent import kotlinx.html.h1 import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.bufferAlgebra +import space.kscience.kmath.stat.ksComparisonStatistic import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.slice import space.kscience.kmath.structures.toList @@ -34,6 +35,8 @@ fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) { val s3: Buffer = s1.zip(s2) { l, r -> l + r } //s1 + s2 val s4 = ln(s3) + val kmTest = ksComparisonStatistic(s1, s2) + Plotly.page { h1 { +"This is my plot" } plotSeries(s1) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt index d82efa865..8dc0d63ef 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt @@ -79,11 +79,19 @@ public class BufferExpanded( /** * Zero-copy select a slice inside the original buffer */ -public fun Buffer.slice(range: UIntRange): BufferView = BufferSlice( - this, - range.first, - (range.last - range.first).toInt() + 1 -) +public fun Buffer.slice(range: UIntRange): BufferView = if (this is BufferSlice) { + BufferSlice( + origin, + this.offset + range.first, + (range.last - range.first).toInt() + 1 + ) +} else { + BufferSlice( + this, + range.first, + (range.last - range.first).toInt() + 1 + ) +} /** * Resize original buffer to a given range using given [range], filling additional segments with [defaultValue]. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt index 0e465c64b..d361cb013 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt @@ -5,7 +5,8 @@ import space.kscience.kmath.misc.UnstableKMathAPI /** * Non-boxing access to primitive [Double] */ -@OptIn(UnstableKMathAPI::class) + +@UnstableKMathAPI public fun Buffer.getDouble(index: Int): Double = if (this is BufferView) { val originIndex = originIndex(index) if( originIndex>=0) { @@ -22,7 +23,7 @@ public fun Buffer.getDouble(index: Int): Double = if (this is BufferView /** * Non-boxing access to primitive [Int] */ -@OptIn(UnstableKMathAPI::class) +@UnstableKMathAPI public fun Buffer.getInt(index: Int): Int = if (this is BufferView) { val originIndex = originIndex(index) if( originIndex>=0) { diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt index c8510a8eb..fcda58268 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.stat +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory @@ -20,12 +21,20 @@ public fun > StatisticalAlgebra.ecdf(buffer: Buffer>(val n: Int, val m: Int, val value: T) + +/** + * Kolmogorov-Smirnov sample comparison test * Implementation copied from https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/index.html?org/apache/commons/math3/stat/inference/KolmogorovSmirnovTest.html */ -public fun , A, BA : BufferAlgebra> StatisticalAlgebra.kolmogorovSmirnovTest( +@UnstableKMathAPI +public fun , A, BA : BufferAlgebra> StatisticalAlgebra.ksComparisonStatistic( x: Buffer, y: Buffer, -): T where A : Group, A : NumericAlgebra = elementAlgebra.invoke { +): KMComparisonResult where A : Group, A : NumericAlgebra = elementAlgebra.invoke { // Copy and sort the sample arrays val sx = x.sorted() val sy = y.sorted() @@ -41,19 +50,19 @@ public fun , A, BA : BufferAlgebra> StatisticalAlgebra supD -> supD = curD -curD > supD -> supD = -curD } - } while (rankX < n && rankY < m); - return supD; + } while (rankX < n && rankY < m) + return KMComparisonResult(n, m, supD) } \ No newline at end of file