diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt index 3cd2212f6..bdd74c4fe 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt @@ -3,16 +3,21 @@ package space.kscience.kmath.series import space.kscience.kmath.operations.BufferAlgebra import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.RingOps +import space.kscience.kmath.operations.reduce import space.kscience.kmath.stat.StatisticalAlgebra import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferView import kotlin.math.max import kotlin.math.min + +// TODO: check if ranges are intersected @PublishedApi internal fun IntRange.intersect(other: IntRange): IntRange = max(first, other.first)..min(last, other.last) + @PublishedApi internal val IntRange.size: Int get() = last - first + 1 @@ -33,11 +38,14 @@ public interface Series : Buffer { public val position: Int } + + public val Series.absoluteIndices: IntRange get() = position until position + size /** * A [BufferView] with index offset (both positive and negative) and possible size change */ + private class SeriesImpl( override val origin: Buffer, override val position: Int, @@ -107,6 +115,8 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( * Get a label buffer for given buffer. */ public val Buffer.labels: List get() = indices.map(labelResolver) + // TODO: there can be troubles with label consistency after moving position argument + // TODO: so offset should be reflected in the labelResolver also /** @@ -145,6 +155,17 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( return accumulator } + // TODO: add fold with recorded accumulation +// public inline fun Buffer.traceFold(initial: R, operation: A.(acc: R, T) -> R): Buffer { +// var tempBuffer = elementAlgebra.bufferFactory(this.size) {i -> getAbsolute(i)} +// var accumulator = initial +// for (index in this.indices) { +// accumulator = elementAlgebra.operation(accumulator, getAbsolute(index)) +// tempBuffer.set(index, accumulator) +// } +// return elementAlgebra.bufferFactory(this.size) {i -> tempBuffer.getAbsolute(i)} +// } + public inline fun Buffer.foldWithLabel(initial: R, operation: A.(acc: R, arg: T, label: L) -> R): R { val labels = labels var accumulator = initial @@ -154,7 +175,7 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( } /** - * Zip two buffers in the range whe they overlap + * Zip two buffers in the range where they overlap */ public inline fun Buffer.zip( other: Buffer, @@ -169,11 +190,24 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( }.moveTo(newRange.first) } + /** + * Zip buffer with itself, but shifted + * */ + public inline fun Buffer.shiftOp( + shift: Int = 1, + crossinline operation: A.(left: T, right: T) -> T + ): Buffer { + val shifted = this.moveTo(this.offset+shift) + return zip(shifted, operation) + } + override fun Buffer.unaryMinus(): Buffer = map { -it } override fun add(left: Buffer, right: Buffer): Series = left.zip(right) { l, r -> l + r } override fun multiply(left: Buffer, right: Buffer): Buffer = left.zip(right) { l, r -> l * r } + + public inline fun Buffer.diff(): Buffer = this.shiftOp {l, r -> r - l} } public fun , BA : BufferAlgebra, L> BA.seriesAlgebra(labels: Iterable): SeriesAlgebra {