From ee569b85f801972fd7cbd44d43abcd1df0a1b30d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 14 Oct 2022 13:05:39 +0300 Subject: [PATCH] Safe shapes --- .../kmath/benchmarks/NDFieldBenchmark.kt | 2 +- .../kmath/benchmarks/ViktorBenchmark.kt | 4 +- .../kmath/benchmarks/ViktorLogBenchmark.kt | 4 +- .../kmath/operations/mixedNDOperations.kt | 4 +- .../kscience/kmath/structures/NDField.kt | 2 +- .../kmath/structures/StreamDoubleFieldND.kt | 6 +- .../structures/StructureReadBenchmark.kt | 4 +- .../structures/StructureWriteBenchmark.kt | 4 +- .../kscience/kmath/tensors/OLSWithSVD.kt | 8 +- .../space/kscience/kmath/tensors/PCA.kt | 10 +- .../kmath/tensors/dataSetNormalization.kt | 6 +- .../tensors/linearSystemSolvingWithLUP.kt | 8 +- .../kscience/kmath/tensors/neuralNetwork.kt | 12 +-- .../kscience/kmath/complex/ComplexFieldND.kt | 6 +- .../kmath/linear/BufferedLinearSpace.kt | 2 +- .../kmath/linear/DoubleLinearSpace.kt | 2 +- .../kscience/kmath/linear/VirtualMatrix.kt | 5 +- .../space/kscience/kmath/nd/AlgebraND.kt | 2 +- .../kscience/kmath/nd/BufferAlgebraND.kt | 16 +-- .../space/kscience/kmath/nd/BufferND.kt | 2 +- .../space/kscience/kmath/nd/DoubleFieldND.kt | 10 +- .../space/kscience/kmath/nd/IntRingND.kt | 6 +- .../kscience/kmath/nd/PermutedStructureND.kt | 6 +- .../kotlin/space/kscience/kmath/nd/Shape.kt | 102 ------------------ .../space/kscience/kmath/nd/ShapeIndices.kt | 10 +- .../kotlin/space/kscience/kmath/nd/ShapeND.kt | 102 ++++++++++++++++++ .../space/kscience/kmath/nd/ShortRingND.kt | 4 +- .../space/kscience/kmath/nd/Structure1D.kt | 8 +- .../space/kscience/kmath/nd/Structure2D.kt | 6 +- .../space/kscience/kmath/nd/StructureND.kt | 10 +- .../kscience/kmath/nd/VirtualStructureND.kt | 6 +- .../kscience/kmath/nd/algebraNDExtentions.kt | 6 +- .../kmath/structures/BufferAccessor2D.kt | 2 +- .../space/kscience/kmath/nd/StridesTest.kt | 4 +- .../kmath/structures/LazyStructureND.kt | 8 +- .../kscience/kmath/dimensions/Wrappers.kt | 4 +- .../kscience/kmath/histogram/HistogramND.kt | 4 +- .../histogram/UniformHistogramGroupND.kt | 2 +- .../kscience/kmath/multik/MultikTensor.kt | 4 +- .../kmath/multik/MultikTensorAlgebra.kt | 8 +- .../kscience/kmath/multik/MultikNDTest.kt | 6 +- .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 15 +-- .../kscience/kmath/nd4j/Nd4jArrayStructure.kt | 2 +- .../kscience/kmath/nd4j/Nd4jTensorAlgebra.kt | 8 +- .../tensorflow/DoubleTensorFlowAlgebra.kt | 6 +- .../kmath/tensorflow/TensorFlowAlgebra.kt | 12 ++- .../kmath/tensorflow/DoubleTensorFlowOps.kt | 6 +- .../kmath/tensors/api/TensorAlgebra.kt | 4 +- .../kmath/tensors/core/BufferedTensor.kt | 4 +- .../kmath/tensors/core/DoubleTensor.kt | 8 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 40 +++---- .../kscience/kmath/tensors/core/IntTensor.kt | 6 +- .../kmath/tensors/core/IntTensorAlgebra.kt | 20 ++-- .../tensors/core/internal/broadcastUtils.kt | 8 +- .../kmath/tensors/core/internal/checks.kt | 10 +- .../core/internal/doubleTensorHelpers.kt | 4 +- .../tensors/core/internal/intTensorHelpers.kt | 4 +- .../kmath/tensors/core/internal/linUtils.kt | 8 +- .../tensors/core/tensorAlgebraExtensions.kt | 10 +- .../kmath/tensors/core/TestBroadcasting.kt | 64 +++++------ .../core/TestDoubleAnalyticTensorAlgebra.kt | 22 ++-- .../core/TestDoubleLinearOpsAlgebra.kt | 38 +++---- .../kmath/tensors/core/TestDoubleTensor.kt | 12 +-- .../tensors/core/TestDoubleTensorAlgebra.kt | 74 ++++++------- .../kscience/kmath/viktor/ViktorFieldOpsND.kt | 8 +- .../kmath/viktor/ViktorStructureND.kt | 4 +- 66 files changed, 416 insertions(+), 408 deletions(-) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeND.kt diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt index 75c1a3ee3..3d39e89a5 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -85,7 +85,7 @@ internal class NDFieldBenchmark { private companion object { private const val dim = 1000 private const val n = 100 - private val shape = Shape(dim, dim) + private val shape = ShapeND(dim, dim) private val specializedField = DoubleField.ndAlgebra private val genericField = BufferedFieldOpsND(DoubleField) private val nd4jField = DoubleField.nd4j diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt index 25ce8410a..90f3cb765 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt @@ -10,7 +10,7 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import org.jetbrains.bio.viktor.F64Array -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.ndAlgebra import space.kscience.kmath.nd.one @@ -49,7 +49,7 @@ internal class ViktorBenchmark { private companion object { private const val dim = 1000 private const val n = 100 - private val shape = Shape(dim, dim) + private val shape = ShapeND(dim, dim) // automatically build context most suited for given type. private val doubleField = DoubleField.ndAlgebra diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt index ea417e564..4ec4605ed 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt @@ -10,7 +10,7 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import org.jetbrains.bio.viktor.F64Array -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.ndAlgebra import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField @@ -49,7 +49,7 @@ internal class ViktorLogBenchmark { private companion object { private const val dim = 1000 private const val n = 100 - private val shape = Shape(dim, dim) + private val shape = ShapeND(dim, dim) // automatically build context most suited for given type. private val doubleField = DoubleField.ndAlgebra diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt index 8fc6e1b06..4a5d783e1 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt @@ -8,14 +8,14 @@ package space.kscience.kmath.operations import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.linear.matrix import space.kscience.kmath.nd.DoubleBufferND -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.ndAlgebra import space.kscience.kmath.viktor.ViktorStructureND import space.kscience.kmath.viktor.viktorAlgebra fun main() { - val viktorStructure: ViktorStructureND = DoubleField.viktorAlgebra.structureND(Shape(2, 2)) { (i, j) -> + val viktorStructure: ViktorStructureND = DoubleField.viktorAlgebra.structureND(ShapeND(2, 2)) { (i, j) -> if (i == j) 2.0 else 0.0 } diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt index 48d14cb4c..ba8f047a8 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt @@ -29,7 +29,7 @@ fun main() { Nd4j.zeros(0) val dim = 1000 val n = 1000 - val shape = Shape(dim, dim) + val shape = ShapeND(dim, dim) // specialized nd-field for Double. It works as generic Double field as well. diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt index dd1516fcd..67c9b421f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -17,7 +17,7 @@ import java.util.stream.IntStream * A demonstration implementation of NDField over Real using Java [java.util.stream.DoubleStream] for parallel * execution. */ -class StreamDoubleFieldND(override val shape: Shape) : FieldND, +class StreamDoubleFieldND(override val shape: ShapeND) : FieldND, NumbersAddOps>, ExtendedField> { @@ -43,7 +43,7 @@ class StreamDoubleFieldND(override val shape: Shape) : FieldND DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } } - override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): BufferND { + override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): BufferND { val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset -> val index = strides.index(offset) DoubleField.initializer(index) @@ -111,4 +111,4 @@ class StreamDoubleFieldND(override val shape: Shape) : FieldND): BufferND = arg.map { atanh(it) } } -fun DoubleField.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(Shape(shape)) +fun DoubleField.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(ShapeND(shape)) diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt index ec05f38d0..e3e7daaae 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.structures import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.BufferND import space.kscience.kmath.nd.ColumnStrides -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import kotlin.system.measureTimeMillis @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") @@ -17,7 +17,7 @@ fun main() { val n = 6000 val array = DoubleArray(n * n) { 1.0 } val buffer = DoubleBuffer(array) - val strides = ColumnStrides(Shape(n, n)) + val strides = ColumnStrides(ShapeND(n, n)) val structure = BufferND(strides, buffer) measureTimeMillis { diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt index 081bfa5c0..522eeb768 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.structures import space.kscience.kmath.nd.BufferND -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.map import kotlin.system.measureTimeMillis @@ -16,7 +16,7 @@ private inline fun BufferND.map(block: (T) -> R): BufferN @Suppress("UNUSED_VARIABLE") fun main() { val n = 6000 - val structure = StructureND.buffered(Shape(n, n), Buffer.Companion::auto) { 1.0 } + val structure = StructureND.buffered(ShapeND(n, n), Buffer.Companion::auto) { 1.0 } structure.map { it + 1 } // warm-up val time1 = measureTimeMillis { val res = structure.map { it + 1 } } println("Structure mapping finished in $time1 millis") diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 32d4176c1..40b927215 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor @@ -25,10 +25,10 @@ fun main() { DoubleTensorAlgebra { // take coefficient vector from normal distribution val alpha = randomNormal( - Shape(5), + ShapeND(5), randSeed ) + fromArray( - Shape(5), + ShapeND(5), doubleArrayOf(1.0, 2.5, 3.4, 5.0, 10.1) ) @@ -36,7 +36,7 @@ fun main() { // also take sample of size 20 from normal distribution for x val x = randomNormal( - Shape(20, 5), + ShapeND(20, 5), randSeed ) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt index 2022b6472..78199aa8b 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.tensors.core.tensorAlgebra import space.kscience.kmath.tensors.core.withBroadcast @@ -17,7 +17,7 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with // assume x is range from 0 until 10 val x = fromArray( - Shape(10), + ShapeND(10), DoubleArray(10) { it.toDouble() } ) @@ -42,13 +42,13 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with // save means ans standard deviations for further recovery val mean = fromArray( - Shape(2), + ShapeND(2), doubleArrayOf(xMean, yMean) ) println("Means:\n$mean") val std = fromArray( - Shape(2), + ShapeND(2), doubleArrayOf(xStd, yStd) ) println("Standard deviations:\n$std") @@ -69,7 +69,7 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with // we can restore original data from reduced data; // for example, find 7th element of dataset. val n = 7 - val restored = (datasetReduced.getTensor(n) dot v.view(Shape(1, 2))) * std + mean + val restored = (datasetReduced.getTensor(n) dot v.view(ShapeND(1, 2))) * std + mean println("Original value:\n${dataset.getTensor(n)}") println("Restored value:\n$restored") } diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt index 248266edb..091889e8e 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.tensors.core.tensorAlgebra import space.kscience.kmath.tensors.core.withBroadcast @@ -14,10 +14,10 @@ import space.kscience.kmath.tensors.core.withBroadcast fun main() = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods // take dataset of 5-element vectors from normal distribution - val dataset = randomNormal(Shape(100, 5)) * 1.5 // all elements from N(0, 1.5) + val dataset = randomNormal(ShapeND(100, 5)) * 1.5 // all elements from N(0, 1.5) dataset += fromArray( - Shape(5), + ShapeND(5), doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // row means ) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt index 3eab64429..60716d0ba 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.tensorAlgebra import space.kscience.kmath.tensors.core.withBroadcast @@ -16,13 +16,13 @@ fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear // set true value of x val trueX = fromArray( - Shape(4), + ShapeND(4), doubleArrayOf(-2.0, 1.5, 6.8, -2.4) ) // and A matrix val a = fromArray( - Shape(4, 4), + ShapeND(4, 4), doubleArrayOf( 0.5, 10.5, 4.5, 1.0, 8.5, 0.9, 12.8, 0.1, @@ -65,7 +65,7 @@ fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear // this function returns solution x of a system lx = b, l should be lower triangular fun solveLT(l: DoubleTensor, b: DoubleTensor): DoubleTensor { val n = l.shape[0] - val x = zeros(Shape(n)) + val x = zeros(ShapeND(n)) for (i in 0 until n) { x[intArrayOf(i)] = (b[intArrayOf(i)] - l.getTensor(i).dot(x).value()) / l[intArrayOf(i, i)] } diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt index 1e4e339dc..52b3b556c 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.asIterable import space.kscience.kmath.operations.invoke @@ -70,12 +70,12 @@ class Dense( private val weights: DoubleTensor = DoubleTensorAlgebra { randomNormal( - Shape(inputUnits, outputUnits), + ShapeND(inputUnits, outputUnits), seed ) * sqrt(2.0 / (inputUnits + outputUnits)) } - private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(Shape(outputUnits)) } + private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(ShapeND(outputUnits)) } override fun forward(input: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra { (input dot weights) + bias @@ -184,17 +184,17 @@ fun main() = BroadcastDoubleTensorAlgebra { //val testSize = sampleSize - trainSize // take sample of features from normal distribution - val x = randomNormal(Shape(sampleSize, features), seed) * 2.5 + val x = randomNormal(ShapeND(sampleSize, features), seed) * 2.5 x += fromArray( - Shape(5), + ShapeND(5), doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // row means ) // define class like '1' if the sum of features > 0 and '0' otherwise val y = fromArray( - Shape(sampleSize, 1), + ShapeND(sampleSize, 1), DoubleArray(sampleSize) { i -> if (x.getTensor(i).sum() > 0.0) { 1.0 diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt index cbc69ca6e..06f6cad85 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt @@ -59,7 +59,7 @@ public sealed class ComplexFieldOpsND : BufferedFieldOpsND, NumbersAddOps> { @@ -71,12 +71,12 @@ public class ComplexFieldND(override val shape: Shape) : public val ComplexField.ndAlgebra: ComplexFieldOpsND get() = ComplexFieldOpsND -public fun ComplexField.ndAlgebra(vararg shape: Int): ComplexFieldND = ComplexFieldND(Shape(shape)) +public fun ComplexField.ndAlgebra(vararg shape: Int): ComplexFieldND = ComplexFieldND(ShapeND(shape)) /** * Produce a context for n-dimensional operations inside this real field */ public inline fun ComplexField.withNdAlgebra(vararg shape: Int, action: ComplexFieldND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return ComplexFieldND(Shape(shape)).action() + return ComplexFieldND(ShapeND(shape)).action() } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt index 52f04d76a..5976b67b1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt @@ -21,7 +21,7 @@ public class BufferedLinearSpace>( private val ndAlgebra = BufferedRingOpsND(bufferAlgebra) override fun buildMatrix(rows: Int, columns: Int, initializer: A.(i: Int, j: Int) -> T): Matrix = - ndAlgebra.structureND(Shape(rows, columns)) { (i, j) -> elementAlgebra.initializer(i, j) }.as2D() + ndAlgebra.structureND(ShapeND(rows, columns)) { (i, j) -> elementAlgebra.initializer(i, j) }.as2D() override fun buildVector(size: Int, initializer: A.(Int) -> T): Point = bufferAlgebra.buffer(size) { elementAlgebra.initializer(it) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/DoubleLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/DoubleLinearSpace.kt index 47ab5bece..4e7ab55ef 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/DoubleLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/DoubleLinearSpace.kt @@ -21,7 +21,7 @@ public object DoubleLinearSpace : LinearSpace { rows: Int, columns: Int, initializer: DoubleField.(i: Int, j: Int) -> Double - ): Matrix = DoubleFieldOpsND.structureND(Shape(rows, columns)) { (i, j) -> + ): Matrix = DoubleFieldOpsND.structureND(ShapeND(rows, columns)) { (i, j) -> DoubleField.initializer(i, j) }.as2D() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt index b7ed6e867..55b970f4a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt @@ -5,7 +5,8 @@ package space.kscience.kmath.linear -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND + /** * The matrix where each element is evaluated each time when is being accessed. @@ -18,7 +19,7 @@ public class VirtualMatrix( public val generator: (i: Int, j: Int) -> T, ) : Matrix { - override val shape: Shape get() = Shape(rowNum, colNum) + override val shape: ShapeND get() = ShapeND(rowNum, colNum) override operator fun get(i: Int, j: Int): T = generator(i, j) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt index 101f90160..d53f5488a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt @@ -25,7 +25,7 @@ public interface AlgebraND>: Algebra> { /** * Produces a new [StructureND] using given initializer function. */ - public fun structureND(shape: Shape, initializer: C.(IntArray) -> T): StructureND + public fun structureND(shape: ShapeND, initializer: C.(IntArray) -> T): StructureND /** * Maps elements from one structure to another one by applying [transform] to them. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt index 597fc7d97..781d2e367 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt @@ -12,11 +12,11 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* public interface BufferAlgebraND> : AlgebraND { - public val indexerBuilder: (Shape) -> ShapeIndexer + public val indexerBuilder: (ShapeND) -> ShapeIndexer public val bufferAlgebra: BufferAlgebra override val elementAlgebra: A get() = bufferAlgebra.elementAlgebra - override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): BufferND { + override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): BufferND { val indexer = indexerBuilder(shape) return BufferND( indexer, @@ -47,7 +47,7 @@ public interface BufferAlgebraND> : AlgebraND { zipInline(left.toBufferND(), right.toBufferND(), transform) public companion object { - public val defaultIndexerBuilder: (Shape) -> ShapeIndexer = ::Strides + public val defaultIndexerBuilder: (ShapeND) -> ShapeIndexer = ::Strides } } @@ -99,24 +99,24 @@ internal inline fun > BufferAlgebraND.zipInline( @OptIn(PerformancePitfall::class) public open class BufferedGroupNDOps>( override val bufferAlgebra: BufferAlgebra, - override val indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + override val indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, ) : GroupOpsND, BufferAlgebraND { override fun StructureND.unaryMinus(): StructureND = map { -it } } public open class BufferedRingOpsND>( bufferAlgebra: BufferAlgebra, - indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, ) : BufferedGroupNDOps(bufferAlgebra, indexerBuilder), RingOpsND public open class BufferedFieldOpsND>( bufferAlgebra: BufferAlgebra, - indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, ) : BufferedRingOpsND(bufferAlgebra, indexerBuilder), FieldOpsND { public constructor( elementAlgebra: A, - indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, ) : this(BufferFieldOps(elementAlgebra), indexerBuilder) @OptIn(PerformancePitfall::class) @@ -131,7 +131,7 @@ public val > BufferAlgebra.nd: BufferedFieldOpsND ge public fun > BufferAlgebraND.structureND( vararg shape: Int, initializer: A.(IntArray) -> T, -): BufferND = structureND(Shape(shape), initializer) +): BufferND = structureND(ShapeND(shape), initializer) public fun , A> A.structureND( initializer: EA.(IntArray) -> T, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt index 644b62ebe..55e8bbcf8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt @@ -24,7 +24,7 @@ public open class BufferND( @PerformancePitfall override operator fun get(index: IntArray): T = buffer[indices.offset(index)] - override val shape: Shape get() = indices.shape + override val shape: ShapeND get() = indices.shape override fun toString(): String = StructureND.toString(this) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt index 182ce38d6..b5ed64108 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt @@ -74,7 +74,7 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND(D transform: DoubleField.(Double, Double) -> Double, ): BufferND = zipInline(left.toBufferND(), right.toBufferND()) { l, r -> DoubleField.transform(l, r) } - override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): DoubleBufferND { + override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): DoubleBufferND { val indexer = indexerBuilder(shape) return DoubleBufferND( indexer, @@ -189,7 +189,7 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND(D } @OptIn(UnstableKMathAPI::class) -public class DoubleFieldND(override val shape: Shape) : +public class DoubleFieldND(override val shape: ShapeND) : DoubleFieldOpsND(), FieldND, NumbersAddOps>, ExtendedField> { @@ -231,8 +231,8 @@ public class DoubleFieldND(override val shape: Shape) : public val DoubleField.ndAlgebra: DoubleFieldOpsND get() = DoubleFieldOpsND -public fun DoubleField.ndAlgebra(vararg shape: Int): DoubleFieldND = DoubleFieldND(Shape(shape)) -public fun DoubleField.ndAlgebra(shape: Shape): DoubleFieldND = DoubleFieldND(shape) +public fun DoubleField.ndAlgebra(vararg shape: Int): DoubleFieldND = DoubleFieldND(ShapeND(shape)) +public fun DoubleField.ndAlgebra(shape: ShapeND): DoubleFieldND = DoubleFieldND(shape) /** * Produce a context for n-dimensional operations inside this real field @@ -240,5 +240,5 @@ public fun DoubleField.ndAlgebra(shape: Shape): DoubleFieldND = DoubleFieldND(sh @UnstableKMathAPI public inline fun DoubleField.withNdAlgebra(vararg shape: Int, action: DoubleFieldND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return DoubleFieldND(Shape(shape)).run(action) + return DoubleFieldND(ShapeND(shape)).run(action) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt index 697e351d2..f46defeee 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt @@ -20,7 +20,7 @@ public class IntBufferND( public sealed class IntRingOpsND : BufferedRingOpsND(IntRing.bufferAlgebra) { - override fun structureND(shape: Shape, initializer: IntRing.(IntArray) -> Int): IntBufferND { + override fun structureND(shape: ShapeND, initializer: IntRing.(IntArray) -> Int): IntBufferND { val indexer = indexerBuilder(shape) return IntBufferND( indexer, @@ -35,7 +35,7 @@ public sealed class IntRingOpsND : BufferedRingOpsND(IntRing.buffe @OptIn(UnstableKMathAPI::class) public class IntRingND( - override val shape: Shape + override val shape: ShapeND ) : IntRingOpsND(), RingND, NumbersAddOps> { override fun number(value: Number): BufferND { @@ -46,5 +46,5 @@ public class IntRingND( public inline fun IntRing.withNdAlgebra(vararg shape: Int, action: IntRingND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return IntRingND(Shape(shape)).run(action) + return IntRingND(ShapeND(shape)).run(action) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/PermutedStructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/PermutedStructureND.kt index 0efc7beb0..e4ba72cec 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/PermutedStructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/PermutedStructureND.kt @@ -13,7 +13,7 @@ public class PermutedStructureND( public val permutation: (IntArray) -> IntArray, ) : StructureND { - override val shape: Shape + override val shape: ShapeND get() = origin.shape @OptIn(PerformancePitfall::class) @@ -28,7 +28,7 @@ public fun StructureND.permute( public class PermutedMutableStructureND( public val origin: MutableStructureND, - override val shape: Shape = origin.shape, + override val shape: ShapeND = origin.shape, public val permutation: (IntArray) -> IntArray, ) : MutableStructureND { @@ -45,6 +45,6 @@ public class PermutedMutableStructureND( } public fun MutableStructureND.permute( - newShape: Shape = shape, + newShape: ShapeND = shape, permutation: (IntArray) -> IntArray, ): PermutedMutableStructureND = PermutedMutableStructureND(this, newShape, permutation) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt deleted file mode 100644 index 8dd17ab32..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2018-2022 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.nd - -import space.kscience.kmath.misc.UnsafeKMathAPI -import kotlin.jvm.JvmInline - -/** - * A read-only ND shape - */ -@JvmInline -public value class Shape(@PublishedApi internal val array: IntArray) { - public val size: Int get() = array.size - public operator fun get(index: Int): Int = array[index] - override fun toString(): String = array.contentToString() -} - -public inline fun Shape.forEach(block: (value: Int) -> Unit): Unit = array.forEach(block) - -public inline fun Shape.forEachIndexed(block: (index: Int, value: Int) -> Unit): Unit = array.forEachIndexed(block) - -public infix fun Shape.contentEquals(other: Shape): Boolean = array.contentEquals(other.array) - -public fun Shape.contentHashCode(): Int = array.contentHashCode() - -public val Shape.indices: IntRange get() = array.indices -public val Shape.linearSize: Int get() = array.reduce(Int::times) - -public fun Shape.slice(range: IntRange): Shape = Shape(array.sliceArray(range)) - -public fun Shape.last(): Int = array.last() - -/** - * A shape including last [n] dimensions of this shape - */ -public fun Shape.last(n: Int): Shape = Shape(array.copyOfRange(size - n, size)) - -public fun Shape.first(): Int = array.first() - -/** - * A shape including first [n] dimensions of this shape - */ -public fun Shape.first(n: Int): Shape = Shape(array.copyOfRange(0, n)) - -public operator fun Shape.plus(add: IntArray): Shape = Shape(array + add) - -public operator fun Shape.plus(add: Shape): Shape = Shape(array + add.array) - -public fun Shape.isEmpty(): Boolean = size == 0 -public fun Shape.isNotEmpty(): Boolean = size > 0 - -public fun Shape.transposed(i: Int, j: Int): Shape = Shape(array.copyOf().apply { - val ith = get(i) - val jth = get(j) - set(i, jth) - set(j, ith) -}) - -public operator fun Shape.component1(): Int = get(0) -public operator fun Shape.component2(): Int = get(1) -public operator fun Shape.component3(): Int = get(2) - -/** - * Convert to array with protective copy - */ -public fun Shape.toArray(): IntArray = array.copyOf() - -@UnsafeKMathAPI -public fun Shape.asArray(): IntArray = array - -public fun Shape.asList(): List = array.asList() - - -/** - * An exception is thrown when the expected and actual shape of NDArray differ. - * - * @property expected the expected shape. - * @property actual the actual shape. - */ -public class ShapeMismatchException(public val expected: Shape, public val actual: Shape) : - RuntimeException("Shape $actual doesn't fit in expected shape ${expected}.") - -public class IndexOutOfShapeException(public val shape: Shape, public val index: IntArray) : - RuntimeException("Index ${index.contentToString()} is out of shape ${shape}") - -public fun Shape(shapeFirst: Int, vararg shapeRest: Int): Shape = Shape(intArrayOf(shapeFirst, *shapeRest)) - -public interface WithShape { - public val shape: Shape - - public val indices: ShapeIndexer get() = ColumnStrides(shape) -} - -internal fun requireIndexInShape(index: IntArray, shape: Shape) { - if (index.size != shape.size) throw IndexOutOfShapeException(shape, index) - shape.forEachIndexed { axis, axisShape -> - if (index[axis] !in 0 until axisShape) throw IndexOutOfShapeException(shape, index) - } -} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt index d2ea302fd..37e0c7b5e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt @@ -12,7 +12,7 @@ import kotlin.native.concurrent.ThreadLocal * A converter from linear index to multivariate index */ public interface ShapeIndexer : Iterable { - public val shape: Shape + public val shape: ShapeND /** * Get linear index from multidimensional index @@ -68,7 +68,7 @@ public abstract class Strides : ShapeIndexer { /** * Column-first [Strides]. Columns are represented as continuous arrays */ -public class ColumnStrides(override val shape: Shape) : Strides() { +public class ColumnStrides(override val shape: ShapeND) : Strides() { override val linearSize: Int get() = strides[shape.size] /** @@ -118,7 +118,7 @@ public class ColumnStrides(override val shape: Shape) : Strides() { * * @param shape the shape of the tensor. */ -public class RowStrides(override val shape: Shape) : Strides() { +public class RowStrides(override val shape: ShapeND) : Strides() { override val strides: IntArray by lazy { val nDim = shape.size @@ -163,9 +163,9 @@ public class RowStrides(override val shape: Shape) : Strides() { } @ThreadLocal -private val defaultStridesCache = HashMap() +private val defaultStridesCache = HashMap() /** * Cached builder for default strides */ -public fun Strides(shape: Shape): Strides = defaultStridesCache.getOrPut(shape) { RowStrides(shape) } \ No newline at end of file +public fun Strides(shape: ShapeND): Strides = defaultStridesCache.getOrPut(shape) { RowStrides(shape) } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeND.kt new file mode 100644 index 000000000..63728e94f --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeND.kt @@ -0,0 +1,102 @@ +/* + * Copyright 2018-2022 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.nd + +import space.kscience.kmath.misc.UnsafeKMathAPI +import kotlin.jvm.JvmInline + +/** + * A read-only ND shape + */ +@JvmInline +public value class ShapeND(@PublishedApi internal val array: IntArray) { + public val size: Int get() = array.size + public operator fun get(index: Int): Int = array[index] + override fun toString(): String = array.contentToString() +} + +public inline fun ShapeND.forEach(block: (value: Int) -> Unit): Unit = array.forEach(block) + +public inline fun ShapeND.forEachIndexed(block: (index: Int, value: Int) -> Unit): Unit = array.forEachIndexed(block) + +public infix fun ShapeND.contentEquals(other: ShapeND): Boolean = array.contentEquals(other.array) + +public fun ShapeND.contentHashCode(): Int = array.contentHashCode() + +public val ShapeND.indices: IntRange get() = array.indices +public val ShapeND.linearSize: Int get() = array.reduce(Int::times) + +public fun ShapeND.slice(range: IntRange): ShapeND = ShapeND(array.sliceArray(range)) + +public fun ShapeND.last(): Int = array.last() + +/** + * A shape including last [n] dimensions of this shape + */ +public fun ShapeND.last(n: Int): ShapeND = ShapeND(array.copyOfRange(size - n, size)) + +public fun ShapeND.first(): Int = array.first() + +/** + * A shape including first [n] dimensions of this shape + */ +public fun ShapeND.first(n: Int): ShapeND = ShapeND(array.copyOfRange(0, n)) + +public operator fun ShapeND.plus(add: IntArray): ShapeND = ShapeND(array + add) + +public operator fun ShapeND.plus(add: ShapeND): ShapeND = ShapeND(array + add.array) + +public fun ShapeND.isEmpty(): Boolean = size == 0 +public fun ShapeND.isNotEmpty(): Boolean = size > 0 + +public fun ShapeND.transposed(i: Int, j: Int): ShapeND = ShapeND(array.copyOf().apply { + val ith = get(i) + val jth = get(j) + set(i, jth) + set(j, ith) +}) + +public operator fun ShapeND.component1(): Int = get(0) +public operator fun ShapeND.component2(): Int = get(1) +public operator fun ShapeND.component3(): Int = get(2) + +/** + * Convert to array with protective copy + */ +public fun ShapeND.toArray(): IntArray = array.copyOf() + +@UnsafeKMathAPI +public fun ShapeND.asArray(): IntArray = array + +public fun ShapeND.asList(): List = array.asList() + + +/** + * An exception is thrown when the expected and actual shape of NDArray differ. + * + * @property expected the expected shape. + * @property actual the actual shape. + */ +public class ShapeMismatchException(public val expected: ShapeND, public val actual: ShapeND) : + RuntimeException("Shape $actual doesn't fit in expected shape ${expected}.") + +public class IndexOutOfShapeException(public val shape: ShapeND, public val index: IntArray) : + RuntimeException("Index ${index.contentToString()} is out of shape ${shape}") + +public fun ShapeND(shapeFirst: Int, vararg shapeRest: Int): ShapeND = ShapeND(intArrayOf(shapeFirst, *shapeRest)) + +public interface WithShape { + public val shape: ShapeND + + public val indices: ShapeIndexer get() = ColumnStrides(shape) +} + +internal fun requireIndexInShape(index: IntArray, shape: ShapeND) { + if (index.size != shape.size) throw IndexOutOfShapeException(shape, index) + shape.forEachIndexed { axis, axisShape -> + if (index[axis] !in 0 until axisShape) throw IndexOutOfShapeException(shape, index) + } +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt index d34c722a1..34d748b3f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt @@ -18,7 +18,7 @@ public sealed class ShortRingOpsND : BufferedRingOpsND(ShortRi @OptIn(UnstableKMathAPI::class) public class ShortRingND( - override val shape: Shape + override val shape: ShapeND ) : ShortRingOpsND(), RingND, NumbersAddOps> { override fun number(value: Number): BufferND { @@ -30,5 +30,5 @@ public class ShortRingND( public inline fun ShortRing.withNdAlgebra(vararg shape: Int, action: ShortRingND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return ShortRingND(Shape(shape)).run(action) + return ShortRingND(ShapeND(shape)).run(action) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 51a3d7fd0..ba48e25ce 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -46,7 +46,7 @@ public interface MutableStructure1D : Structure1D, MutableStructureND, */ @JvmInline private value class Structure1DWrapper(val structure: StructureND) : Structure1D { - override val shape: Shape get() = structure.shape + override val shape: ShapeND get() = structure.shape override val size: Int get() = structure.shape[0] @PerformancePitfall @@ -60,7 +60,7 @@ private value class Structure1DWrapper(val structure: StructureND) : S * A 1D wrapper for a mutable nd-structure */ private class MutableStructure1DWrapper(val structure: MutableStructureND) : MutableStructure1D { - override val shape: Shape get() = structure.shape + override val shape: ShapeND get() = structure.shape override val size: Int get() = structure.shape[0] @PerformancePitfall @@ -90,7 +90,7 @@ private class MutableStructure1DWrapper(val structure: MutableStructureND) */ @JvmInline private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D { - override val shape: Shape get() = Shape(buffer.size) + override val shape: ShapeND get() = ShapeND(buffer.size) override val size: Int get() = buffer.size @PerformancePitfall @@ -102,7 +102,7 @@ private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D< } internal class MutableBuffer1DWrapper(val buffer: MutableBuffer) : MutableStructure1D { - override val shape: Shape get() = Shape(buffer.size) + override val shape: ShapeND get() = ShapeND(buffer.size) override val size: Int get() = buffer.size @PerformancePitfall diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index d10c43c25..a9c6c2748 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -29,7 +29,7 @@ public interface Structure2D : StructureND { */ public val colNum: Int - override val shape: Shape get() = Shape(rowNum, colNum) + override val shape: ShapeND get() = ShapeND(rowNum, colNum) /** * The buffer of rows of this structure. It gets elements from the structure dynamically. @@ -102,7 +102,7 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { */ @JvmInline private value class Structure2DWrapper(val structure: StructureND) : Structure2D { - override val shape: Shape get() = structure.shape + override val shape: ShapeND get() = structure.shape override val rowNum: Int get() = shape[0] override val colNum: Int get() = shape[1] @@ -120,7 +120,7 @@ private value class Structure2DWrapper(val structure: StructureND) : S * A 2D wrapper for a mutable nd-structure */ private class MutableStructure2DWrapper(val structure: MutableStructureND) : MutableStructure2D { - override val shape: Shape get() = structure.shape + override val shape: ShapeND get() = structure.shape override val rowNum: Int get() = shape[0] override val colNum: Int get() = shape[1] diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index baea5da15..c96843651 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -33,7 +33,7 @@ public interface StructureND : Featured, WithShape { * The shape of structure i.e., non-empty sequence of non-negative integers that specify sizes of dimensions of * this structure. */ - override val shape: Shape + override val shape: ShapeND /** * The count of dimensions in this structure. It should be equal to size of [shape]. @@ -147,13 +147,13 @@ public interface StructureND : Featured, WithShape { ): BufferND = BufferND(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) }) public fun buffered( - shape: Shape, + shape: ShapeND, bufferFactory: BufferFactory = BufferFactory.boxing(), initializer: (IntArray) -> T, ): BufferND = buffered(ColumnStrides(shape), bufferFactory, initializer) public inline fun auto( - shape: Shape, + shape: ShapeND, crossinline initializer: (IntArray) -> T, ): BufferND = auto(ColumnStrides(shape), initializer) @@ -162,13 +162,13 @@ public interface StructureND : Featured, WithShape { vararg shape: Int, crossinline initializer: (IntArray) -> T, ): BufferND = - auto(ColumnStrides(Shape(shape)), initializer) + auto(ColumnStrides(ShapeND(shape)), initializer) public inline fun auto( type: KClass, vararg shape: Int, crossinline initializer: (IntArray) -> T, - ): BufferND = auto(type, ColumnStrides(Shape(shape)), initializer) + ): BufferND = auto(type, ColumnStrides(ShapeND(shape)), initializer) } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt index e5edeef7f..4932dca41 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI public open class VirtualStructureND( - override val shape: Shape, + override val shape: ShapeND, public val producer: (IntArray) -> T, ) : StructureND { @@ -22,12 +22,12 @@ public open class VirtualStructureND( @UnstableKMathAPI public class VirtualDoubleStructureND( - shape: Shape, + shape: ShapeND, producer: (IntArray) -> Double, ) : VirtualStructureND(shape, producer) @UnstableKMathAPI public class VirtualIntStructureND( - shape: Shape, + shape: ShapeND, producer: (IntArray) -> Int, ) : VirtualStructureND(shape, producer) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/algebraNDExtentions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/algebraNDExtentions.kt index 1b7bd20db..f0d4bd7f5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/algebraNDExtentions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/algebraNDExtentions.kt @@ -15,9 +15,9 @@ public fun > AlgebraND.structureND( shapeFirst: Int, vararg shapeRest: Int, initializer: A.(IntArray) -> T -): StructureND = structureND(Shape(shapeFirst, *shapeRest), initializer) +): StructureND = structureND(ShapeND(shapeFirst, *shapeRest), initializer) -public fun > AlgebraND.zero(shape: Shape): StructureND = structureND(shape) { zero } +public fun > AlgebraND.zero(shape: ShapeND): StructureND = structureND(shape) { zero } @JvmName("zeroVarArg") public fun > AlgebraND.zero( @@ -25,7 +25,7 @@ public fun > AlgebraND.zero( vararg shapeRest: Int, ): StructureND = structureND(shapeFirst, *shapeRest) { zero } -public fun > AlgebraND.one(shape: Shape): StructureND = structureND(shape) { one } +public fun > AlgebraND.one(shape: ShapeND): StructureND = structureND(shape) { one } @JvmName("oneVarArg") public fun > AlgebraND.one( diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt index b1b6fba9f..48f3e919b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt @@ -28,7 +28,7 @@ internal class BufferAccessor2D( //TODO optimize wrapper fun MutableBuffer.collect(): Structure2D = StructureND.buffered( - ColumnStrides(Shape(rowNum, colNum)), + ColumnStrides(ShapeND(rowNum, colNum)), factory ) { (i, j) -> get(i, j) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt index 7044eb930..e6335f652 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt @@ -10,7 +10,7 @@ import kotlin.test.Test class StridesTest { @Test fun checkRowBasedStrides() { - val strides = RowStrides(Shape(3, 3)) + val strides = RowStrides(ShapeND(3, 3)) var counter = 0 for(i in 0..2){ for(j in 0..2){ @@ -24,7 +24,7 @@ class StridesTest { @Test fun checkColumnBasedStrides() { - val strides = ColumnStrides(Shape(3, 3)) + val strides = ColumnStrides(ShapeND(3, 3)) var counter = 0 for(i in 0..2){ for(j in 0..2){ diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt index 97e27df96..1f717658e 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt @@ -9,12 +9,12 @@ import kotlinx.coroutines.* import space.kscience.kmath.coroutines.Math import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.ColumnStrides -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND public class LazyStructureND( public val scope: CoroutineScope, - override val shape: Shape, + override val shape: ShapeND, public val function: suspend (IntArray) -> T, ) : StructureND { private val cache: MutableMap> = HashMap() @@ -35,20 +35,24 @@ public class LazyStructureND( } } +@OptIn(PerformancePitfall::class) public fun StructureND.async(index: IntArray): Deferred = if (this is LazyStructureND) this@async.async(index) else CompletableDeferred(get(index)) +@OptIn(PerformancePitfall::class) public suspend fun StructureND.await(index: IntArray): T = if (this is LazyStructureND) await(index) else get(index) /** * PENDING would benefit from KEEP-176 */ +@OptIn(PerformancePitfall::class) public inline fun StructureND.mapAsyncIndexed( scope: CoroutineScope, crossinline function: suspend (T, index: IntArray) -> R, ): LazyStructureND = LazyStructureND(scope, shape) { index -> function(get(index), index) } +@OptIn(PerformancePitfall::class) public inline fun StructureND.mapAsync( scope: CoroutineScope, crossinline function: suspend (T) -> R, diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt index 30c84d848..dde2d4fcf 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.dimensions import space.kscience.kmath.linear.* -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Ring @@ -48,7 +48,7 @@ public interface DMatrix : Structure2D { public value class DMatrixWrapper( private val structure: Structure2D, ) : DMatrix { - override val shape: Shape get() = structure.shape + override val shape: ShapeND get() = structure.shape override val rowNum: Int get() = shape[0] override val colNum: Int get() = shape[1] override operator fun get(i: Int, j: Int): T = structure[i, j] diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/HistogramND.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/HistogramND.kt index 06320c8d9..623452422 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/HistogramND.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/HistogramND.kt @@ -10,7 +10,7 @@ import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.FieldOpsND -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.ScaleOperations @@ -45,7 +45,7 @@ public class HistogramND, D : Domain, V : Any>( */ public interface HistogramGroupND, D : Domain, V : Any> : Group>, ScaleOperations> { - public val shape: Shape + public val shape: ShapeND public val valueAlgebraND: FieldOpsND //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape), /** diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt index cf8b59087..f22ea9776 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt @@ -39,7 +39,7 @@ public class UniformHistogramGroupND>( public val dimension: Int get() = lower.size - override val shape: Shape = Shape(IntArray(binNums.size) { binNums[it] + 2 }) + override val shape: ShapeND = ShapeND(IntArray(binNums.size) { binNums[it] + 2 }) private val binSize = DoubleBuffer(dimension) { (upper[it] - lower[it]) / binNums[it] } diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt index 88c004c7b..ae526873d 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt @@ -7,13 +7,13 @@ package space.kscience.kmath.multik import org.jetbrains.kotlinx.multik.ndarray.data.* import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.tensors.api.Tensor import kotlin.jvm.JvmInline @JvmInline public value class MultikTensor(public val array: MutableMultiArray) : Tensor { - override val shape: Shape get() = Shape(array.shape) + override val shape: ShapeND get() = ShapeND(array.shape) @PerformancePitfall override fun get(index: IntArray): T = array[index] diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt index 99cbc3193..1736b48e3 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt @@ -32,7 +32,7 @@ public abstract class MultikTensorAlgebra>( protected val multikStat: Statistics = multikEngine.getStatistics() @OptIn(UnsafeKMathAPI::class) - override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): MultikTensor { + override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): MultikTensor { val strides = ColumnStrides(shape) val memoryView = initMemoryView(strides.linearSize, type) strides.asSequence().forEachIndexed { linearIndex, tensorIndex -> @@ -123,7 +123,7 @@ public abstract class MultikTensorAlgebra>( public fun MutableMultiArray.wrap(): MultikTensor = MultikTensor(this.asDNArray()) @OptIn(PerformancePitfall::class) - override fun StructureND.valueOrNull(): T? = if (shape contentEquals Shape(1)) { + override fun StructureND.valueOrNull(): T? = if (shape contentEquals ShapeND(1)) { get(intArrayOf(0)) } else null @@ -211,7 +211,7 @@ public abstract class MultikTensorAlgebra>( override fun StructureND.transposed(i: Int, j: Int): MultikTensor = asMultik().array.transpose(i, j).wrap() - override fun Tensor.view(shape: Shape): MultikTensor { + override fun Tensor.view(shape: ShapeND): MultikTensor { require(shape.asList().all { it > 0 }) require(shape.linearSize == this.shape.size) { "Cannot reshape array of size ${this.shape.size} into a new shape ${ @@ -223,7 +223,7 @@ public abstract class MultikTensorAlgebra>( } val mt = asMultik().array - return if (Shape(mt.shape).contentEquals(shape)) { + return if (ShapeND(mt.shape).contentEquals(shape)) { mt } else { @OptIn(UnsafeKMathAPI::class) diff --git a/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt index de54af732..afd292904 100644 --- a/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt +++ b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.multik import org.jetbrains.kotlinx.multik.default.DefaultEngine import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField @@ -29,8 +29,8 @@ internal class MultikNDTest { fun dotResult() { val dim = 100 - val tensor1 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12224) - val tensor2 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12225) + val tensor1 = DoubleTensorAlgebra.randomNormal(shape = ShapeND(dim, dim), 12224) + val tensor2 = DoubleTensorAlgebra.randomNormal(shape = ShapeND(dim, dim), 12225) val multikResult = with(multikAlgebra) { tensor1 dot tensor2 diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index 7654ec9ce..6f01233d7 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -33,7 +33,8 @@ public sealed interface Nd4jArrayAlgebra> : AlgebraND.ndArray: INDArray - override fun structureND(shape: Shape, initializer: C.(IntArray) -> T): Nd4jArrayStructure { + @OptIn(PerformancePitfall::class) + override fun structureND(shape: ShapeND, initializer: C.(IntArray) -> T): Nd4jArrayStructure { @OptIn(UnsafeKMathAPI::class) val struct: Nd4jArrayStructure = Nd4j.create(*shape.asArray())!!.wrap() struct.indicesIterator().forEach { struct[it] = elementAlgebra.initializer(it) } @@ -224,10 +225,10 @@ public open class DoubleNd4jArrayFieldOps : Nd4jArrayExtendedFieldOps +public class DoubleNd4jArrayField(override val shape: ShapeND) : DoubleNd4jArrayFieldOps(), FieldND public fun DoubleField.nd4j(shapeFirst: Int, vararg shapeRest: Int): DoubleNd4jArrayField = - DoubleNd4jArrayField(Shape(shapeFirst, * shapeRest)) + DoubleNd4jArrayField(ShapeND(shapeFirst, * shapeRest)) /** @@ -271,12 +272,12 @@ public open class FloatNd4jArrayFieldOps : Nd4jArrayExtendedFieldOps +public class FloatNd4jArrayField(override val shape: ShapeND) : FloatNd4jArrayFieldOps(), RingND public val FloatField.nd4j: FloatNd4jArrayFieldOps get() = FloatNd4jArrayFieldOps public fun FloatField.nd4j(shapeFirst: Int, vararg shapeRest: Int): FloatNd4jArrayField = - FloatNd4jArrayField(Shape(shapeFirst, * shapeRest)) + FloatNd4jArrayField(ShapeND(shapeFirst, * shapeRest)) /** * Represents [RingND] over [Nd4jArrayIntStructure]. @@ -312,7 +313,7 @@ public open class IntNd4jArrayRingOps : Nd4jArrayRingOps { public val IntRing.nd4j: IntNd4jArrayRingOps get() = IntNd4jArrayRingOps -public class IntNd4jArrayRing(override val shape: Shape) : IntNd4jArrayRingOps(), RingND +public class IntNd4jArrayRing(override val shape: ShapeND) : IntNd4jArrayRingOps(), RingND public fun IntRing.nd4j(shapeFirst: Int, vararg shapeRest: Int): IntNd4jArrayRing = - IntNd4jArrayRing(Shape(shapeFirst, * shapeRest)) \ No newline at end of file + IntNd4jArrayRing(ShapeND(shapeFirst, * shapeRest)) \ No newline at end of file diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt index 60c865a02..a1405ccfb 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt @@ -21,7 +21,7 @@ public sealed class Nd4jArrayStructure : MutableStructureND { */ public abstract val ndArray: INDArray - override val shape: Shape get() = Shape(ndArray.shape().toIntArray()) + override val shape: ShapeND get() = ShapeND(ndArray.shape().toIntArray()) internal abstract fun elementsIterator(): Iterator> internal fun indicesIterator(): Iterator = ndArray.indicesIterator() diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt index d505b3c0e..62bfe90ba 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt @@ -37,7 +37,7 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe */ public val StructureND.ndArray: INDArray - override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): Nd4jArrayStructure + override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): Nd4jArrayStructure @OptIn(PerformancePitfall::class) override fun StructureND.map(transform: A.(T) -> T): Nd4jArrayStructure = @@ -108,7 +108,7 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe ndArray.max(keepDim, dim).wrap() @OptIn(UnsafeKMathAPI::class) - override fun Tensor.view(shape: Shape): Nd4jArrayStructure = ndArray.reshape(shape.asArray()).wrap() + override fun Tensor.view(shape: ShapeND): Nd4jArrayStructure = ndArray.reshape(shape.asArray()).wrap() override fun Tensor.viewAs(other: StructureND): Nd4jArrayStructure = view(other.shape) @@ -178,7 +178,7 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra { override fun INDArray.wrap(): Nd4jArrayStructure = asDoubleStructure() @OptIn(UnsafeKMathAPI::class) - override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): Nd4jArrayStructure { + override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): Nd4jArrayStructure { val array: INDArray = Nd4j.zeros(*shape.asArray()) val indices = ColumnStrides(shape) indices.asSequence().forEach { index -> @@ -198,7 +198,7 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra { } override fun StructureND.valueOrNull(): Double? = - if (shape contentEquals Shape(1)) ndArray.getDouble(0) else null + if (shape contentEquals ShapeND(1)) ndArray.getDouble(0) else null // TODO rewrite override fun diagonalEmbedding( diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt index 674485fd1..27a20aafe 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt @@ -14,7 +14,7 @@ import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.ColumnStrides -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.PowerOperations @@ -28,7 +28,7 @@ public class DoubleTensorFlowOutput( } -internal fun Shape.toLongArray(): LongArray = LongArray(size) { get(it).toLong() } +internal fun ShapeND.toLongArray(): LongArray = LongArray(size) { get(it).toLong() } public class DoubleTensorFlowAlgebra internal constructor( graph: Graph, @@ -37,7 +37,7 @@ public class DoubleTensorFlowAlgebra internal constructor( override val elementAlgebra: DoubleField get() = DoubleField override fun structureND( - shape: Shape, + shape: ShapeND, initializer: DoubleField.(IntArray) -> Double, ): StructureND { val res = TFloat64.tensorOf(org.tensorflow.ndarray.Shape.of(*shape.toLongArray())) { array -> diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt index a1e0335f8..435b01b80 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt @@ -20,7 +20,7 @@ import org.tensorflow.types.family.TType import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnsafeKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.asArray import space.kscience.kmath.nd.contentEquals @@ -41,12 +41,14 @@ public sealed interface TensorFlowTensor : Tensor */ @JvmInline public value class TensorFlowArray(public val tensor: NdArray) : Tensor { - override val shape: Shape get() = Shape(tensor.shape().asArray().toIntArray()) + override val shape: ShapeND get() = ShapeND(tensor.shape().asArray().toIntArray()) + @PerformancePitfall override fun get(index: IntArray): T = tensor.getObject(*index.toLongArray()) //TODO implement native element sequence + @PerformancePitfall override fun set(index: IntArray, value: T) { tensor.setObject(value, *index.toLongArray()) } @@ -65,7 +67,7 @@ public abstract class TensorFlowOutput( public var output: Output = output internal set - override val shape: Shape get() = Shape(output.shape().asArray().toIntArray()) + override val shape: ShapeND get() = ShapeND(output.shape().asArray().toIntArray()) protected abstract fun org.tensorflow.Tensor.actualizeTensor(): NdArray @@ -99,7 +101,7 @@ public abstract class TensorFlowAlgebra> internal c protected abstract fun const(value: T): Constant - override fun StructureND.valueOrNull(): T? = if (shape contentEquals Shape(1)) + override fun StructureND.valueOrNull(): T? = if (shape contentEquals ShapeND(1)) get(intArrayOf(0)) else null /** @@ -195,7 +197,7 @@ public abstract class TensorFlowAlgebra> internal c ops.linalg.transpose(it, ops.constant(intArrayOf(i, j))) } - override fun Tensor.view(shape: Shape): Tensor = operate { + override fun Tensor.view(shape: ShapeND): Tensor = operate { @OptIn(UnsafeKMathAPI::class) ops.reshape(it, ops.constant(shape.asArray())) } diff --git a/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt b/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt index 44a594299..ff11dc8fe 100644 --- a/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt +++ b/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.tensorflow import org.junit.jupiter.api.Test import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.get import space.kscience.kmath.nd.structureND import space.kscience.kmath.operations.DoubleField @@ -32,8 +32,8 @@ class DoubleTensorFlowOps { fun dot(){ val dim = 1000 - val tensor1 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12224) - val tensor2 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12225) + val tensor1 = DoubleTensorAlgebra.randomNormal(shape = ShapeND(dim, dim), 12224) + val tensor2 = DoubleTensorAlgebra.randomNormal(shape = ShapeND(dim, dim), 12225) DoubleField.produceWithTF { tensor1 dot tensor2 diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index ec5d6f5e6..f923400c5 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.api import space.kscience.kmath.nd.RingOpsND -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.Ring @@ -193,7 +193,7 @@ public interface TensorAlgebra> : RingOpsND { * @param shape the desired size * @return tensor with new shape */ - public fun Tensor.view(shape: Shape): Tensor + public fun Tensor.view(shape: ShapeND): Tensor /** * View this tensor as the same size as [other]. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index c4266c669..a7283e4c8 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.RowStrides -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.Strides import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.tensors.api.Tensor @@ -16,7 +16,7 @@ import space.kscience.kmath.tensors.api.Tensor * Represents [Tensor] over a [MutableBuffer] intended to be used through [DoubleTensor] and [IntTensor] */ public abstract class BufferedTensor( - override val shape: Shape, + override val shape: ShapeND, ) : Tensor { public abstract val source: MutableBuffer diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt index 3dfea7f8a..12e9549da 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt @@ -84,7 +84,7 @@ public inline fun OffsetDoubleBuffer.mapInPlace(operation: (Double) -> Double) { * [DoubleTensor] always uses row-based strides */ public class DoubleTensor( - shape: Shape, + shape: ShapeND, override val source: OffsetDoubleBuffer, ) : BufferedTensor(shape), MutableStructureNDOfDouble { @@ -92,7 +92,7 @@ public class DoubleTensor( require(linearSize == source.size) { "Source buffer size must be equal tensor size" } } - public constructor(shape: Shape, buffer: DoubleBuffer) : this(shape, OffsetDoubleBuffer(buffer, 0, buffer.size)) + public constructor(shape: ShapeND, buffer: DoubleBuffer) : this(shape, OffsetDoubleBuffer(buffer, 0, buffer.size)) @OptIn(PerformancePitfall::class) @@ -147,7 +147,7 @@ public value class DoubleTensor2D(public val tensor: DoubleTensor) : MutableStru override fun elements(): Sequence> = tensor.elements() @OptIn(PerformancePitfall::class) override fun get(index: IntArray): Double = tensor[index] - override val shape: Shape get() = tensor.shape + override val shape: ShapeND get() = tensor.shape } public fun DoubleTensor.asDoubleTensor2D(): DoubleTensor2D = DoubleTensor2D(this) @@ -162,7 +162,7 @@ public inline fun DoubleTensor.forEachMatrix(block: (index: IntArray, matrix: Do val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } val matrixOffset = shape[n - 1] * shape[n - 2] - val matrixShape = Shape(shape[n - 2], shape[n - 1]) + val matrixShape = ShapeND(shape[n - 2], shape[n - 1]) val size = matrixShape.linearSize for (i in 0 until linearSize / matrixOffset) { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index a022f31a6..ce1778013 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -92,7 +92,7 @@ public open class DoubleTensorAlgebra : override fun StructureND.valueOrNull(): Double? { val dt = asDoubleTensor() - return if (dt.shape contentEquals Shape(1)) dt.source[0] else null + return if (dt.shape contentEquals ShapeND(1)) dt.source[0] else null } override fun StructureND.value(): Double = valueOrNull() @@ -105,7 +105,7 @@ public open class DoubleTensorAlgebra : * @param array one-dimensional data array. * @return tensor with the [shape] shape and [array] data. */ - public fun fromArray(shape: Shape, array: DoubleArray): DoubleTensor { + public fun fromArray(shape: ShapeND, array: DoubleArray): DoubleTensor { checkNotEmptyShape(shape) checkEmptyDoubleBuffer(array) checkBufferShapeConsistency(shape, array) @@ -119,7 +119,7 @@ public open class DoubleTensorAlgebra : * @param initializer mapping tensor indices to values. * @return tensor with the [shape] shape and data generated by the [initializer]. */ - override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray( + override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray( shape, RowStrides(shape).asSequence().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray() ) @@ -127,7 +127,7 @@ public open class DoubleTensorAlgebra : override fun Tensor.getTensor(i: Int): DoubleTensor { val dt = asDoubleTensor() val lastShape = shape.last(shape.size - 1) - val newShape: Shape = if (lastShape.isNotEmpty()) lastShape else Shape(1) + val newShape: ShapeND = if (lastShape.isNotEmpty()) lastShape else ShapeND(1) return DoubleTensor( newShape, dt.source.view(newShape.linearSize * i, newShape.linearSize) @@ -141,7 +141,7 @@ public open class DoubleTensorAlgebra : * @param shape array of integers defining the shape of the output tensor. * @return tensor with the [shape] shape and filled with [value]. */ - public fun full(value: Double, shape: Shape): DoubleTensor { + public fun full(value: Double, shape: ShapeND): DoubleTensor { checkNotEmptyShape(shape) val buffer = DoubleBuffer(shape.linearSize) { value } return DoubleTensor(shape, buffer) @@ -165,7 +165,7 @@ public open class DoubleTensorAlgebra : * @param shape array of integers defining the shape of the output tensor. * @return tensor filled with the scalar value `0.0`, with the [shape] shape. */ - public fun zeros(shape: Shape): DoubleTensor = full(0.0, shape) + public fun zeros(shape: ShapeND): DoubleTensor = full(0.0, shape) /** * Returns a tensor filled with the scalar value `0.0`, with the same shape as a given array. @@ -180,7 +180,7 @@ public open class DoubleTensorAlgebra : * @param shape array of integers defining the shape of the output tensor. * @return tensor filled with the scalar value `1.0`, with the [shape] shape. */ - public fun ones(shape: Shape): DoubleTensor = full(1.0, shape) + public fun ones(shape: ShapeND): DoubleTensor = full(1.0, shape) /** * Returns a tensor filled with the scalar value `1.0`, with the same shape as a given array. @@ -196,7 +196,7 @@ public open class DoubleTensorAlgebra : * @return a 2-D tensor with ones on the diagonal and zeros elsewhere. */ public fun eye(n: Int): DoubleTensor { - val shape = Shape(n, n) + val shape = ShapeND(n, n) val buffer = DoubleBuffer(n * n) { 0.0 } val res = DoubleTensor(shape, buffer) for (i in 0 until n) { @@ -306,7 +306,7 @@ public open class DoubleTensorAlgebra : // return resTensor } - override fun Tensor.view(shape: Shape): DoubleTensor { + override fun Tensor.view(shape: ShapeND): DoubleTensor { checkView(asDoubleTensor(), shape) return DoubleTensor(shape, asDoubleTensor().source) } @@ -346,7 +346,7 @@ public open class DoubleTensorAlgebra : @UnstableKMathAPI public infix fun StructureND.matmul(other: StructureND): DoubleTensor { if (shape.size == 1 && other.shape.size == 1) { - return DoubleTensor(Shape(1), DoubleBuffer(times(other).sum())) + return DoubleTensor(ShapeND(1), DoubleBuffer(times(other).sum())) } var penultimateDim = false @@ -358,7 +358,7 @@ public open class DoubleTensorAlgebra : if (shape.size == 1) { penultimateDim = true - newThis = newThis.view(Shape(1) + shape) + newThis = newThis.view(ShapeND(1) + shape) } if (other.shape.size == 1) { @@ -396,7 +396,7 @@ public open class DoubleTensorAlgebra : // } return if (penultimateDim) { - resTensor.view(resTensor.shape.first(resTensor.shape.size - 2) + Shape(resTensor.shape.last())) + resTensor.view(resTensor.shape.first(resTensor.shape.size - 2) + ShapeND(resTensor.shape.last())) } else if (lastDim) { resTensor.view(resTensor.shape.first(resTensor.shape.size - 1)) } else { @@ -506,7 +506,7 @@ public open class DoubleTensorAlgebra : * @return tensor of a given shape filled with numbers from the normal distribution * with `0.0` mean and `1.0` standard deviation. */ - public fun randomNormal(shape: Shape, seed: Long = 0): DoubleTensor = + public fun randomNormal(shape: ShapeND, seed: Long = 0): DoubleTensor = DoubleTensor(shape, DoubleBuffer.randomNormals(shape.linearSize, seed)) /** @@ -531,7 +531,7 @@ public open class DoubleTensorAlgebra : check(tensors.isNotEmpty()) { "List must have at least 1 element" } val shape = tensors[0].shape check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } - val resShape = Shape(tensors.size) + shape + val resShape = ShapeND(tensors.size) + shape // val resBuffer: List = tensors.flatMap { // it.asDoubleTensor().source.array.drop(it.asDoubleTensor().bufferStart) // .take(it.asDoubleTensor().linearSize) @@ -685,9 +685,9 @@ public open class DoubleTensorAlgebra : check(tensors.isNotEmpty()) { "List must have at least 1 element" } val n = tensors.size val m = tensors[0].shape[0] - check(tensors.all { it.shape contentEquals Shape(m) }) { "Tensors must have same shapes" } + check(tensors.all { it.shape contentEquals ShapeND(m) }) { "Tensors must have same shapes" } val resTensor = DoubleTensor( - Shape(n, n), + ShapeND(n, n), DoubleBuffer(n * n) { 0.0 } ) for (i in 0 until n) { @@ -875,9 +875,9 @@ public open class DoubleTensorAlgebra : val size = dimension val commonShape = shape.slice(0 until size - 2) val (n, m) = shape.slice(size - 2 until size) - val uTensor = zeros(commonShape + Shape(min(n, m), n)) - val sTensor = zeros(commonShape + Shape(min(n, m))) - val vTensor = zeros(commonShape + Shape(min(n, m), m)) + val uTensor = zeros(commonShape + ShapeND(min(n, m), n)) + val sTensor = zeros(commonShape + ShapeND(min(n, m))) + val vTensor = zeros(commonShape + ShapeND(min(n, m), m)) val matrices = asDoubleTensor().matrices val uTensors = uTensor.matrices @@ -988,7 +988,7 @@ public open class DoubleTensorAlgebra : val n = shape.size - val detTensorShape = Shape(IntArray(n - 1) { i -> shape[i] }.apply { + val detTensorShape = ShapeND(IntArray(n - 1) { i -> shape[i] }.apply { set(n - 2, 1) }) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt index a99773f84..a77c4de4c 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.structures.* /** @@ -75,7 +75,7 @@ public inline fun OffsetIntBuffer.mapInPlace(operation: (Int) -> Int) { * Default [BufferedTensor] implementation for [Int] values */ public class IntTensor( - shape: Shape, + shape: ShapeND, override val source: OffsetIntBuffer, ) : BufferedTensor(shape) { @@ -83,7 +83,7 @@ public class IntTensor( require(linearSize == source.size) { "Source buffer size must be equal tensor size" } } - public constructor(shape: Shape, buffer: IntBuffer) : this(shape, OffsetIntBuffer(buffer, 0, buffer.size)) + public constructor(shape: ShapeND, buffer: IntBuffer) : this(shape, OffsetIntBuffer(buffer, 0, buffer.size)) @OptIn(PerformancePitfall::class) override fun get(index: IntArray): Int = this.source[indices.offset(index)] diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt index 86199d19b..429b3ffa9 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt @@ -89,7 +89,7 @@ public open class IntTensorAlgebra : TensorAlgebra { override fun StructureND.valueOrNull(): Int? { val dt = asIntTensor() - return if (dt.shape contentEquals Shape(1)) dt.source[0] else null + return if (dt.shape contentEquals ShapeND(1)) dt.source[0] else null } override fun StructureND.value(): Int = valueOrNull() @@ -102,7 +102,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @param array one-dimensional data array. * @return tensor with the [shape] shape and [array] data. */ - public fun fromArray(shape: Shape, array: IntArray): IntTensor { + public fun fromArray(shape: ShapeND, array: IntArray): IntTensor { checkNotEmptyShape(shape) check(array.isNotEmpty()) { "Illegal empty buffer provided" } check(array.size == shape.linearSize) { @@ -118,7 +118,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @param initializer mapping tensor indices to values. * @return tensor with the [shape] shape and data generated by the [initializer]. */ - override fun structureND(shape: Shape, initializer: IntRing.(IntArray) -> Int): IntTensor = fromArray( + override fun structureND(shape: ShapeND, initializer: IntRing.(IntArray) -> Int): IntTensor = fromArray( shape, RowStrides(shape).asSequence().map { IntRing.initializer(it) }.toMutableList().toIntArray() ) @@ -126,7 +126,7 @@ public open class IntTensorAlgebra : TensorAlgebra { override fun Tensor.getTensor(i: Int): IntTensor { val dt = asIntTensor() val lastShape = shape.last(shape.size - 1) - val newShape = if (lastShape.isNotEmpty()) lastShape else Shape(1) + val newShape = if (lastShape.isNotEmpty()) lastShape else ShapeND(1) return IntTensor(newShape, dt.source.view(newShape.linearSize * i)) } @@ -137,7 +137,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @param shape array of integers defining the shape of the output tensor. * @return tensor with the [shape] shape and filled with [value]. */ - public fun full(value: Int, shape: Shape): IntTensor { + public fun full(value: Int, shape: ShapeND): IntTensor { checkNotEmptyShape(shape) val buffer = IntBuffer(shape.linearSize) { value } return IntTensor(shape, buffer) @@ -161,7 +161,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @param shape array of integers defining the shape of the output tensor. * @return tensor filled with the scalar value `0`, with the [shape] shape. */ - public fun zeros(shape: Shape): IntTensor = full(0, shape) + public fun zeros(shape: ShapeND): IntTensor = full(0, shape) /** * Returns a tensor filled with the scalar value `0`, with the same shape as a given array. @@ -176,7 +176,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @param shape array of integers defining the shape of the output tensor. * @return tensor filled with the scalar value `1`, with the [shape] shape. */ - public fun ones(shape: Shape): IntTensor = full(1, shape) + public fun ones(shape: ShapeND): IntTensor = full(1, shape) /** * Returns a tensor filled with the scalar value `1`, with the same shape as a given array. @@ -192,7 +192,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @return a 2-D tensor with ones on the diagonal and zeros elsewhere. */ public fun eye(n: Int): IntTensor { - val shape = Shape(n, n) + val shape = ShapeND(n, n) val buffer = IntBuffer(n * n) { 0 } val res = IntTensor(shape, buffer) for (i in 0 until n) { @@ -287,7 +287,7 @@ public open class IntTensorAlgebra : TensorAlgebra { // return resTensor } - override fun Tensor.view(shape: Shape): IntTensor { + override fun Tensor.view(shape: ShapeND): IntTensor { checkView(asIntTensor(), shape) return IntTensor(shape, asIntTensor().source) } @@ -388,7 +388,7 @@ public open class IntTensorAlgebra : TensorAlgebra { check(tensors.isNotEmpty()) { "List must have at least 1 element" } val shape = tensors[0].shape check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } - val resShape = Shape(tensors.size) + shape + val resShape = ShapeND(tensors.size) + shape // val resBuffer: List = tensors.flatMap { // it.asIntTensor().source.array.drop(it.asIntTensor().bufferStart) // .take(it.asIntTensor().linearSize) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt index dcb16b755..0b0325a85 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt @@ -32,7 +32,7 @@ internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTenso } } -internal fun broadcastShapes(shapes: List): Shape { +internal fun broadcastShapes(shapes: List): ShapeND { var totalDim = 0 for (shape in shapes) { totalDim = max(totalDim, shape.size) @@ -57,10 +57,10 @@ internal fun broadcastShapes(shapes: List): Shape { } } - return Shape(totalShape) + return ShapeND(totalShape) } -internal fun broadcastTo(tensor: DoubleTensor, newShape: Shape): DoubleTensor { +internal fun broadcastTo(tensor: DoubleTensor, newShape: ShapeND): DoubleTensor { require(tensor.shape.size <= newShape.size) { "Tensor is not compatible with the new shape" } @@ -120,7 +120,7 @@ internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List 0) { "Illegal empty shape provided" } @@ -24,7 +24,7 @@ internal fun checkEmptyDoubleBuffer(buffer: DoubleArray) = check(buffer.isNotEmp "Illegal empty buffer provided" } -internal fun checkBufferShapeConsistency(shape: Shape, buffer: DoubleArray) = +internal fun checkBufferShapeConsistency(shape: ShapeND, buffer: DoubleArray) = check(buffer.size == shape.linearSize) { "Inconsistent shape ${shape} for buffer of size ${buffer.size} provided" } @@ -40,10 +40,10 @@ internal fun checkTranspose(dim: Int, i: Int, j: Int) = "Cannot transpose $i to $j for a tensor of dim $dim" } -internal fun checkView(a: Tensor, shape: Shape) = +internal fun checkView(a: Tensor, shape: ShapeND) = check(a.shape.linearSize == shape.linearSize) -internal fun checkSquareMatrix(shape: Shape) { +internal fun checkSquareMatrix(shape: ShapeND) { val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n instead" diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt index 1c6e5edfb..a293c8da3 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt @@ -156,7 +156,7 @@ internal val DoubleTensor.vectors: List get() { val n = shape.size val vectorOffset = shape[n - 1] - val vectorShape = Shape(shape.last()) + val vectorShape = ShapeND(shape.last()) return List(linearSize / vectorOffset) { index -> val offset = index * vectorOffset @@ -173,7 +173,7 @@ internal val DoubleTensor.matrices: List val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } val matrixOffset = shape[n - 1] * shape[n - 2] - val matrixShape = Shape(shape[n - 2], shape[n - 1]) + val matrixShape = ShapeND(shape[n - 2], shape[n - 1]) val size = matrixShape.linearSize diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt index 2513dedb7..35f0bf324 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core.internal -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.first import space.kscience.kmath.nd.last import space.kscience.kmath.operations.asSequence @@ -55,7 +55,7 @@ internal val IntTensor.matrices: VirtualBuffer val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } val matrixOffset = shape[n - 1] * shape[n - 2] - val matrixShape = Shape(shape[n - 2], shape[n - 1]) + val matrixShape = ShapeND(shape[n - 2], shape[n - 1]) return VirtualBuffer(linearSize / matrixOffset) { index -> val offset = index * matrixOffset diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt index b01e67eee..44459ad14 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt @@ -95,7 +95,7 @@ internal fun StructureND.setUpPivots(): IntTensor { pivotsShape[n - 2] = m + 1 return IntTensor( - Shape(pivotsShape), + ShapeND(pivotsShape), IntBuffer(pivotsShape.reduce(Int::times)) { 0 } ) } @@ -240,10 +240,10 @@ internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10) val b: DoubleTensor if (n > m) { b = a.transposed(0, 1).dot(a) - v = DoubleTensor(Shape(m), DoubleBuffer.randomUnitVector(m, 0)) + v = DoubleTensor(ShapeND(m), DoubleBuffer.randomUnitVector(m, 0)) } else { b = a.dot(a.transposed(0, 1)) - v = DoubleTensor(Shape(n), DoubleBuffer.randomUnitVector(n, 0)) + v = DoubleTensor(ShapeND(n), DoubleBuffer.randomUnitVector(n, 0)) } var lastV: DoubleTensor @@ -275,7 +275,7 @@ internal fun DoubleTensorAlgebra.svdHelper( outerProduct[i * v.shape[0] + j] = u.getTensor(i).value() * v.getTensor(j).value() } } - a = a - singularValue.times(DoubleTensor(Shape(u.shape[0], v.shape[0]), outerProduct.asBuffer())) + a = a - singularValue.times(DoubleTensor(ShapeND(u.shape[0], v.shape[0]), outerProduct.asBuffer())) } var v: DoubleTensor var u: DoubleTensor diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt index 7e30c7965..1733c1a7e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt @@ -8,15 +8,15 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import kotlin.jvm.JvmName @JvmName("varArgOne") -public fun DoubleTensorAlgebra.one(vararg shape: Int): DoubleTensor = ones(Shape(shape)) +public fun DoubleTensorAlgebra.one(vararg shape: Int): DoubleTensor = ones(ShapeND(shape)) -public fun DoubleTensorAlgebra.one(shape: Shape): DoubleTensor = ones(shape) +public fun DoubleTensorAlgebra.one(shape: ShapeND): DoubleTensor = ones(shape) @JvmName("varArgZero") -public fun DoubleTensorAlgebra.zero(vararg shape: Int): DoubleTensor = zeros(Shape(shape)) +public fun DoubleTensorAlgebra.zero(vararg shape: Int): DoubleTensor = zeros(ShapeND(shape)) -public fun DoubleTensorAlgebra.zero(shape: Shape): DoubleTensor = zeros(shape) +public fun DoubleTensorAlgebra.zero(shape: ShapeND): DoubleTensor = zeros(shape) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 5940d44e9..73aed8a7b 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.internal.broadcastOuterTensors @@ -21,38 +21,38 @@ internal class TestBroadcasting { fun testBroadcastShapes() = DoubleTensorAlgebra { assertTrue( broadcastShapes( - listOf(Shape(2, 3), Shape(1, 3), Shape(1, 1, 1)) - ) contentEquals Shape(1, 2, 3) + listOf(ShapeND(2, 3), ShapeND(1, 3), ShapeND(1, 1, 1)) + ) contentEquals ShapeND(1, 2, 3) ) assertTrue( broadcastShapes( - listOf(Shape(6, 7), Shape(5, 6, 1), Shape(7), Shape(5, 1, 7)) - ) contentEquals Shape(5, 6, 7) + listOf(ShapeND(6, 7), ShapeND(5, 6, 1), ShapeND(7), ShapeND(5, 1, 7)) + ) contentEquals ShapeND(5, 6, 7) ) } @Test fun testBroadcastTo() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(Shape(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor1 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val res = broadcastTo(tensor2, tensor1.shape) - assertTrue(res.shape contentEquals Shape(2, 3)) + assertTrue(res.shape contentEquals ShapeND(2, 3)) assertTrue(res.source contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) } @Test fun testBroadcastTensors() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(Shape(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = fromArray(Shape(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(ShapeND(1, 1, 1), doubleArrayOf(500.0)) val res = broadcastTensors(tensor1, tensor2, tensor3) - assertTrue(res[0].shape contentEquals Shape(1, 2, 3)) - assertTrue(res[1].shape contentEquals Shape(1, 2, 3)) - assertTrue(res[2].shape contentEquals Shape(1, 2, 3)) + assertTrue(res[0].shape contentEquals ShapeND(1, 2, 3)) + assertTrue(res[1].shape contentEquals ShapeND(1, 2, 3)) + assertTrue(res[2].shape contentEquals ShapeND(1, 2, 3)) assertTrue(res[0].source contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) assertTrue(res[1].source contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) @@ -61,15 +61,15 @@ internal class TestBroadcasting { @Test fun testBroadcastOuterTensors() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(Shape(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = fromArray(Shape(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(ShapeND(1, 1, 1), doubleArrayOf(500.0)) val res = broadcastOuterTensors(tensor1, tensor2, tensor3) - assertTrue(res[0].shape contentEquals Shape(1, 2, 3)) - assertTrue(res[1].shape contentEquals Shape(1, 1, 3)) - assertTrue(res[2].shape contentEquals Shape(1, 1, 1)) + assertTrue(res[0].shape contentEquals ShapeND(1, 2, 3)) + assertTrue(res[1].shape contentEquals ShapeND(1, 1, 3)) + assertTrue(res[2].shape contentEquals ShapeND(1, 1, 1)) assertTrue(res[0].source contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) assertTrue(res[1].source contentEquals doubleArrayOf(10.0, 20.0, 30.0)) @@ -78,37 +78,37 @@ internal class TestBroadcasting { @Test fun testBroadcastOuterTensorsShapes() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) { 0.0 }) - val tensor2 = fromArray(Shape(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) { 0.0 }) - val tensor3 = fromArray(Shape(1, 1), doubleArrayOf(500.0)) + val tensor1 = fromArray(ShapeND(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) { 0.0 }) + val tensor2 = fromArray(ShapeND(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) { 0.0 }) + val tensor3 = fromArray(ShapeND(1, 1), doubleArrayOf(500.0)) val res = broadcastOuterTensors(tensor1, tensor2, tensor3) - assertTrue(res[0].shape contentEquals Shape(4, 2, 5, 3, 2, 3)) - assertTrue(res[1].shape contentEquals Shape(4, 2, 5, 3, 3, 3)) - assertTrue(res[2].shape contentEquals Shape(4, 2, 5, 3, 1, 1)) + assertTrue(res[0].shape contentEquals ShapeND(4, 2, 5, 3, 2, 3)) + assertTrue(res[1].shape contentEquals ShapeND(4, 2, 5, 3, 3, 3)) + assertTrue(res[2].shape contentEquals ShapeND(4, 2, 5, 3, 1, 1)) } @Test fun testMinusTensor() = BroadcastDoubleTensorAlgebra.invoke { - val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(Shape(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = fromArray(Shape(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(ShapeND(1, 1, 1), doubleArrayOf(500.0)) val tensor21 = tensor2 - tensor1 val tensor31 = tensor3 - tensor1 val tensor32 = tensor3 - tensor2 - assertTrue(tensor21.shape contentEquals Shape(2, 3)) + assertTrue(tensor21.shape contentEquals ShapeND(2, 3)) assertTrue(tensor21.source contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) - assertTrue(tensor31.shape contentEquals Shape(1, 2, 3)) + assertTrue(tensor31.shape contentEquals ShapeND(1, 2, 3)) assertTrue( tensor31.source contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0) ) - assertTrue(tensor32.shape contentEquals Shape(1, 1, 3)) + assertTrue(tensor32.shape contentEquals ShapeND(1, 1, 3)) assertTrue(tensor32.source contentEquals doubleArrayOf(490.0, 480.0, 470.0)) } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index f098eecb0..2ef2d87d6 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.asBuffer import kotlin.math.* @@ -14,7 +14,7 @@ import kotlin.test.assertTrue internal class TestDoubleAnalyticTensorAlgebra { - val shape = Shape(2, 1, 3, 2) + val shape = ShapeND(2, 1, 3, 2) val buffer = doubleArrayOf( 27.1, 20.0, 19.84, 23.123, 3.0, 2.0, @@ -103,7 +103,7 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor.floor() eq expectedTensor(::floor) } } - val shape2 = Shape(2, 2) + val shape2 = ShapeND(2, 2) val buffer2 = doubleArrayOf( 1.0, 2.0, -3.0, 4.0 @@ -115,13 +115,13 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor2.min() == -3.0 } assertTrue { tensor2.min(0, true) eq fromArray( - Shape(1, 2), + ShapeND(1, 2), doubleArrayOf(-3.0, 2.0) ) } assertTrue { tensor2.min(1, false) eq fromArray( - Shape(2), + ShapeND(2), doubleArrayOf(1.0, -3.0) ) } @@ -132,13 +132,13 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor2.max() == 4.0 } assertTrue { tensor2.max(0, true) eq fromArray( - Shape(1, 2), + ShapeND(1, 2), doubleArrayOf(1.0, 4.0) ) } assertTrue { tensor2.max(1, false) eq fromArray( - Shape(2), + ShapeND(2), doubleArrayOf(2.0, 4.0) ) } @@ -149,13 +149,13 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor2.sum() == 4.0 } assertTrue { tensor2.sum(0, true) eq fromArray( - Shape(1, 2), + ShapeND(1, 2), doubleArrayOf(-2.0, 6.0) ) } assertTrue { tensor2.sum(1, false) eq fromArray( - Shape(2), + ShapeND(2), doubleArrayOf(3.0, 1.0) ) } @@ -166,13 +166,13 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor2.mean() == 1.0 } assertTrue { tensor2.mean(0, true) eq fromArray( - Shape(1, 2), + ShapeND(1, 2), doubleArrayOf(-1.0, 3.0) ) } assertTrue { tensor2.mean(1, false) eq fromArray( - Shape(2), + ShapeND(2), doubleArrayOf(1.5, 0.5) ) } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index b9f845bb2..d47af4a64 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.internal.svd1d @@ -19,7 +19,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testDetLU() = DoubleTensorAlgebra { val tensor = fromArray( - Shape(2, 2, 2), + ShapeND(2, 2, 2), doubleArrayOf( 1.0, 3.0, 1.0, 2.0, @@ -29,7 +29,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) val expectedTensor = fromArray( - Shape(2, 1), + ShapeND(2, 1), doubleArrayOf( -1.0, -7.0 @@ -45,7 +45,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testDet() = DoubleTensorAlgebra { val expectedValue = 0.019827417 val m = fromArray( - Shape(3, 3), doubleArrayOf( + ShapeND(3, 3), doubleArrayOf( 2.1843, 1.4391, -0.4845, 1.4391, 1.7772, 0.4055, -0.4845, 0.4055, 0.7519 @@ -59,7 +59,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testDetSingle() = DoubleTensorAlgebra { val expectedValue = 48.151623 val m = fromArray( - Shape(1, 1), doubleArrayOf( + ShapeND(1, 1), doubleArrayOf( expectedValue ) ) @@ -70,7 +70,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testInvLU() = DoubleTensorAlgebra { val tensor = fromArray( - Shape(2, 2, 2), + ShapeND(2, 2, 2), doubleArrayOf( 1.0, 0.0, 0.0, 2.0, @@ -80,7 +80,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) val expectedTensor = fromArray( - Shape(2, 2, 2), doubleArrayOf( + ShapeND(2, 2, 2), doubleArrayOf( 1.0, 0.0, 0.0, 0.5, 0.0, 1.0, @@ -94,14 +94,14 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testScalarProduct() = DoubleTensorAlgebra { - val a = fromArray(Shape(3), doubleArrayOf(1.8, 2.5, 6.8)) - val b = fromArray(Shape(3), doubleArrayOf(5.5, 2.6, 6.4)) + val a = fromArray(ShapeND(3), doubleArrayOf(1.8, 2.5, 6.8)) + val b = fromArray(ShapeND(3), doubleArrayOf(5.5, 2.6, 6.4)) assertEquals(a.dot(b).value(), 59.92) } @Test fun testQR() = DoubleTensorAlgebra { - val shape = Shape(2, 2, 2) + val shape = ShapeND(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, 1.0, 2.0, @@ -122,7 +122,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testLU() = DoubleTensorAlgebra { - val shape = Shape(2, 2, 2) + val shape = ShapeND(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, 1.0, 2.0, @@ -142,9 +142,9 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testCholesky() = DoubleTensorAlgebra { - val tensor = randomNormal(Shape(2, 5, 5), 0) + val tensor = randomNormal(ShapeND(2, 5, 5), 0) val sigma = (tensor matmul tensor.transposed()) + diagonalEmbedding( - fromArray(Shape(2, 5), DoubleArray(10) { 0.1 }) + fromArray(ShapeND(2, 5), DoubleArray(10) { 0.1 }) ) val low = sigma.cholesky() val sigmChol = low matmul low.transposed() @@ -153,24 +153,24 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testSVD1D() = DoubleTensorAlgebra { - val tensor2 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = svd1d(tensor2) - assertTrue(res.shape contentEquals Shape(2)) + assertTrue(res.shape contentEquals ShapeND(2)) assertTrue { abs(abs(res.source[0]) - 0.386) < 0.01 } assertTrue { abs(abs(res.source[1]) - 0.922) < 0.01 } } @Test fun testSVD() = DoubleTensorAlgebra { - testSVDFor(fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) - testSVDFor(fromArray(Shape(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) + testSVDFor(fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) + testSVDFor(fromArray(ShapeND(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } @Test fun testBatchedSVD() = DoubleTensorAlgebra { - val tensor = randomNormal(Shape(2, 5, 3), 0) + val tensor = randomNormal(ShapeND(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed()) assertTrue(tensor.eq(tensorSVD)) @@ -178,7 +178,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testBatchedSymEig() = DoubleTensorAlgebra { - val tensor = randomNormal(shape = Shape(2, 3, 3), 0) + val tensor = randomNormal(shape = ShapeND(2, 3, 3), 0) val tensorSigma = tensor + tensor.transposed() val (tensorS, tensorV) = tensorSigma.symEig() val tensorSigmaCalc = tensorV matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed()) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index f07614d05..d01ae124b 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -21,14 +21,14 @@ internal class TestDoubleTensor { @Test fun testValue() = DoubleTensorAlgebra { val value = 12.5 - val tensor = fromArray(Shape(1), doubleArrayOf(value)) + val tensor = fromArray(ShapeND(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @OptIn(PerformancePitfall::class) @Test fun testStrides() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) + val tensor = fromArray(ShapeND(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) assertEquals(tensor[intArrayOf(0, 1)], 5.8) assertTrue( tensor.elements().map { it.second }.toList() @@ -38,7 +38,7 @@ internal class TestDoubleTensor { @Test fun testGet() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) + val tensor = fromArray(ShapeND(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) val matrix = tensor.getTensor(0).asDoubleTensor2D() assertEquals(matrix[0, 1], 5.8) @@ -67,7 +67,7 @@ internal class TestDoubleTensor { val doubleArray = DoubleBuffer(1.0, 2.0, 3.0) // create ND buffers, no data is copied - val ndArray: MutableBufferND = DoubleBufferND(ColumnStrides(Shape(3)), doubleArray) + val ndArray: MutableBufferND = DoubleBufferND(ColumnStrides(ShapeND(3)), doubleArray) // map to tensors val tensorArray = ndArray.asDoubleTensor() // Data is copied because of strides change. @@ -91,7 +91,7 @@ internal class TestDoubleTensor { @Test fun test2D() = with(DoubleTensorAlgebra) { - val tensor: DoubleTensor = structureND(Shape(3, 3)) { (i, j) -> (i - j).toDouble() } + val tensor: DoubleTensor = structureND(ShapeND(3, 3)) { (i, j) -> (i - j).toDouble() } //println(tensor.toPrettyString()) val tensor2d = tensor.asDoubleTensor2D() assertBufferEquals(DoubleBuffer(1.0, 0.0, -1.0), tensor2d.rows[1]) @@ -100,7 +100,7 @@ internal class TestDoubleTensor { @Test fun testMatrixIteration() = with(DoubleTensorAlgebra) { - val tensor = structureND(Shape(3, 3, 3, 3)) { index -> index.sum().toDouble() } + val tensor = structureND(ShapeND(3, 3, 3, 3)) { index -> index.sum().toDouble() } tensor.forEachMatrix { index, matrix -> println(index.joinToString { it.toString() }) println(matrix) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 3c693b089..cae01bed8 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.nd.get import space.kscience.kmath.operations.invoke @@ -20,53 +20,53 @@ internal class TestDoubleTensorAlgebra { @Test fun testDoublePlus() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(2), doubleArrayOf(1.0, 2.0)) + val tensor = fromArray(ShapeND(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.source contentEquals doubleArrayOf(11.0, 12.0)) } @Test fun testDoubleDiv() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(2), doubleArrayOf(2.0, 4.0)) + val tensor = fromArray(ShapeND(2), doubleArrayOf(2.0, 4.0)) val res = 2.0 / tensor assertTrue(res.source contentEquals doubleArrayOf(1.0, 0.5)) } @Test fun testDivDouble() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(2), doubleArrayOf(10.0, 5.0)) + val tensor = fromArray(ShapeND(2), doubleArrayOf(10.0, 5.0)) val res = tensor / 2.5 assertTrue(res.source contentEquals doubleArrayOf(4.0, 2.0)) } @Test fun testTranspose1x1() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(1), doubleArrayOf(0.0)) + val tensor = fromArray(ShapeND(1), doubleArrayOf(0.0)) val res = tensor.transposed(0, 0) assertTrue(res.asDoubleTensor().source contentEquals doubleArrayOf(0.0)) - assertTrue(res.shape contentEquals Shape(1)) + assertTrue(res.shape contentEquals ShapeND(1)) } @Test fun testTranspose3x2() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor = fromArray(ShapeND(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transposed(1, 0) assertTrue(res.asDoubleTensor().source contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) - assertTrue(res.shape contentEquals Shape(2, 3)) + assertTrue(res.shape contentEquals ShapeND(2, 3)) } @Test fun testTranspose1x2x3() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor = fromArray(ShapeND(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transposed(0, 1) val res02 = tensor.transposed(-3, 2) val res12 = tensor.transposed() - assertTrue(res01.shape contentEquals Shape(2, 1, 3)) - assertTrue(res02.shape contentEquals Shape(3, 2, 1)) - assertTrue(res12.shape contentEquals Shape(1, 3, 2)) + assertTrue(res01.shape contentEquals ShapeND(2, 1, 3)) + assertTrue(res02.shape contentEquals ShapeND(3, 2, 1)) + assertTrue(res12.shape contentEquals ShapeND(1, 3, 2)) assertTrue(res01.asDoubleTensor().source contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) assertTrue(res02.asDoubleTensor().source contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) @@ -75,7 +75,7 @@ internal class TestDoubleTensorAlgebra { @Test fun testLinearStructure() = DoubleTensorAlgebra { - val shape = Shape(3) + val shape = ShapeND(3) val tensorA = full(value = -4.5, shape = shape) val tensorB = full(value = 10.9, shape = shape) val tensorC = full(value = 789.3, shape = shape) @@ -107,28 +107,28 @@ internal class TestDoubleTensorAlgebra { @Test fun testDot() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor11 = fromArray(Shape(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(Shape(3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = fromArray(Shape(1, 1, 3), doubleArrayOf(-1.0, -2.0, -3.0)) - val tensor4 = fromArray(Shape(2, 3, 3), (1..18).map { it.toDouble() }.toDoubleArray()) - val tensor5 = fromArray(Shape(2, 3, 3), (1..18).map { 1 + it.toDouble() }.toDoubleArray()) + val tensor1 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor11 = fromArray(ShapeND(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(ShapeND(1, 1, 3), doubleArrayOf(-1.0, -2.0, -3.0)) + val tensor4 = fromArray(ShapeND(2, 3, 3), (1..18).map { it.toDouble() }.toDoubleArray()) + val tensor5 = fromArray(ShapeND(2, 3, 3), (1..18).map { 1 + it.toDouble() }.toDoubleArray()) val res12 = tensor1.dot(tensor2) assertTrue(res12.source contentEquals doubleArrayOf(140.0, 320.0)) - assertTrue(res12.shape contentEquals Shape(2)) + assertTrue(res12.shape contentEquals ShapeND(2)) val res32 = tensor3.matmul(tensor2) assertTrue(res32.source contentEquals doubleArrayOf(-140.0)) - assertTrue(res32.shape contentEquals Shape(1, 1)) + assertTrue(res32.shape contentEquals ShapeND(1, 1)) val res22 = tensor2.dot(tensor2) assertTrue(res22.source contentEquals doubleArrayOf(1400.0)) - assertTrue(res22.shape contentEquals Shape(1)) + assertTrue(res22.shape contentEquals ShapeND(1)) val res11 = tensor1.dot(tensor11) assertTrue(res11.source contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0)) - assertTrue(res11.shape contentEquals Shape(2, 2)) + assertTrue(res11.shape contentEquals ShapeND(2, 2)) val res45 = tensor4.matmul(tensor5) assertTrue( @@ -137,44 +137,44 @@ internal class TestDoubleTensorAlgebra { 468.0, 501.0, 534.0, 594.0, 636.0, 678.0, 720.0, 771.0, 822.0 ) ) - assertTrue(res45.shape contentEquals Shape(2, 3, 3)) + assertTrue(res45.shape contentEquals ShapeND(2, 3, 3)) } @Test fun testDiagonalEmbedding() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor2 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor3 = zeros(Shape(2, 3, 4, 5)) + val tensor1 = fromArray(ShapeND(3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor2 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor3 = zeros(ShapeND(2, 3, 4, 5)) assertTrue( diagonalEmbedding(tensor3, 0, 3, 4).shape contentEquals - Shape(2, 3, 4, 5, 5) + ShapeND(2, 3, 4, 5, 5) ) assertTrue( diagonalEmbedding(tensor3, 1, 3, 4).shape contentEquals - Shape(2, 3, 4, 6, 6) + ShapeND(2, 3, 4, 6, 6) ) assertTrue( diagonalEmbedding(tensor3, 2, 0, 3).shape contentEquals - Shape(7, 2, 3, 7, 4) + ShapeND(7, 2, 3, 7, 4) ) val diagonal1 = diagonalEmbedding(tensor1, 0, 1, 0) - assertTrue(diagonal1.shape contentEquals Shape(3, 3)) + assertTrue(diagonal1.shape contentEquals ShapeND(3, 3)) assertTrue( diagonal1.source contentEquals doubleArrayOf(10.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 30.0) ) val diagonal1Offset = diagonalEmbedding(tensor1, 1, 1, 0) - assertTrue(diagonal1Offset.shape contentEquals Shape(4, 4)) + assertTrue(diagonal1Offset.shape contentEquals ShapeND(4, 4)) assertTrue( diagonal1Offset.source contentEquals doubleArrayOf(0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 30.0, 0.0) ) val diagonal2 = diagonalEmbedding(tensor2, 1, 0, 2) - assertTrue(diagonal2.shape contentEquals Shape(4, 2, 4)) + assertTrue(diagonal2.shape contentEquals ShapeND(4, 2, 4)) assertTrue( diagonal2.source contentEquals doubleArrayOf( @@ -188,9 +188,9 @@ internal class TestDoubleTensorAlgebra { @Test fun testEq() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor3 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) + val tensor1 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor3 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) assertTrue(tensor1 eq tensor1) assertTrue(tensor1 eq tensor2) @@ -204,7 +204,7 @@ internal class TestDoubleTensorAlgebra { val l = tensor.getTensor(0).map { it + 1.0 } val r = tensor.getTensor(1).map { it - 1.0 } val res = l + r - assertTrue { Shape(5, 5) contentEquals res.shape } + assertTrue { ShapeND(5, 5) contentEquals res.shape } assertEquals(2.0, res[4, 4]) } } diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt index 5ac1c74a3..8533c9d32 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt @@ -33,7 +33,7 @@ public open class ViktorFieldOpsND : override val elementAlgebra: DoubleField get() = DoubleField @OptIn(UnsafeKMathAPI::class) - override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND = + override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND = F64Array(*shape.asArray()).apply { ColumnStrides(shape).asSequence().forEach { index -> set(value = DoubleField.initializer(index), indices = index) @@ -46,7 +46,7 @@ public open class ViktorFieldOpsND : @PerformancePitfall override fun StructureND.map(transform: DoubleField.(Double) -> Double): ViktorStructureND = F64Array(*shape.asArray()).apply { - ColumnStrides(Shape(shape)).asSequence().forEach { index -> + ColumnStrides(ShapeND(shape)).asSequence().forEach { index -> set(value = DoubleField.transform(this@map[index]), indices = index) } }.asStructure() @@ -56,7 +56,7 @@ public open class ViktorFieldOpsND : override fun StructureND.mapIndexed( transform: DoubleField.(index: IntArray, Double) -> Double, ): ViktorStructureND = F64Array(*shape.asArray()).apply { - ColumnStrides(Shape(shape)).asSequence().forEach { index -> + ColumnStrides(ShapeND(shape)).asSequence().forEach { index -> set(value = DoubleField.transform(index, this@mapIndexed[index]), indices = index) } }.asStructure() @@ -127,7 +127,7 @@ public open class ViktorFieldND( private val shapeAsArray: IntArray, ) : ViktorFieldOpsND(), FieldND, NumbersAddOps> { - override val shape: Shape = Shape(shapeAsArray) + override val shape: ShapeND = ShapeND(shapeAsArray) override val zero: ViktorStructureND by lazy { F64Array.full(init = 0.0, shape = shapeAsArray).asStructure() } diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt index cee52b06d..085790355 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt @@ -9,11 +9,11 @@ import org.jetbrains.bio.viktor.F64Array import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.MutableStructureND -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructureND { - override val shape: Shape get() = Shape(f64Buffer.shape) + override val shape: ShapeND get() = ShapeND(f64Buffer.shape) @OptIn(PerformancePitfall::class) override inline fun get(index: IntArray): Double = f64Buffer.get(*index)