Merge branch 'dev' into artdegt

This commit is contained in:
Alexander Nozik 2023-03-22 12:30:28 +03:00
commit 6d219341f9
15 changed files with 269 additions and 98 deletions

View File

@ -15,7 +15,7 @@ jobs:
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
steps: steps:
- uses: actions/checkout@v3.0.0 - uses: actions/checkout@v3.0.0
- uses: actions/setup-java@v3.0.0 - uses: actions/setup-java@v3.10.0
with: with:
java-version: 11 java-version: 11
distribution: liberica distribution: liberica
@ -26,26 +26,24 @@ jobs:
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: | restore-keys: |
${{ runner.os }}-gradle- ${{ runner.os }}-gradle-
- uses: gradle/wrapper-validation-action@v1.0.4
- name: Publish Windows Artifacts - name: Publish Windows Artifacts
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
uses: gradle/gradle-build-action@v2.1.5 uses: gradle/gradle-build-action@v2.4.0
with: with:
arguments: | arguments: |
releaseAll publishAllPublicationsToSpaceRepository
-Ppublishing.enabled=true -Ppublishing.targets=all
-Ppublishing.sonatype=false
-Ppublishing.space.user=${{ secrets.SPACE_APP_ID }} -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }}
-Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }} -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }}
- name: Publish Mac Artifacts - name: Publish Mac Artifacts
if: matrix.os == 'macOS-latest' if: matrix.os == 'macOS-latest'
uses: gradle/gradle-build-action@v2.1.5 uses: gradle/gradle-build-action@v2.4.0
with: with:
arguments: | arguments: |
releaseMacosX64 publishMacosX64PublicationToSpaceRepository
releaseIosArm64 publishIosX64PublicationToSpaceRepository
releaseIosX64 publishIosArm64PublicationToSpaceRepository
-Ppublishing.enabled=true publishIosSimulatorArm64PublicationToSpaceRepository
-Ppublishing.sonatype=false -Ppublishing.targets=all
-Ppublishing.space.user=${{ secrets.SPACE_APP_ID }} -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }}
-Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }} -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }}

3
.gitignore vendored
View File

@ -18,4 +18,5 @@ out/
!/.idea/copyright/ !/.idea/copyright/
!/.idea/scopes/ !/.idea/scopes/
/kotlin-js-store/yarn.lock /gradle/yarn.lock

View File

@ -2,6 +2,7 @@
## [Unreleased] ## [Unreleased]
### Added ### Added
- Generic builders for `BufferND` and `MutableBufferND`
- `NamedMatrix` - matrix with symbol-based indexing - `NamedMatrix` - matrix with symbol-based indexing
- `Expression` with default arguments - `Expression` with default arguments
- Type-aliases for numbers like `Float64` - Type-aliases for numbers like `Float64`

View File

@ -1,3 +1,5 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
plugins { plugins {
kotlin("jvm") kotlin("jvm")
} }
@ -33,6 +35,8 @@ dependencies {
implementation(project(":kmath-multik")) implementation(project(":kmath-multik"))
implementation("org.jetbrains.kotlinx:multik-default:$multikVersion") implementation("org.jetbrains.kotlinx:multik-default:$multikVersion")
//datetime
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
implementation("org.nd4j:nd4j-native:1.0.0-beta7") implementation("org.nd4j:nd4j-native:1.0.0-beta7")
@ -46,25 +50,24 @@ dependencies {
// } else // } else
implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7")
// multik implementation
implementation("org.jetbrains.kotlinx:multik-default:0.1.0")
implementation("org.slf4j:slf4j-simple:1.7.32") implementation("org.slf4j:slf4j-simple:1.7.32")
// plotting // plotting
implementation("space.kscience:plotlykt-server:0.5.0") implementation("space.kscience:plotlykt-server:0.5.0")
} }
kotlin.sourceSets.all { kotlin {
jvmToolchain(11)
sourceSets.all {
with(languageSettings) { with(languageSettings) {
optIn("kotlin.contracts.ExperimentalContracts") optIn("kotlin.contracts.ExperimentalContracts")
optIn("kotlin.ExperimentalUnsignedTypes") optIn("kotlin.ExperimentalUnsignedTypes")
optIn("space.kscience.kmath.misc.UnstableKMathAPI") optIn("space.kscience.kmath.misc.UnstableKMathAPI")
} }
}
} }
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> { tasks.withType<KotlinJvmCompile> {
kotlinOptions { kotlinOptions {
jvmTarget = "11"
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" + "-Xlambdas=indy" freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" + "-Xlambdas=indy"
} }
} }

