Minor refactoring

This commit is contained in:
Alexander Nozik 2021-11-09 17:56:53 +03:00
parent d62bc66d4a
commit fa9ff4c978
5 changed files with 71 additions and 16 deletions

View File

@ -15,11 +15,24 @@ import space.kscience.kmath.complex.complex
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.DoubleBuffer
import space.kscience.kmath.structures.getDouble
import space.kscience.kmath.structures.permute
@State(Scope.Benchmark) @State(Scope.Benchmark)
internal class BufferBenchmark { internal class BufferBenchmark {
@Benchmark @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() } val buffer = DoubleBuffer(size) { it.toDouble() }
var res = 0.0 var res = 0.0
(0 until size).forEach { (0 until size).forEach {
@ -28,6 +41,26 @@ internal class BufferBenchmark {
blackhole.consume(res) 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 @Benchmark
fun complexBufferReadWrite(blackhole: Blackhole) = ComplexField { fun complexBufferReadWrite(blackhole: Blackhole) = ComplexField {
val buffer = Buffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) } val buffer = Buffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) }
@ -42,5 +75,6 @@ internal class BufferBenchmark {
private companion object { private companion object {
private const val size = 100 private const val size = 100
private val reversedIndices = IntArray(size){it}.apply { reverse() }
} }
} }

View File

@ -5,6 +5,7 @@ import kotlinx.html.FlowContent
import kotlinx.html.h1 import kotlinx.html.h1
import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.algebra
import space.kscience.kmath.operations.bufferAlgebra import space.kscience.kmath.operations.bufferAlgebra
import space.kscience.kmath.stat.ksComparisonStatistic
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.slice import space.kscience.kmath.structures.slice
import space.kscience.kmath.structures.toList import space.kscience.kmath.structures.toList
@ -34,6 +35,8 @@ fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) {
val s3: Buffer<Double> = s1.zip(s2) { l, r -> l + r } //s1 + s2 val s3: Buffer<Double> = s1.zip(s2) { l, r -> l + r } //s1 + s2
val s4 = ln(s3) val s4 = ln(s3)
val kmTest = ksComparisonStatistic(s1, s2)
Plotly.page { Plotly.page {
h1 { +"This is my plot" } h1 { +"This is my plot" }
plotSeries(s1) plotSeries(s1)

View File

@ -79,11 +79,19 @@ public class BufferExpanded<T>(
/** /**
* Zero-copy select a slice inside the original buffer * Zero-copy select a slice inside the original buffer
*/ */
public fun <T> Buffer<T>.slice(range: UIntRange): BufferView<T> = BufferSlice( public fun <T> Buffer<T>.slice(range: UIntRange): BufferView<T> = if (this is BufferSlice) {
BufferSlice(
origin,
this.offset + range.first,
(range.last - range.first).toInt() + 1
)
} else {
BufferSlice(
this, this,
range.first, range.first,
(range.last - range.first).toInt() + 1 (range.last - range.first).toInt() + 1
) )
}
/** /**
* Resize original buffer to a given range using given [range], filling additional segments with [defaultValue]. * Resize original buffer to a given range using given [range], filling additional segments with [defaultValue].

View File

@ -5,7 +5,8 @@ import space.kscience.kmath.misc.UnstableKMathAPI
/** /**
* Non-boxing access to primitive [Double] * Non-boxing access to primitive [Double]
*/ */
@OptIn(UnstableKMathAPI::class)
@UnstableKMathAPI
public fun Buffer<Double>.getDouble(index: Int): Double = if (this is BufferView) { public fun Buffer<Double>.getDouble(index: Int): Double = if (this is BufferView) {
val originIndex = originIndex(index) val originIndex = originIndex(index)
if( originIndex>=0) { if( originIndex>=0) {
@ -22,7 +23,7 @@ public fun Buffer<Double>.getDouble(index: Int): Double = if (this is BufferView
/** /**
* Non-boxing access to primitive [Int] * Non-boxing access to primitive [Int]
*/ */
@OptIn(UnstableKMathAPI::class) @UnstableKMathAPI
public fun Buffer<Int>.getInt(index: Int): Int = if (this is BufferView) { public fun Buffer<Int>.getInt(index: Int): Int = if (this is BufferView) {
val originIndex = originIndex(index) val originIndex = originIndex(index)
if( originIndex>=0) { if( originIndex>=0) {

View File

@ -1,5 +1,6 @@
package space.kscience.kmath.stat package space.kscience.kmath.stat
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferFactory
@ -20,12 +21,20 @@ public fun <T : Comparable<T>> StatisticalAlgebra<T, *, *>.ecdf(buffer: Buffer<T
} }
/** /**
* Resulting value of kolmogorov-smirnov two-sample statistic
*/
@UnstableKMathAPI
public data class KMComparisonResult<T : Comparable<T>>(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 * 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 <T : Comparable<T>, A, BA : BufferAlgebra<T, A>> StatisticalAlgebra<T, A, BA>.kolmogorovSmirnovTest( @UnstableKMathAPI
public fun <T : Comparable<T>, A, BA : BufferAlgebra<T, A>> StatisticalAlgebra<T, A, BA>.ksComparisonStatistic(
x: Buffer<T>, x: Buffer<T>,
y: Buffer<T>, y: Buffer<T>,
): T where A : Group<T>, A : NumericAlgebra<T> = elementAlgebra.invoke { ): KMComparisonResult<T> where A : Group<T>, A : NumericAlgebra<T> = elementAlgebra.invoke {
// Copy and sort the sample arrays // Copy and sort the sample arrays
val sx = x.sorted() val sx = x.sorted()
val sy = y.sorted() val sy = y.sorted()
@ -41,19 +50,19 @@ public fun <T : Comparable<T>, A, BA : BufferAlgebra<T, A>> StatisticalAlgebra<T
do { do {
val z = if (sx[rankX] <= sy[rankY]) sx[rankX] else sy[rankY] val z = if (sx[rankX] <= sy[rankY]) sx[rankX] else sy[rankY]
while (rankX < n && sx[rankX].compareTo(z) == 0) { while (rankX < n && sx[rankX].compareTo(z) == 0) {
rankX += 1; rankX += 1
curD += number(m); curD += number(m)
} }
while (rankY < m && sy[rankY].compareTo(z) == 0) { while (rankY < m && sy[rankY].compareTo(z) == 0) {
rankY += 1; rankY += 1
curD -= number(n); curD -= number(n)
} }
when { when {
curD > supD -> supD = curD curD > supD -> supD = curD
-curD > supD -> supD = -curD -curD > supD -> supD = -curD
} }
} while (rankX < n && rankY < m); } while (rankX < n && rankY < m)
return supD; return KMComparisonResult(n, m, supD)
} }