shiftOp and diff in SeriesAlgebra

This commit is contained in:
mrFendel 2023-04-06 03:17:01 +03:00
parent db61f71440
commit 1d7f4ed538

View File

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