View File

@ -0,0 +1,19 @@
/*
* Copyright 2018-2023 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.stat
import kotlinx.datetime.Instant
import space.kscience.kmath.operations.algebra
import space.kscience.kmath.operations.bufferAlgebra
import space.kscience.kmath.series.MonotonicSeriesAlgebra
import space.kscience.kmath.series.SeriesAlgebra
import kotlin.time.Duration
fun SeriesAlgebra.Companion.time(zero: Instant, step: Duration) = MonotonicSeriesAlgebra(
bufferAlgebra = Double.algebra.bufferAlgebra,
offsetToLabel = { zero + step * it },
labelToOffset = { (it - zero) / step }
)

View File

@ -9,7 +9,7 @@ kotlin.native.ignoreDisabledTargets=true
org.gradle.configureondemand=true org.gradle.configureondemand=true
org.gradle.jvmargs=-Xmx4096m org.gradle.jvmargs=-Xmx4096m
toolsVersion=0.14.2-kotlin-1.8.10 toolsVersion=0.14.5-kotlin-1.8.20-RC
org.gradle.parallel=true org.gradle.parallel=true

View File

@ -7,7 +7,9 @@ package space.kscience.kmath.nd
import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory
import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableBuffer
import space.kscience.kmath.structures.MutableBufferFactory
/** /**
* Represents [StructureND] over [Buffer]. * Represents [StructureND] over [Buffer].
@ -29,6 +31,18 @@ public open class BufferND<out T>(
override fun toString(): String = StructureND.toString(this) override fun toString(): String = StructureND.toString(this)
} }
/**
* Create a generic [BufferND] using provided [initializer]
*/
public fun <T> BufferND(
shape: ShapeND,
bufferFactory: BufferFactory<T> = BufferFactory.boxing(),
initializer: (IntArray) -> T,
): BufferND<T> {
val strides = Strides(shape)
return BufferND(strides, bufferFactory(strides.linearSize) { initializer(strides.index(it)) })
}
///** ///**
// * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferND] // * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferND]
// */ // */
@ -67,6 +81,18 @@ public open class MutableBufferND<T>(
} }
} }
/**
* Create a generic [BufferND] using provided [initializer]
*/
public fun <T> MutableBufferND(
shape: ShapeND,
bufferFactory: MutableBufferFactory<T> = MutableBufferFactory.boxing(),
initializer: (IntArray) -> T,
): MutableBufferND<T> {
val strides = Strides(shape)
return MutableBufferND(strides, bufferFactory(strides.linearSize) { initializer(strides.index(it)) })
}
///** ///**
// * Transform structure to a new structure using provided [MutableBufferFactory] and optimizing if argument is [MutableBufferND] // * Transform structure to a new structure using provided [MutableBufferFactory] and optimizing if argument is [MutableBufferND]
// */ // */

View File

