forked from kscience/kmath
Explicit mutability for StructureND builders
This commit is contained in:
parent
875e32679b
commit
cdfddb7551
@ -3,6 +3,7 @@
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
- Explicit `mutableStructureND` builders for mutable stucures
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -3,8 +3,6 @@ plugins {
|
|||||||
`version-catalog`
|
`version-catalog`
|
||||||
}
|
}
|
||||||
|
|
||||||
java.targetCompatibility = JavaVersion.VERSION_11
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
maven("https://repo.kotlin.link")
|
maven("https://repo.kotlin.link")
|
||||||
@ -26,6 +24,11 @@ dependencies {
|
|||||||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.+")
|
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.+")
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin.sourceSets.all {
|
kotlin{
|
||||||
|
jvmToolchain{
|
||||||
|
languageVersion.set(JavaLanguageVersion.of(11))
|
||||||
|
}
|
||||||
|
sourceSets.all {
|
||||||
languageSettings.optIn("kotlin.OptIn")
|
languageSettings.optIn("kotlin.OptIn")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -52,7 +52,7 @@ dependencies {
|
|||||||
|
|
||||||
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.3-dev-1")
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
@ -8,14 +8,15 @@ package space.kscience.kmath.operations
|
|||||||
import space.kscience.kmath.commons.linear.CMLinearSpace
|
import space.kscience.kmath.commons.linear.CMLinearSpace
|
||||||
import space.kscience.kmath.linear.matrix
|
import space.kscience.kmath.linear.matrix
|
||||||
import space.kscience.kmath.nd.DoubleBufferND
|
import space.kscience.kmath.nd.DoubleBufferND
|
||||||
import space.kscience.kmath.nd.ShapeND
|
|
||||||
import space.kscience.kmath.nd.Structure2D
|
import space.kscience.kmath.nd.Structure2D
|
||||||
|
import space.kscience.kmath.nd.mutableStructureND
|
||||||
import space.kscience.kmath.nd.ndAlgebra
|
import space.kscience.kmath.nd.ndAlgebra
|
||||||
import space.kscience.kmath.viktor.ViktorStructureND
|
|
||||||
import space.kscience.kmath.viktor.viktorAlgebra
|
import space.kscience.kmath.viktor.viktorAlgebra
|
||||||
|
import kotlin.collections.component1
|
||||||
|
import kotlin.collections.component2
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val viktorStructure: ViktorStructureND = DoubleField.viktorAlgebra.structureND(ShapeND(2, 2)) { (i, j) ->
|
val viktorStructure = DoubleField.viktorAlgebra.mutableStructureND(2, 2) { (i, j) ->
|
||||||
if (i == j) 2.0 else 0.0
|
if (i == j) 2.0 else 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,10 @@ import space.kscience.kmath.structures.slice
|
|||||||
import space.kscience.plotly.*
|
import space.kscience.plotly.*
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
|
|
||||||
fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) {
|
fun Double.Companion.seriesAlgebra() = Double.algebra.bufferAlgebra.seriesAlgebra()
|
||||||
|
|
||||||
|
|
||||||
|
fun main() = with(Double.seriesAlgebra()) {
|
||||||
|
|
||||||
|
|
||||||
fun Plot.plotSeries(name: String, buffer: Buffer<Double>) {
|
fun Plot.plotSeries(name: String, buffer: Buffer<Double>) {
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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.structures.Buffer
|
||||||
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
|
import space.kscience.kmath.structures.asBuffer
|
||||||
|
import space.kscience.kmath.structures.toDoubleArray
|
||||||
|
import space.kscience.plotly.*
|
||||||
|
import space.kscience.plotly.models.Scatter
|
||||||
|
import space.kscience.plotly.models.ScatterMode
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
fun main(): Unit = with(Double.seriesAlgebra()) {
|
||||||
|
|
||||||
|
val random = Random(1234)
|
||||||
|
|
||||||
|
val arrayOfRandoms = DoubleArray(20) { random.nextDouble() }
|
||||||
|
|
||||||
|
val series1: DoubleBuffer = arrayOfRandoms.asBuffer()
|
||||||
|
val series2: Series<Double> = series1.moveBy(3)
|
||||||
|
|
||||||
|
val res = series2 - series1
|
||||||
|
|
||||||
|
println(res.size)
|
||||||
|
|
||||||
|
println(res)
|
||||||
|
|
||||||
|
fun Plot.series(name: String, buffer: Buffer<Double>, block: Scatter.() -> Unit = {}) {
|
||||||
|
scatter {
|
||||||
|
this.name = name
|
||||||
|
x.numbers = buffer.offsetIndices
|
||||||
|
y.doubles = buffer.toDoubleArray()
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Plotly.plot {
|
||||||
|
series("series1", series1)
|
||||||
|
series("series2", series2)
|
||||||
|
series("dif", res){
|
||||||
|
mode = ScatterMode.lines
|
||||||
|
line.color("magenta")
|
||||||
|
}
|
||||||
|
}.makeFile(resourceLocation = ResourceLocation.REMOTE)
|
||||||
|
}
|
@ -52,6 +52,15 @@ class StreamDoubleFieldND(override val shape: ShapeND) : FieldND<Double, DoubleF
|
|||||||
return BufferND(strides, array.asBuffer())
|
return BufferND(strides, array.asBuffer())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun mutableStructureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): MutableBufferND<Double> {
|
||||||
|
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||||
|
val index = strides.index(offset)
|
||||||
|
DoubleField.initializer(index)
|
||||||
|
}.toArray()
|
||||||
|
|
||||||
|
return MutableBufferND(strides, array.asBuffer())
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
override fun StructureND<Double>.map(
|
override fun StructureND<Double>.map(
|
||||||
transform: DoubleField.(Double) -> Double,
|
transform: DoubleField.(Double) -> Double,
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.structures
|
||||||
|
|
||||||
|
import space.kscience.kmath.PerformancePitfall
|
||||||
|
import space.kscience.kmath.nd.*
|
||||||
|
import space.kscience.kmath.operations.algebra
|
||||||
|
|
||||||
|
@OptIn(PerformancePitfall::class)
|
||||||
|
fun main(): Unit = with(Double.algebra.ndAlgebra) {
|
||||||
|
val structure: MutableStructure2D<Double> = mutableStructureND(ShapeND(2, 2)) { (i, j) ->
|
||||||
|
i.toDouble() + j.toDouble()
|
||||||
|
}.as2D()
|
||||||
|
|
||||||
|
structure[0, 1] = -2.0
|
||||||
|
|
||||||
|
val structure2 = mutableStructureND(2, 2) { (i, j) -> i.toDouble() + j.toDouble() }.as2D()
|
||||||
|
|
||||||
|
structure2[0, 1] = 2.0
|
||||||
|
|
||||||
|
|
||||||
|
println(structure + structure2)
|
||||||
|
}
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@ -37,8 +37,8 @@ kotlin.sourceSets {
|
|||||||
filter { it.name.contains("test", true) }
|
filter { it.name.contains("test", true) }
|
||||||
.map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings)
|
.map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings)
|
||||||
.forEach {
|
.forEach {
|
||||||
it.optIn("space.kscience.kmath.misc.PerformancePitfall")
|
it.optIn("space.kscience.kmath.PerformancePitfall")
|
||||||
it.optIn("space.kscience.kmath.misc.UnstableKMathAPI")
|
it.optIn("space.kscience.kmath.UnstableKMathAPI")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,10 +22,16 @@ public interface AlgebraND<T, out C : Algebra<T>>: Algebra<StructureND<T>> {
|
|||||||
*/
|
*/
|
||||||
public val elementAlgebra: C
|
public val elementAlgebra: C
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Produces a new [MutableStructureND] using given initializer function.
|
||||||
|
*/
|
||||||
|
public fun mutableStructureND(shape: ShapeND, initializer: C.(IntArray) -> T): MutableStructureND<T>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produces a new [StructureND] using given initializer function.
|
* Produces a new [StructureND] using given initializer function.
|
||||||
*/
|
*/
|
||||||
public fun structureND(shape: ShapeND, initializer: C.(IntArray) -> T): StructureND<T>
|
public fun structureND(shape: ShapeND, initializer: C.(IntArray) -> T): StructureND<T> =
|
||||||
|
mutableStructureND(shape, initializer)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps elements from one structure to another one by applying [transform] to them.
|
* Maps elements from one structure to another one by applying [transform] to them.
|
||||||
|
@ -16,9 +16,10 @@ public interface BufferAlgebraND<T, out A : Algebra<T>> : AlgebraND<T, A> {
|
|||||||
public val bufferAlgebra: BufferAlgebra<T, A>
|
public val bufferAlgebra: BufferAlgebra<T, A>
|
||||||
override val elementAlgebra: A get() = bufferAlgebra.elementAlgebra
|
override val elementAlgebra: A get() = bufferAlgebra.elementAlgebra
|
||||||
|
|
||||||
override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): BufferND<T> {
|
//TODO change AlgebraND contract to include this
|
||||||
|
override fun mutableStructureND(shape: ShapeND, initializer: A.(IntArray) -> T): MutableBufferND<T> {
|
||||||
val indexer = indexerBuilder(shape)
|
val indexer = indexerBuilder(shape)
|
||||||
return BufferND(
|
return MutableBufferND(
|
||||||
indexer,
|
indexer,
|
||||||
bufferAlgebra.buffer(indexer.linearSize) { offset ->
|
bufferAlgebra.buffer(indexer.linearSize) { offset ->
|
||||||
elementAlgebra.initializer(indexer.index(offset))
|
elementAlgebra.initializer(indexer.index(offset))
|
||||||
@ -26,6 +27,9 @@ public interface BufferAlgebraND<T, out A : Algebra<T>> : AlgebraND<T, A> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): BufferND<T> =
|
||||||
|
mutableStructureND(shape, initializer)
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
public fun StructureND<T>.toBufferND(): BufferND<T> = when (this) {
|
public fun StructureND<T>.toBufferND(): BufferND<T> = when (this) {
|
||||||
is BufferND -> this
|
is BufferND -> this
|
||||||
@ -133,6 +137,11 @@ public fun <T, A : Algebra<T>> BufferAlgebraND<T, A>.structureND(
|
|||||||
initializer: A.(IntArray) -> T,
|
initializer: A.(IntArray) -> T,
|
||||||
): BufferND<T> = structureND(ShapeND(shape), initializer)
|
): BufferND<T> = structureND(ShapeND(shape), initializer)
|
||||||
|
|
||||||
|
public fun <T, A : Algebra<T>> BufferAlgebraND<T, A>.mutableStructureND(
|
||||||
|
vararg shape: Int,
|
||||||
|
initializer: A.(IntArray) -> T,
|
||||||
|
): MutableBufferND<T> = mutableStructureND(ShapeND(shape), initializer)
|
||||||
|
|
||||||
public fun <T, EA : Algebra<T>, A> A.structureND(
|
public fun <T, EA : Algebra<T>, A> A.structureND(
|
||||||
initializer: EA.(IntArray) -> T,
|
initializer: EA.(IntArray) -> T,
|
||||||
): BufferND<T> where A : BufferAlgebraND<T, EA>, A : WithShape = structureND(shape, initializer)
|
): BufferND<T> where A : BufferAlgebraND<T, EA>, A : WithShape = structureND(shape, initializer)
|
||||||
|
@ -74,7 +74,7 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND<Double, DoubleField>(D
|
|||||||
transform: DoubleField.(Double, Double) -> Double,
|
transform: DoubleField.(Double, Double) -> Double,
|
||||||
): BufferND<Double> = zipInline(left.toBufferND(), right.toBufferND()) { l, r -> DoubleField.transform(l, r) }
|
): BufferND<Double> = zipInline(left.toBufferND(), right.toBufferND()) { l, r -> DoubleField.transform(l, r) }
|
||||||
|
|
||||||
override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): DoubleBufferND {
|
override fun mutableStructureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): DoubleBufferND {
|
||||||
val indexer = indexerBuilder(shape)
|
val indexer = indexerBuilder(shape)
|
||||||
return DoubleBufferND(
|
return DoubleBufferND(
|
||||||
indexer,
|
indexer,
|
||||||
@ -225,7 +225,7 @@ public class DoubleFieldND(override val shape: ShapeND) :
|
|||||||
|
|
||||||
override fun number(value: Number): DoubleBufferND {
|
override fun number(value: Number): DoubleBufferND {
|
||||||
val d = value.toDouble() // minimize conversions
|
val d = value.toDouble() // minimize conversions
|
||||||
return structureND(shape) { d }
|
return mutableStructureND(shape) { d }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,6 +244,7 @@ public interface MutableStructureND<T> : StructureND<T> {
|
|||||||
* Set value at specified indices
|
* Set value at specified indices
|
||||||
*/
|
*/
|
||||||
@PerformancePitfall
|
@PerformancePitfall
|
||||||
|
@Deprecated("")
|
||||||
public operator fun <T> MutableStructureND<T>.set(vararg index: Int, value: T) {
|
public operator fun <T> MutableStructureND<T>.set(vararg index: Int, value: T) {
|
||||||
set(index, value)
|
set(index, value)
|
||||||
}
|
}
|
@ -17,6 +17,12 @@ public fun <T, A : Algebra<T>> AlgebraND<T, A>.structureND(
|
|||||||
initializer: A.(IntArray) -> T
|
initializer: A.(IntArray) -> T
|
||||||
): StructureND<T> = structureND(ShapeND(shapeFirst, *shapeRest), initializer)
|
): StructureND<T> = structureND(ShapeND(shapeFirst, *shapeRest), initializer)
|
||||||
|
|
||||||
|
public fun <T, A : Algebra<T>> AlgebraND<T, A>.mutableStructureND(
|
||||||
|
shapeFirst: Int,
|
||||||
|
vararg shapeRest: Int,
|
||||||
|
initializer: A.(IntArray) -> T
|
||||||
|
): MutableStructureND<T> = mutableStructureND(ShapeND(shapeFirst, *shapeRest), initializer)
|
||||||
|
|
||||||
public fun <T, A : Group<T>> AlgebraND<T, A>.zero(shape: ShapeND): StructureND<T> = structureND(shape) { zero }
|
public fun <T, A : Group<T>> AlgebraND<T, A>.zero(shape: ShapeND): StructureND<T> = structureND(shape) { zero }
|
||||||
|
|
||||||
@JvmName("zeroVarArg")
|
@JvmName("zeroVarArg")
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
package space.kscience.kmath.operations
|
package 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.MutableBuffer
|
||||||
|
import space.kscience.kmath.structures.MutableBufferFactory
|
||||||
|
|
||||||
public interface WithSize {
|
public interface WithSize {
|
||||||
public val size: Int
|
public val size: Int
|
||||||
@ -17,7 +18,7 @@ public interface WithSize {
|
|||||||
*/
|
*/
|
||||||
public interface BufferAlgebra<T, out A : Algebra<T>> : Algebra<Buffer<T>> {
|
public interface BufferAlgebra<T, out A : Algebra<T>> : Algebra<Buffer<T>> {
|
||||||
public val elementAlgebra: A
|
public val elementAlgebra: A
|
||||||
public val elementBufferFactory: BufferFactory<T> get() = elementAlgebra.bufferFactory
|
public val elementBufferFactory: MutableBufferFactory<T> get() = elementAlgebra.bufferFactory
|
||||||
|
|
||||||
public fun buffer(size: Int, vararg elements: T): Buffer<T> {
|
public fun buffer(size: Int, vararg elements: T): Buffer<T> {
|
||||||
require(elements.size == size) { "Expected $size elements but found ${elements.size}" }
|
require(elements.size == size) { "Expected $size elements but found ${elements.size}" }
|
||||||
@ -73,11 +74,11 @@ private inline fun <T, A : Algebra<T>> BufferAlgebra<T, A>.zipInline(
|
|||||||
return elementBufferFactory(l.size) { elementAlgebra.block(l[it], r[it]) }
|
return elementBufferFactory(l.size) { elementAlgebra.block(l[it], r[it]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <T> BufferAlgebra<T, *>.buffer(size: Int, initializer: (Int) -> T): Buffer<T> {
|
public fun <T> BufferAlgebra<T, *>.buffer(size: Int, initializer: (Int) -> T): MutableBuffer<T> {
|
||||||
return elementBufferFactory(size, initializer)
|
return elementBufferFactory(size, initializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <T, A> A.buffer(initializer: (Int) -> T): Buffer<T> where A : BufferAlgebra<T, *>, A : WithSize {
|
public fun <T, A> A.buffer(initializer: (Int) -> T): MutableBuffer<T> where A : BufferAlgebra<T, *>, A : WithSize {
|
||||||
return elementBufferFactory(size, initializer)
|
return elementBufferFactory(size, initializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>>(
|
|||||||
protected val multikStat: Statistics = multikEngine.getStatistics()
|
protected val multikStat: Statistics = multikEngine.getStatistics()
|
||||||
|
|
||||||
@OptIn(UnsafeKMathAPI::class)
|
@OptIn(UnsafeKMathAPI::class)
|
||||||
override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): MultikTensor<T> {
|
override fun mutableStructureND(shape: ShapeND, initializer: A.(IntArray) -> T): MultikTensor<T> {
|
||||||
val strides = ColumnStrides(shape)
|
val strides = ColumnStrides(shape)
|
||||||
val memoryView = initMemoryView<T>(strides.linearSize, type)
|
val memoryView = initMemoryView<T>(strides.linearSize, type)
|
||||||
strides.asSequence().forEachIndexed { linearIndex, tensorIndex ->
|
strides.asSequence().forEachIndexed { linearIndex, tensorIndex ->
|
||||||
@ -49,7 +49,7 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>>(
|
|||||||
for (el in array) data[count++] = elementAlgebra.transform(el)
|
for (el in array) data[count++] = elementAlgebra.transform(el)
|
||||||
NDArray(data, shape = shape.asArray(), dim = array.dim).wrap()
|
NDArray(data, shape = shape.asArray(), dim = array.dim).wrap()
|
||||||
} else {
|
} else {
|
||||||
structureND(shape) { index ->
|
mutableStructureND(shape) { index ->
|
||||||
transform(get(index))
|
transform(get(index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>>(
|
|||||||
}
|
}
|
||||||
NDArray(data, shape = array.shape, dim = array.dim).wrap()
|
NDArray(data, shape = array.shape, dim = array.dim).wrap()
|
||||||
} else {
|
} else {
|
||||||
structureND(shape) { index ->
|
mutableStructureND(shape) { index ->
|
||||||
transform(index, get(index))
|
transform(index, get(index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ public sealed interface Nd4jArrayAlgebra<T, out C : Algebra<T>> : AlgebraND<T, C
|
|||||||
public val StructureND<T>.ndArray: INDArray
|
public val StructureND<T>.ndArray: INDArray
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
override fun structureND(shape: ShapeND, initializer: C.(IntArray) -> T): Nd4jArrayStructure<T> {
|
override fun mutableStructureND(shape: ShapeND, initializer: C.(IntArray) -> T): Nd4jArrayStructure<T> {
|
||||||
@OptIn(UnsafeKMathAPI::class)
|
@OptIn(UnsafeKMathAPI::class)
|
||||||
val struct: Nd4jArrayStructure<T> = Nd4j.create(*shape.asArray())!!.wrap()
|
val struct: Nd4jArrayStructure<T> = Nd4j.create(*shape.asArray())!!.wrap()
|
||||||
struct.indicesIterator().forEach { struct[it] = elementAlgebra.initializer(it) }
|
struct.indicesIterator().forEach { struct[it] = elementAlgebra.initializer(it) }
|
||||||
|
@ -37,20 +37,20 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
|
|||||||
*/
|
*/
|
||||||
public val StructureND<T>.ndArray: INDArray
|
public val StructureND<T>.ndArray: INDArray
|
||||||
|
|
||||||
override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): Nd4jArrayStructure<T>
|
override fun mutableStructureND(shape: ShapeND, initializer: A.(IntArray) -> T): Nd4jArrayStructure<T>
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
override fun StructureND<T>.map(transform: A.(T) -> T): Nd4jArrayStructure<T> =
|
override fun StructureND<T>.map(transform: A.(T) -> T): Nd4jArrayStructure<T> =
|
||||||
structureND(shape) { index -> elementAlgebra.transform(get(index)) }
|
mutableStructureND(shape) { index -> elementAlgebra.transform(get(index)) }
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
override fun StructureND<T>.mapIndexed(transform: A.(index: IntArray, T) -> T): Nd4jArrayStructure<T> =
|
override fun StructureND<T>.mapIndexed(transform: A.(index: IntArray, T) -> T): Nd4jArrayStructure<T> =
|
||||||
structureND(shape) { index -> elementAlgebra.transform(index, get(index)) }
|
mutableStructureND(shape) { index -> elementAlgebra.transform(index, get(index)) }
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
override fun zip(left: StructureND<T>, right: StructureND<T>, transform: A.(T, T) -> T): Nd4jArrayStructure<T> {
|
override fun zip(left: StructureND<T>, right: StructureND<T>, transform: A.(T, T) -> T): Nd4jArrayStructure<T> {
|
||||||
require(left.shape.contentEquals(right.shape))
|
require(left.shape.contentEquals(right.shape))
|
||||||
return structureND(left.shape) { index -> elementAlgebra.transform(left[index], right[index]) }
|
return mutableStructureND(left.shape) { index -> elementAlgebra.transform(left[index], right[index]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun T.plus(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.add(this).wrap()
|
override fun T.plus(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.add(this).wrap()
|
||||||
@ -178,7 +178,7 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra<Double, DoubleField> {
|
|||||||
override fun INDArray.wrap(): Nd4jArrayStructure<Double> = asDoubleStructure()
|
override fun INDArray.wrap(): Nd4jArrayStructure<Double> = asDoubleStructure()
|
||||||
|
|
||||||
@OptIn(UnsafeKMathAPI::class)
|
@OptIn(UnsafeKMathAPI::class)
|
||||||
override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): Nd4jArrayStructure<Double> {
|
override fun mutableStructureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): Nd4jArrayStructure<Double> {
|
||||||
val array: INDArray = Nd4j.zeros(*shape.asArray())
|
val array: INDArray = Nd4j.zeros(*shape.asArray())
|
||||||
val indices = ColumnStrides(shape)
|
val indices = ColumnStrides(shape)
|
||||||
indices.asSequence().forEach { index ->
|
indices.asSequence().forEach { index ->
|
||||||
|
@ -14,6 +14,7 @@ import space.kscience.kmath.PerformancePitfall
|
|||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.expressions.Symbol
|
import space.kscience.kmath.expressions.Symbol
|
||||||
import space.kscience.kmath.nd.ColumnStrides
|
import space.kscience.kmath.nd.ColumnStrides
|
||||||
|
import space.kscience.kmath.nd.MutableStructureND
|
||||||
import space.kscience.kmath.nd.ShapeND
|
import space.kscience.kmath.nd.ShapeND
|
||||||
import space.kscience.kmath.nd.StructureND
|
import space.kscience.kmath.nd.StructureND
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
@ -36,10 +37,10 @@ public class DoubleTensorFlowAlgebra internal constructor(
|
|||||||
|
|
||||||
override val elementAlgebra: DoubleField get() = DoubleField
|
override val elementAlgebra: DoubleField get() = DoubleField
|
||||||
|
|
||||||
override fun structureND(
|
override fun mutableStructureND(
|
||||||
shape: ShapeND,
|
shape: ShapeND,
|
||||||
initializer: DoubleField.(IntArray) -> Double,
|
initializer: DoubleField.(IntArray) -> Double,
|
||||||
): StructureND<Double> {
|
): MutableStructureND<Double> {
|
||||||
val res = TFloat64.tensorOf(org.tensorflow.ndarray.Shape.of(*shape.toLongArray())) { array ->
|
val res = TFloat64.tensorOf(org.tensorflow.ndarray.Shape.of(*shape.toLongArray())) { array ->
|
||||||
ColumnStrides(shape).forEach { index ->
|
ColumnStrides(shape).forEach { index ->
|
||||||
array.setDouble(elementAlgebra.initializer(index), *index.toLongArray())
|
array.setDouble(elementAlgebra.initializer(index), *index.toLongArray())
|
||||||
|
@ -15,12 +15,12 @@ kscience{
|
|||||||
|
|
||||||
kotlin.sourceSets {
|
kotlin.sourceSets {
|
||||||
all {
|
all {
|
||||||
languageSettings.optIn("space.kscience.kmath.misc.UnstableKMathAPI")
|
languageSettings.optIn("space.kscience.kmath.UnstableKMathAPI")
|
||||||
}
|
}
|
||||||
|
|
||||||
filter { it.name.contains("test", true) }
|
filter { it.name.contains("test", true) }
|
||||||
.map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings)
|
.map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings)
|
||||||
.forEach { it.optIn("space.kscience.kmath.misc.PerformancePitfall") }
|
.forEach { it.optIn("space.kscience.kmath.PerformancePitfall") }
|
||||||
|
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -127,7 +127,7 @@ public open class DoubleTensorAlgebra :
|
|||||||
* @param initializer mapping tensor indices to values.
|
* @param initializer mapping tensor indices to values.
|
||||||
* @return tensor with the [shape] shape and data generated by the [initializer].
|
* @return tensor with the [shape] shape and data generated by the [initializer].
|
||||||
*/
|
*/
|
||||||
override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray(
|
override fun mutableStructureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray(
|
||||||
shape,
|
shape,
|
||||||
RowStrides(shape).asSequence().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray()
|
RowStrides(shape).asSequence().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray()
|
||||||
)
|
)
|
||||||
|
@ -118,7 +118,7 @@ public open class IntTensorAlgebra : TensorAlgebra<Int, IntRing> {
|
|||||||
* @param initializer mapping tensor indices to values.
|
* @param initializer mapping tensor indices to values.
|
||||||
* @return tensor with the [shape] shape and data generated by the [initializer].
|
* @return tensor with the [shape] shape and data generated by the [initializer].
|
||||||
*/
|
*/
|
||||||
override fun structureND(shape: ShapeND, initializer: IntRing.(IntArray) -> Int): IntTensor = fromArray(
|
override fun mutableStructureND(shape: ShapeND, initializer: IntRing.(IntArray) -> Int): IntTensor = fromArray(
|
||||||
shape,
|
shape,
|
||||||
RowStrides(shape).asSequence().map { IntRing.initializer(it) }.toMutableList().toIntArray()
|
RowStrides(shape).asSequence().map { IntRing.initializer(it) }.toMutableList().toIntArray()
|
||||||
)
|
)
|
||||||
|
@ -92,7 +92,7 @@ internal class TestDoubleTensor {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test2D() = with(DoubleTensorAlgebra) {
|
fun test2D() = with(DoubleTensorAlgebra) {
|
||||||
val tensor: DoubleTensor = structureND(ShapeND(3, 3)) { (i, j) -> (i - j).toDouble() }
|
val tensor: DoubleTensor = mutableStructureND(ShapeND(3, 3)) { (i, j) -> (i - j).toDouble() }
|
||||||
//println(tensor.toPrettyString())
|
//println(tensor.toPrettyString())
|
||||||
val tensor2d = tensor.asDoubleTensor2D()
|
val tensor2d = tensor.asDoubleTensor2D()
|
||||||
assertBufferEquals(DoubleBuffer(1.0, 0.0, -1.0), tensor2d.rows[1])
|
assertBufferEquals(DoubleBuffer(1.0, 0.0, -1.0), tensor2d.rows[1])
|
||||||
@ -101,7 +101,7 @@ internal class TestDoubleTensor {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMatrixIteration() = with(DoubleTensorAlgebra) {
|
fun testMatrixIteration() = with(DoubleTensorAlgebra) {
|
||||||
val tensor = structureND(ShapeND(3, 3, 3, 3)) { index -> index.sum().toDouble() }
|
val tensor = mutableStructureND(ShapeND(3, 3, 3, 3)) { index -> index.sum().toDouble() }
|
||||||
tensor.forEachMatrix { index, matrix ->
|
tensor.forEachMatrix { index, matrix ->
|
||||||
println(index.joinToString { it.toString() })
|
println(index.joinToString { it.toString() })
|
||||||
println(matrix)
|
println(matrix)
|
||||||
|
@ -17,8 +17,7 @@ import space.kscience.kmath.operations.ExtendedFieldOps
|
|||||||
import space.kscience.kmath.operations.NumbersAddOps
|
import space.kscience.kmath.operations.NumbersAddOps
|
||||||
import space.kscience.kmath.operations.PowerOperations
|
import space.kscience.kmath.operations.PowerOperations
|
||||||
|
|
||||||
@OptIn(UnstableKMathAPI::class, PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
|
||||||
public open class ViktorFieldOpsND :
|
public open class ViktorFieldOpsND :
|
||||||
FieldOpsND<Double, DoubleField>,
|
FieldOpsND<Double, DoubleField>,
|
||||||
ExtendedFieldOps<StructureND<Double>>,
|
ExtendedFieldOps<StructureND<Double>>,
|
||||||
@ -27,13 +26,13 @@ public open class ViktorFieldOpsND :
|
|||||||
public val StructureND<Double>.f64Buffer: F64Array
|
public val StructureND<Double>.f64Buffer: F64Array
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
is ViktorStructureND -> this.f64Buffer
|
is ViktorStructureND -> this.f64Buffer
|
||||||
else -> structureND(shape) { this@f64Buffer[it] }.f64Buffer
|
else -> mutableStructureND(shape) { this@f64Buffer[it] }.f64Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
override val elementAlgebra: DoubleField get() = DoubleField
|
override val elementAlgebra: DoubleField get() = DoubleField
|
||||||
|
|
||||||
@OptIn(UnsafeKMathAPI::class)
|
@OptIn(UnsafeKMathAPI::class)
|
||||||
override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND =
|
override fun mutableStructureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND =
|
||||||
F64Array(*shape.asArray()).apply {
|
F64Array(*shape.asArray()).apply {
|
||||||
ColumnStrides(shape).asSequence().forEach { index ->
|
ColumnStrides(shape).asSequence().forEach { index ->
|
||||||
set(value = DoubleField.initializer(index), indices = index)
|
set(value = DoubleField.initializer(index), indices = index)
|
||||||
|
Loading…
Reference in New Issue
Block a user