@ -8,6 +8,7 @@
package space.kscience.kmath.coroutines package space.kscience.kmath.coroutines
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.channels.produce import kotlinx.coroutines.channels.produce
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
@ -57,7 +58,7 @@ public suspend fun <T> AsyncFlow<T>.collect(concurrency: Int, collector: FlowCol
coroutineScope { coroutineScope {
//Starting up to N deferred coroutines ahead of time //Starting up to N deferred coroutines ahead of time
val channel = produce(capacity = concurrency - 1) { val channel: ReceiveChannel<LazyDeferred<T>> = produce(capacity = concurrency - 1) {
deferredFlow.collect { value -> deferredFlow.collect { value ->
value.start(this@coroutineScope) value.start(this@coroutineScope)
send(value) send(value)

View File

@ -9,7 +9,6 @@ import space.kscience.kmath.operations.mapToBuffer
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.asBuffer import space.kscience.kmath.structures.asBuffer
import kotlin.jvm.Synchronized
import kotlin.math.ulp import kotlin.math.ulp
import kotlin.native.concurrent.ThreadLocal import kotlin.native.concurrent.ThreadLocal
@ -57,7 +56,6 @@ public object GaussLegendreRuleFactory : GaussIntegratorRuleFactory {
private val cache = HashMap<Int, Pair<Buffer<Double>, Buffer<Double>>>() private val cache = HashMap<Int, Pair<Buffer<Double>, Buffer<Double>>>()
@Synchronized
private fun getOrBuildRule(numPoints: Int): Pair<Buffer<Double>, Buffer<Double>> = private fun getOrBuildRule(numPoints: Int): Pair<Buffer<Double>, Buffer<Double>> =
cache.getOrPut(numPoints) { buildRule(numPoints) } cache.getOrPut(numPoints) { buildRule(numPoints) }

View File

@ -78,8 +78,11 @@ public object Euclidean3DSpace : GeometrySpace<DoubleVector3D>, ScaleOperations<
} }
} }
public fun vector(x: Double, y: Double, z: Double): DoubleVector3D =
Vector3DImpl(x, y, z)
public fun vector(x: Number, y: Number, z: Number): DoubleVector3D = public fun vector(x: Number, y: Number, z: Number): DoubleVector3D =
Vector3DImpl(x.toDouble(), y.toDouble(), z.toDouble()) vector(x.toDouble(), y.toDouble(), z.toDouble())
override val zero: DoubleVector3D by lazy { vector(0.0, 0.0, 0.0) } override val zero: DoubleVector3D by lazy { vector(0.0, 0.0, 0.0) }
@ -100,6 +103,46 @@ public object Euclidean3DSpace : GeometrySpace<DoubleVector3D>, ScaleOperations<
override fun DoubleVector3D.dot(other: DoubleVector3D): Double = override fun DoubleVector3D.dot(other: DoubleVector3D): Double =
x * other.x + y * other.y + z * other.z x * other.x + y * other.y + z * other.z
private fun leviCivita(i: Int, j: Int, k: Int): Int = when {
// even permutation
i == 0 && j == 1 && k == 2 -> 1
i == 1 && j == 2 && k == 0 -> 1
i == 2 && j == 0 && k == 1 -> 1
// odd permutations
i == 2 && j == 1 && k == 0 -> -1
i == 0 && j == 2 && k == 1 -> -1
i == 1 && j == 0 && k == 2 -> -1
else -> 0
}
/**
* Compute vector product of [first] and [second]. The basis assumed to be right-handed.
*/
public fun vectorProduct(
first: DoubleVector3D,
second: DoubleVector3D,
): DoubleVector3D {
var x = 0.0
var y = 0.0
var z = 0.0
for (j in (0..2)) {
for (k in (0..2)) {
x += leviCivita(0, j, k) * first[j] * second[k]
y += leviCivita(1, j, k) * first[j] * second[k]
z += leviCivita(2, j, k) * first[j] * second[k]
}
}
return vector(x, y, z)
}
/**
* Vector product with right basis
*/
public infix fun DoubleVector3D.cross(other: DoubleVector3D): Vector3D<Double> = vectorProduct(this, other)
public val xAxis: DoubleVector3D = vector(1.0, 0.0, 0.0) public val xAxis: DoubleVector3D = vector(1.0, 0.0, 0.0)
public val yAxis: DoubleVector3D = vector(0.0, 1.0, 0.0) public val yAxis: DoubleVector3D = vector(0.0, 1.0, 0.0)
public val zAxis: DoubleVector3D = vector(0.0, 0.0, 1.0) public val zAxis: DoubleVector3D = vector(0.0, 0.0, 1.0)

View File

@ -57,8 +57,7 @@ internal class Euclidean3DSpaceTest {
} }
@Test @Test
fun add() { fun add() = with(Euclidean3DSpace) {
with(Euclidean3DSpace) {
assertVectorEquals( assertVectorEquals(
vector(1.0, -2.0, 0.001), vector(1.0, -2.0, 0.001),
vector(1.0, -2.0, 0.001) + zero vector(1.0, -2.0, 0.001) + zero
@ -68,12 +67,28 @@ internal class Euclidean3DSpaceTest {
vector(1.0, 2.0, 3.0) + vector(7.0, -5.0, 0.001) vector(1.0, 2.0, 3.0) + vector(7.0, -5.0, 0.001)
) )
} }
@Test
fun multiply() = with(Euclidean3DSpace) {
assertVectorEquals(vector(2.0, -4.0, 0.0), vector(1.0, -2.0, 0.0) * 2)
} }
@Test @Test
fun multiply() { fun vectorProduct() = with(Euclidean3DSpace) {
with(Euclidean3DSpace) { assertVectorEquals(zAxis, vectorProduct(xAxis, yAxis))
assertVectorEquals(vector(2.0, -4.0, 0.0), vector(1.0, -2.0, 0.0) * 2) assertVectorEquals(zAxis, xAxis cross yAxis)
assertVectorEquals(-zAxis, vectorProduct(yAxis, xAxis))
} }
@Test
fun doubleVectorProduct() = with(Euclidean3DSpace) {
val a = vector(1, 2, -3)
val b = vector(-1, 0, 1)
val c = vector(4, 5, 6)
val res = a cross (b cross c)
val expected = b * (a dot c) - c * (a dot b)
assertVectorEquals(expected, res)
} }
} }

View File

@ -0,0 +1,47 @@
/*
* Copyright 2018-2023 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.series
import space.kscience.kmath.operations.BufferAlgebra
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.structures.Buffer
import kotlin.math.ceil
import kotlin.math.floor
/**
* A [SeriesAlgebra] with reverse label to index transformation.
*
* @param [labelToOffset] returns floating point number that is used for index resolution.
*/
public class MonotonicSeriesAlgebra<T, out A : Ring<T>, out BA : BufferAlgebra<T, A>, L : Comparable<L>>(
bufferAlgebra: BA,
offsetToLabel: (Int) -> L,
private val labelToOffset: (L) -> Double,
) : SeriesAlgebra<T, A, BA, L>(bufferAlgebra, offsetToLabel) {
public val Buffer<T>.labelRange: ClosedRange<L> get() = offsetToLabel(startOffset)..offsetToLabel(startOffset + size)
/**
* An offset of the given [label] rounded down
*/
public fun floorOffset(label: L): Int = floor(labelToOffset(label)).toInt()
/**
* An offset of the given [label] rounded up
*/
public fun ceilOffset(label: L): Int = ceil(labelToOffset(label)).toInt()
/**
* Get value by label (rounded down) or return null if the value is outside series boundaries.
*/
public fun Buffer<T>.getByLabelOrNull(label: L): T? = getByOffsetOrNull(floorOffset(label))
/**
* Get value by label (rounded down) or throw [IndexOutOfBoundsException] if the value is outside series boundaries.
*/
public fun Buffer<T>.getByLabel(label: L): T = getByLabelOrNull(label)
?: throw IndexOutOfBoundsException("Label $label is not in $labelRange")
}

View File

@ -6,6 +6,7 @@ import space.kscience.kmath.operations.RingOps
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.BufferView import space.kscience.kmath.structures.BufferView
import space.kscience.kmath.structures.getOrNull
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -23,7 +24,9 @@ internal operator fun IntRange.contains(other: IntRange): Boolean = (other.first
//TODO add permutation sort //TODO add permutation sort
//TODO check rank statistics //TODO check rank statistics
/**
* A [Buffer] with an offset relative to the [SeriesAlgebra] zero.
*/
public interface Series<T> : Buffer<T> { public interface Series<T> : Buffer<T> {
public val origin: Buffer<T> public val origin: Buffer<T>
@ -33,8 +36,6 @@ 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
/** /**
* 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
*/ */
@ -55,59 +56,75 @@ private class SeriesImpl<T>(
/** /**
* A scope to operation on series * A scope to operation on series
*/ */
public class SeriesAlgebra<T, out A : Ring<T>, out BA : BufferAlgebra<T, A>, L>( public open class SeriesAlgebra<T, out A : Ring<T>, out BA : BufferAlgebra<T, A>, L>(
override val bufferAlgebra: BA, override val bufferAlgebra: BA,
private val labelResolver: (Int) -> L, public val offsetToLabel: (Int) -> L,
) : RingOps<Buffer<T>>, StatisticalAlgebra<T, A, BA> { ) : RingOps<Buffer<T>>, StatisticalAlgebra<T, A, BA> {
public val Buffer<T>.indices: IntRange /**
* A range of valid offset indices. In general, does not start with zero.
*/
public val Buffer<T>.offsetIndices: IntRange
get() = if (this is Series) { get() = if (this is Series) {
absoluteIndices position until position + size
} else { } else {
0 until size 0 until size
} }
/** /**
* Get the value by absolute index in the series algebra or return null if index is out of range * Get the value by absolute offset in the series algebra or return null if index is out of range
*/ */
public fun Buffer<T>.getAbsoluteOrNull(index: Int): T? = when { public fun Buffer<T>.getByOffsetOrNull(index: Int): T? = when {
index !in indices -> null index !in offsetIndices -> null
this is Series -> origin[index - position] this is Series -> origin.getOrNull(index - position)
else -> get(index) else -> getOrNull(index)
} }
/** /**
* Get the value by absolute index in the series algebra or throw [IndexOutOfBoundsException] if index is out of range * Get the value by absolute index in the series algebra or throw [IndexOutOfBoundsException] if index is out of range
*/ */
public fun Buffer<T>.getAbsolute(index: Int): T = public fun Buffer<T>.getByOffset(index: Int): T =
getAbsoluteOrNull(index) ?: throw IndexOutOfBoundsException("Index $index is not in $indices") getByOffsetOrNull(index) ?: throw IndexOutOfBoundsException("Index $index is not in $offsetIndices")
/** /**
* Create an offset series with index starting point at [index] * Zero-copy move [Buffer] or [Series] to given [position] ignoring series offset if it is present.
*/ */
public fun Buffer<T>.moveTo(index: Int): Series<T> = if (this is Series) { public fun Buffer<T>.moveTo(position: Int): Series<T> = if (this is Series) {
SeriesImpl(origin, index, size) SeriesImpl(origin, position, size)
} else { } else {
SeriesImpl(this, index, size) SeriesImpl(this, position, size)
} }
public val Buffer<T>.offset: Int get() = if (this is Series) position else 0 /**
* Zero-copy move [Buffer] or [Series] by given [offset]. If it is [Series], sum intrinsic series position and the [offset].
*/
public fun Buffer<T>.moveBy(offset: Int): Series<T> = if (this is Series) {
SeriesImpl(origin, position + offset, size)
} else {
SeriesImpl(this, offset, size)
}
/** /**
* Build a new series * An offset of the buffer start relative to [SeriesAlgebra] zero offset
*/ */
public fun series(size: Int, fromIndex: Int = 0, block: A.(label: L) -> T): Series<T> { public val Buffer<T>.startOffset: Int get() = if (this is Series) position else 0
public val Buffer<T>.startLabel: L get() = offsetToLabel(startOffset)
/**
* Build a new series positioned at [startOffset].
*/
public fun series(size: Int, startOffset: Int = 0, block: A.(label: L) -> T): Series<T> {
return elementAlgebra.bufferFactory(size) { return elementAlgebra.bufferFactory(size) {
val index = it + fromIndex val index = it + startOffset
elementAlgebra.block(labelResolver(index)) elementAlgebra.block(offsetToLabel(index))
}.moveTo(fromIndex) }.moveTo(startOffset)
} }
/** /**
* 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() = offsetIndices.map(offsetToLabel)
/** /**
* Try to resolve element by label and return null if element with a given label is not found * Try to resolve element by label and return null if element with a given label is not found
@ -115,7 +132,7 @@ public class SeriesAlgebra<T, out A : Ring<T>, out BA : BufferAlgebra<T, A>, L>(
public operator fun Buffer<T>.get(label: L): T? { public operator fun Buffer<T>.get(label: L): T? {
val index = labels.indexOf(label) val index = labels.indexOf(label)
if (index == -1) return null if (index == -1) return null
return getAbsolute(index + offset) return getByOffset(index + startOffset)
} }
/** /**
@ -123,9 +140,9 @@ public class SeriesAlgebra<T, out A : Ring<T>, out BA : BufferAlgebra<T, A>, L>(
*/ */
public inline fun Buffer<T>.map(crossinline transform: A.(T) -> T): Series<T> { public inline fun Buffer<T>.map(crossinline transform: A.(T) -> T): Series<T> {
val buf = elementAlgebra.bufferFactory(size) { val buf = elementAlgebra.bufferFactory(size) {
elementAlgebra.transform(getAbsolute(it)) elementAlgebra.transform(getByOffset(it))
} }
return buf.moveTo(indices.first) return buf.moveTo(offsetIndices.first)
} }
/** /**
@ -134,22 +151,22 @@ public class SeriesAlgebra<T, out A : Ring<T>, out BA : BufferAlgebra<T, A>, L>(
public inline fun Buffer<T>.mapWithLabel(crossinline transform: A.(arg: T, label: L) -> T): Series<T> { public inline fun Buffer<T>.mapWithLabel(crossinline transform: A.(arg: T, label: L) -> T): Series<T> {
val labels = labels val labels = labels
val buf = elementAlgebra.bufferFactory(size) { val buf = elementAlgebra.bufferFactory(size) {
elementAlgebra.transform(getAbsolute(it), labels[it]) elementAlgebra.transform(getByOffset(it), labels[it])
} }
return buf.moveTo(indices.first) return buf.moveTo(offsetIndices.first)
} }
public inline fun <R> Buffer<T>.fold(initial: R, operation: A.(acc: R, T) -> R): R { public inline fun <R> Buffer<T>.fold(initial: R, operation: A.(acc: R, T) -> R): R {
var accumulator = initial var accumulator = initial
for (index in this.indices) accumulator = elementAlgebra.operation(accumulator, getAbsolute(index)) for (index in this.offsetIndices) accumulator = elementAlgebra.operation(accumulator, getByOffset(index))
return accumulator return accumulator
} }
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
for (index in this.indices) accumulator = for (index in this.offsetIndices) accumulator =
elementAlgebra.operation(accumulator, getAbsolute(index), labels[index]) elementAlgebra.operation(accumulator, getByOffset(index), labels[index])
return accumulator return accumulator
} }
@ -160,11 +177,11 @@ public class SeriesAlgebra<T, out A : Ring<T>, out BA : BufferAlgebra<T, A>, L>(
other: Buffer<T>, other: Buffer<T>,
crossinline operation: A.(left: T, right: T) -> T, crossinline operation: A.(left: T, right: T) -> T,
): Series<T> { ): Series<T> {
val newRange = indices.intersect(other.indices) val newRange = offsetIndices.intersect(other.offsetIndices)
return elementAlgebra.bufferFactory(newRange.size) { return elementAlgebra.bufferFactory(newRange.size) {
elementAlgebra.operation( elementAlgebra.operation(
getAbsolute(it), getByOffset(it),
other.getAbsolute(it) other.getByOffset(it)
) )
}.moveTo(newRange.first) }.moveTo(newRange.first)
} }
@ -174,6 +191,8 @@ public class SeriesAlgebra<T, out A : Ring<T>, out BA : BufferAlgebra<T, A>, L>(
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 companion object
} }
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> {

View File

@ -12,32 +12,32 @@ import space.kscience.kmath.structures.Buffer
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.sin( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.sin(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : TrigonometricOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : TrigonometricOperations<Buffer<T>> =
bufferAlgebra.sin(arg).moveTo(arg.offset) bufferAlgebra.sin(arg).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.cos( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.cos(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : TrigonometricOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : TrigonometricOperations<Buffer<T>> =
bufferAlgebra.cos(arg).moveTo(arg.offset) bufferAlgebra.cos(arg).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.tan( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.tan(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : TrigonometricOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : TrigonometricOperations<Buffer<T>> =
bufferAlgebra.tan(arg).moveTo(arg.offset) bufferAlgebra.tan(arg).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.asin( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.asin(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : TrigonometricOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : TrigonometricOperations<Buffer<T>> =
bufferAlgebra.asin(arg).moveTo(arg.offset) bufferAlgebra.asin(arg).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.acos( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.acos(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : TrigonometricOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : TrigonometricOperations<Buffer<T>> =
bufferAlgebra.acos(arg).moveTo(arg.offset) bufferAlgebra.acos(arg).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.atan( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.atan(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : TrigonometricOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : TrigonometricOperations<Buffer<T>> =
bufferAlgebra.atan(arg).moveTo(arg.offset) bufferAlgebra.atan(arg).moveTo(arg.startOffset)
//exponential //exponential
@ -45,42 +45,42 @@ public fun <T, BA> SeriesAlgebra<T, *, BA, *>.atan(
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.exp( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.exp(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> =
bufferAlgebra.exp(arg).moveTo(arg.offset) bufferAlgebra.exp(arg).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.ln( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.ln(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> =
bufferAlgebra.ln(arg).moveTo(arg.offset) bufferAlgebra.ln(arg).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.sinh( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.sinh(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> =
bufferAlgebra.sinh(arg).moveTo(arg.offset) bufferAlgebra.sinh(arg).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.cosh( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.cosh(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> =
bufferAlgebra.cosh(arg).moveTo(arg.offset) bufferAlgebra.cosh(arg).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.tanh( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.tanh(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> =
bufferAlgebra.tanh(arg).moveTo(arg.offset) bufferAlgebra.tanh(arg).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.asinh( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.asinh(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> =
bufferAlgebra.asinh(arg).moveTo(arg.offset) bufferAlgebra.asinh(arg).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.acosh( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.acosh(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> =
bufferAlgebra.acosh(arg).moveTo(arg.offset) bufferAlgebra.acosh(arg).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.atanh( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.atanh(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : ExponentialOperations<Buffer<T>> =
bufferAlgebra.atanh(arg).moveTo(arg.offset) bufferAlgebra.atanh(arg).moveTo(arg.startOffset)
//power //power
@ -89,9 +89,9 @@ public fun <T, BA> SeriesAlgebra<T, *, BA, *>.power(
arg: Buffer<T>, arg: Buffer<T>,
pow: Number, pow: Number,
): Series<T> where BA : BufferAlgebra<T, *>, BA : PowerOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : PowerOperations<Buffer<T>> =
bufferAlgebra.power(arg, pow).moveTo(arg.offset) bufferAlgebra.power(arg, pow).moveTo(arg.startOffset)
public fun <T, BA> SeriesAlgebra<T, *, BA, *>.sqrt( public fun <T, BA> SeriesAlgebra<T, *, BA, *>.sqrt(
arg: Buffer<T>, arg: Buffer<T>,
): Series<T> where BA : BufferAlgebra<T, *>, BA : PowerOperations<Buffer<T>> = ): Series<T> where BA : BufferAlgebra<T, *>, BA : PowerOperations<Buffer<T>> =
bufferAlgebra.sqrt(arg).moveTo(arg.offset) bufferAlgebra.sqrt(arg).moveTo(arg.startOffset)

View File

@ -15,7 +15,7 @@ kscience{
} }
readme { readme {
description = "Path and trajectory optimization" description = "Path and trajectory optimization (to be moved to a separate project)"
maturity = space.kscience.gradle.Maturity.PROTOTYPE maturity = space.kscience.gradle.Maturity.DEPRECATED
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
} }