forked from kscience/kmath
Safe shapes
This commit is contained in:
parent
b0abcf2d0c
commit
ee569b85f8
@ -85,7 +85,7 @@ internal class NDFieldBenchmark {
|
|||||||
private companion object {
|
private companion object {
|
||||||
private const val dim = 1000
|
private const val dim = 1000
|
||||||
private const val n = 100
|
private const val n = 100
|
||||||
private val shape = Shape(dim, dim)
|
private val shape = ShapeND(dim, dim)
|
||||||
private val specializedField = DoubleField.ndAlgebra
|
private val specializedField = DoubleField.ndAlgebra
|
||||||
private val genericField = BufferedFieldOpsND(DoubleField)
|
private val genericField = BufferedFieldOpsND(DoubleField)
|
||||||
private val nd4jField = DoubleField.nd4j
|
private val nd4jField = DoubleField.nd4j
|
||||||
|
@ -10,7 +10,7 @@ import kotlinx.benchmark.Blackhole
|
|||||||
import kotlinx.benchmark.Scope
|
import kotlinx.benchmark.Scope
|
||||||
import kotlinx.benchmark.State
|
import kotlinx.benchmark.State
|
||||||
import org.jetbrains.bio.viktor.F64Array
|
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.StructureND
|
||||||
import space.kscience.kmath.nd.ndAlgebra
|
import space.kscience.kmath.nd.ndAlgebra
|
||||||
import space.kscience.kmath.nd.one
|
import space.kscience.kmath.nd.one
|
||||||
@ -49,7 +49,7 @@ internal class ViktorBenchmark {
|
|||||||
private companion object {
|
private companion object {
|
||||||
private const val dim = 1000
|
private const val dim = 1000
|
||||||
private const val n = 100
|
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.
|
// automatically build context most suited for given type.
|
||||||
private val doubleField = DoubleField.ndAlgebra
|
private val doubleField = DoubleField.ndAlgebra
|
||||||
|
@ -10,7 +10,7 @@ import kotlinx.benchmark.Blackhole
|
|||||||
import kotlinx.benchmark.Scope
|
import kotlinx.benchmark.Scope
|
||||||
import kotlinx.benchmark.State
|
import kotlinx.benchmark.State
|
||||||
import org.jetbrains.bio.viktor.F64Array
|
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.ndAlgebra
|
||||||
import space.kscience.kmath.nd.one
|
import space.kscience.kmath.nd.one
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
@ -49,7 +49,7 @@ internal class ViktorLogBenchmark {
|
|||||||
private companion object {
|
private companion object {
|
||||||
private const val dim = 1000
|
private const val dim = 1000
|
||||||
private const val n = 100
|
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.
|
// automatically build context most suited for given type.
|
||||||
private val doubleField = DoubleField.ndAlgebra
|
private val doubleField = DoubleField.ndAlgebra
|
||||||
|
@ -8,14 +8,14 @@ package space.kscience.kmath.operations
|
|||||||
import space.kscience.kmath.commons.linear.CMLinearSpace
|
import space.kscience.kmath.commons.linear.CMLinearSpace
|
||||||
import space.kscience.kmath.linear.matrix
|
import space.kscience.kmath.linear.matrix
|
||||||
import space.kscience.kmath.nd.DoubleBufferND
|
import space.kscience.kmath.nd.DoubleBufferND
|
||||||
import space.kscience.kmath.nd.Shape
|
import space.kscience.kmath.nd.ShapeND
|
||||||
import space.kscience.kmath.nd.Structure2D
|
import space.kscience.kmath.nd.Structure2D
|
||||||
import space.kscience.kmath.nd.ndAlgebra
|
import space.kscience.kmath.nd.ndAlgebra
|
||||||
import space.kscience.kmath.viktor.ViktorStructureND
|
import space.kscience.kmath.viktor.ViktorStructureND
|
||||||
import space.kscience.kmath.viktor.viktorAlgebra
|
import space.kscience.kmath.viktor.viktorAlgebra
|
||||||
|
|
||||||
fun main() {
|
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
|
if (i == j) 2.0 else 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ fun main() {
|
|||||||
Nd4j.zeros(0)
|
Nd4j.zeros(0)
|
||||||
val dim = 1000
|
val dim = 1000
|
||||||
val n = 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.
|
// specialized nd-field for Double. It works as generic Double field as well.
|
||||||
|
@ -17,7 +17,7 @@ import java.util.stream.IntStream
|
|||||||
* A demonstration implementation of NDField over Real using Java [java.util.stream.DoubleStream] for parallel
|
* A demonstration implementation of NDField over Real using Java [java.util.stream.DoubleStream] for parallel
|
||||||
* execution.
|
* execution.
|
||||||
*/
|
*/
|
||||||
class StreamDoubleFieldND(override val shape: Shape) : FieldND<Double, DoubleField>,
|
class StreamDoubleFieldND(override val shape: ShapeND) : FieldND<Double, DoubleField>,
|
||||||
NumbersAddOps<StructureND<Double>>,
|
NumbersAddOps<StructureND<Double>>,
|
||||||
ExtendedField<StructureND<Double>> {
|
ExtendedField<StructureND<Double>> {
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ class StreamDoubleFieldND(override val shape: Shape) : FieldND<Double, DoubleFie
|
|||||||
else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) }
|
else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): BufferND<Double> {
|
override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): BufferND<Double> {
|
||||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||||
val index = strides.index(offset)
|
val index = strides.index(offset)
|
||||||
DoubleField.initializer(index)
|
DoubleField.initializer(index)
|
||||||
@ -111,4 +111,4 @@ class StreamDoubleFieldND(override val shape: Shape) : FieldND<Double, DoubleFie
|
|||||||
override fun atanh(arg: StructureND<Double>): BufferND<Double> = arg.map { atanh(it) }
|
override fun atanh(arg: StructureND<Double>): BufferND<Double> = arg.map { atanh(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun DoubleField.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(Shape(shape))
|
fun DoubleField.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(ShapeND(shape))
|
||||||
|
@ -8,7 +8,7 @@ package space.kscience.kmath.structures
|
|||||||
import space.kscience.kmath.misc.PerformancePitfall
|
import space.kscience.kmath.misc.PerformancePitfall
|
||||||
import space.kscience.kmath.nd.BufferND
|
import space.kscience.kmath.nd.BufferND
|
||||||
import space.kscience.kmath.nd.ColumnStrides
|
import space.kscience.kmath.nd.ColumnStrides
|
||||||
import space.kscience.kmath.nd.Shape
|
import space.kscience.kmath.nd.ShapeND
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
|
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
|
||||||
@ -17,7 +17,7 @@ fun main() {
|
|||||||
val n = 6000
|
val n = 6000
|
||||||
val array = DoubleArray(n * n) { 1.0 }
|
val array = DoubleArray(n * n) { 1.0 }
|
||||||
val buffer = DoubleBuffer(array)
|
val buffer = DoubleBuffer(array)
|
||||||
val strides = ColumnStrides(Shape(n, n))
|
val strides = ColumnStrides(ShapeND(n, n))
|
||||||
val structure = BufferND(strides, buffer)
|
val structure = BufferND(strides, buffer)
|
||||||
|
|
||||||
measureTimeMillis {
|
measureTimeMillis {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
|
||||||
import space.kscience.kmath.nd.BufferND
|
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.nd.StructureND
|
||||||
import space.kscience.kmath.operations.map
|
import space.kscience.kmath.operations.map
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
@ -16,7 +16,7 @@ private inline fun <T, reified R: Any> BufferND<T>.map(block: (T) -> R): BufferN
|
|||||||
@Suppress("UNUSED_VARIABLE")
|
@Suppress("UNUSED_VARIABLE")
|
||||||
fun main() {
|
fun main() {
|
||||||
val n = 6000
|
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
|
structure.map { it + 1 } // warm-up
|
||||||
val time1 = measureTimeMillis { val res = structure.map { it + 1 } }
|
val time1 = measureTimeMillis { val res = structure.map { it + 1 } }
|
||||||
println("Structure mapping finished in $time1 millis")
|
println("Structure mapping finished in $time1 millis")
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
package space.kscience.kmath.tensors
|
package space.kscience.kmath.tensors
|
||||||
|
|
||||||
import space.kscience.kmath.misc.PerformancePitfall
|
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.nd.contentEquals
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.tensors.core.DoubleTensor
|
import space.kscience.kmath.tensors.core.DoubleTensor
|
||||||
@ -25,10 +25,10 @@ fun main() {
|
|||||||
DoubleTensorAlgebra {
|
DoubleTensorAlgebra {
|
||||||
// take coefficient vector from normal distribution
|
// take coefficient vector from normal distribution
|
||||||
val alpha = randomNormal(
|
val alpha = randomNormal(
|
||||||
Shape(5),
|
ShapeND(5),
|
||||||
randSeed
|
randSeed
|
||||||
) + fromArray(
|
) + fromArray(
|
||||||
Shape(5),
|
ShapeND(5),
|
||||||
doubleArrayOf(1.0, 2.5, 3.4, 5.0, 10.1)
|
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
|
// also take sample of size 20 from normal distribution for x
|
||||||
val x = randomNormal(
|
val x = randomNormal(
|
||||||
Shape(20, 5),
|
ShapeND(20, 5),
|
||||||
randSeed
|
randSeed
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.tensors
|
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.tensorAlgebra
|
||||||
import space.kscience.kmath.tensors.core.withBroadcast
|
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
|
// assume x is range from 0 until 10
|
||||||
val x = fromArray(
|
val x = fromArray(
|
||||||
Shape(10),
|
ShapeND(10),
|
||||||
DoubleArray(10) { it.toDouble() }
|
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
|
// save means ans standard deviations for further recovery
|
||||||
val mean = fromArray(
|
val mean = fromArray(
|
||||||
Shape(2),
|
ShapeND(2),
|
||||||
doubleArrayOf(xMean, yMean)
|
doubleArrayOf(xMean, yMean)
|
||||||
)
|
)
|
||||||
println("Means:\n$mean")
|
println("Means:\n$mean")
|
||||||
|
|
||||||
val std = fromArray(
|
val std = fromArray(
|
||||||
Shape(2),
|
ShapeND(2),
|
||||||
doubleArrayOf(xStd, yStd)
|
doubleArrayOf(xStd, yStd)
|
||||||
)
|
)
|
||||||
println("Standard deviations:\n$std")
|
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;
|
// we can restore original data from reduced data;
|
||||||
// for example, find 7th element of dataset.
|
// for example, find 7th element of dataset.
|
||||||
val n = 7
|
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("Original value:\n${dataset.getTensor(n)}")
|
||||||
println("Restored value:\n$restored")
|
println("Restored value:\n$restored")
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.tensors
|
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.tensorAlgebra
|
||||||
import space.kscience.kmath.tensors.core.withBroadcast
|
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
|
fun main() = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods
|
||||||
// take dataset of 5-element vectors from normal distribution
|
// 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(
|
dataset += fromArray(
|
||||||
Shape(5),
|
ShapeND(5),
|
||||||
doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // row means
|
doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // row means
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.tensors
|
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.DoubleTensor
|
||||||
import space.kscience.kmath.tensors.core.tensorAlgebra
|
import space.kscience.kmath.tensors.core.tensorAlgebra
|
||||||
import space.kscience.kmath.tensors.core.withBroadcast
|
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
|
// set true value of x
|
||||||
val trueX = fromArray(
|
val trueX = fromArray(
|
||||||
Shape(4),
|
ShapeND(4),
|
||||||
doubleArrayOf(-2.0, 1.5, 6.8, -2.4)
|
doubleArrayOf(-2.0, 1.5, 6.8, -2.4)
|
||||||
)
|
)
|
||||||
|
|
||||||
// and A matrix
|
// and A matrix
|
||||||
val a = fromArray(
|
val a = fromArray(
|
||||||
Shape(4, 4),
|
ShapeND(4, 4),
|
||||||
doubleArrayOf(
|
doubleArrayOf(
|
||||||
0.5, 10.5, 4.5, 1.0,
|
0.5, 10.5, 4.5, 1.0,
|
||||||
8.5, 0.9, 12.8, 0.1,
|
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
|
// this function returns solution x of a system lx = b, l should be lower triangular
|
||||||
fun solveLT(l: DoubleTensor, b: DoubleTensor): DoubleTensor {
|
fun solveLT(l: DoubleTensor, b: DoubleTensor): DoubleTensor {
|
||||||
val n = l.shape[0]
|
val n = l.shape[0]
|
||||||
val x = zeros(Shape(n))
|
val x = zeros(ShapeND(n))
|
||||||
for (i in 0 until n) {
|
for (i in 0 until n) {
|
||||||
x[intArrayOf(i)] = (b[intArrayOf(i)] - l.getTensor(i).dot(x).value()) / l[intArrayOf(i, i)]
|
x[intArrayOf(i)] = (b[intArrayOf(i)] - l.getTensor(i).dot(x).value()) / l[intArrayOf(i, i)]
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.tensors
|
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.nd.contentEquals
|
||||||
import space.kscience.kmath.operations.asIterable
|
import space.kscience.kmath.operations.asIterable
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
@ -70,12 +70,12 @@ class Dense(
|
|||||||
|
|
||||||
private val weights: DoubleTensor = DoubleTensorAlgebra {
|
private val weights: DoubleTensor = DoubleTensorAlgebra {
|
||||||
randomNormal(
|
randomNormal(
|
||||||
Shape(inputUnits, outputUnits),
|
ShapeND(inputUnits, outputUnits),
|
||||||
seed
|
seed
|
||||||
) * sqrt(2.0 / (inputUnits + outputUnits))
|
) * 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 {
|
override fun forward(input: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra {
|
||||||
(input dot weights) + bias
|
(input dot weights) + bias
|
||||||
@ -184,17 +184,17 @@ fun main() = BroadcastDoubleTensorAlgebra {
|
|||||||
//val testSize = sampleSize - trainSize
|
//val testSize = sampleSize - trainSize
|
||||||
|
|
||||||
// take sample of features from normal distribution
|
// 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(
|
x += fromArray(
|
||||||
Shape(5),
|
ShapeND(5),
|
||||||
doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // row means
|
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
|
// define class like '1' if the sum of features > 0 and '0' otherwise
|
||||||
val y = fromArray(
|
val y = fromArray(
|
||||||
Shape(sampleSize, 1),
|
ShapeND(sampleSize, 1),
|
||||||
DoubleArray(sampleSize) { i ->
|
DoubleArray(sampleSize) { i ->
|
||||||
if (x.getTensor(i).sum() > 0.0) {
|
if (x.getTensor(i).sum() > 0.0) {
|
||||||
1.0
|
1.0
|
||||||
|
@ -59,7 +59,7 @@ public sealed class ComplexFieldOpsND : BufferedFieldOpsND<Complex, ComplexField
|
|||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(UnstableKMathAPI::class)
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public class ComplexFieldND(override val shape: Shape) :
|
public class ComplexFieldND(override val shape: ShapeND) :
|
||||||
ComplexFieldOpsND(), FieldND<Complex, ComplexField>,
|
ComplexFieldOpsND(), FieldND<Complex, ComplexField>,
|
||||||
NumbersAddOps<StructureND<Complex>> {
|
NumbersAddOps<StructureND<Complex>> {
|
||||||
|
|
||||||
@ -71,12 +71,12 @@ public class ComplexFieldND(override val shape: Shape) :
|
|||||||
|
|
||||||
public val ComplexField.ndAlgebra: ComplexFieldOpsND get() = ComplexFieldOpsND
|
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
|
* Produce a context for n-dimensional operations inside this real field
|
||||||
*/
|
*/
|
||||||
public inline fun <R> ComplexField.withNdAlgebra(vararg shape: Int, action: ComplexFieldND.() -> R): R {
|
public inline fun <R> ComplexField.withNdAlgebra(vararg shape: Int, action: ComplexFieldND.() -> R): R {
|
||||||
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
|
||||||
return ComplexFieldND(Shape(shape)).action()
|
return ComplexFieldND(ShapeND(shape)).action()
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ public class BufferedLinearSpace<T, out A : Ring<T>>(
|
|||||||
private val ndAlgebra = BufferedRingOpsND(bufferAlgebra)
|
private val ndAlgebra = BufferedRingOpsND(bufferAlgebra)
|
||||||
|
|
||||||
override fun buildMatrix(rows: Int, columns: Int, initializer: A.(i: Int, j: Int) -> T): Matrix<T> =
|
override fun buildMatrix(rows: Int, columns: Int, initializer: A.(i: Int, j: Int) -> T): Matrix<T> =
|
||||||
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<T> =
|
override fun buildVector(size: Int, initializer: A.(Int) -> T): Point<T> =
|
||||||
bufferAlgebra.buffer(size) { elementAlgebra.initializer(it) }
|
bufferAlgebra.buffer(size) { elementAlgebra.initializer(it) }
|
||||||
|
@ -21,7 +21,7 @@ public object DoubleLinearSpace : LinearSpace<Double, DoubleField> {
|
|||||||
rows: Int,
|
rows: Int,
|
||||||
columns: Int,
|
columns: Int,
|
||||||
initializer: DoubleField.(i: Int, j: Int) -> Double
|
initializer: DoubleField.(i: Int, j: Int) -> Double
|
||||||
): Matrix<Double> = DoubleFieldOpsND.structureND(Shape(rows, columns)) { (i, j) ->
|
): Matrix<Double> = DoubleFieldOpsND.structureND(ShapeND(rows, columns)) { (i, j) ->
|
||||||
DoubleField.initializer(i, j)
|
DoubleField.initializer(i, j)
|
||||||
}.as2D()
|
}.as2D()
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.linear
|
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.
|
* The matrix where each element is evaluated each time when is being accessed.
|
||||||
@ -18,7 +19,7 @@ public class VirtualMatrix<out T : Any>(
|
|||||||
public val generator: (i: Int, j: Int) -> T,
|
public val generator: (i: Int, j: Int) -> T,
|
||||||
) : Matrix<T> {
|
) : Matrix<T> {
|
||||||
|
|
||||||
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)
|
override operator fun get(i: Int, j: Int): T = generator(i, j)
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ public interface AlgebraND<T, out C : Algebra<T>>: Algebra<StructureND<T>> {
|
|||||||
/**
|
/**
|
||||||
* Produces a new [StructureND] using given initializer function.
|
* Produces a new [StructureND] using given initializer function.
|
||||||
*/
|
*/
|
||||||
public fun structureND(shape: Shape, initializer: C.(IntArray) -> T): StructureND<T>
|
public fun structureND(shape: ShapeND, initializer: C.(IntArray) -> T): StructureND<T>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps elements from one structure to another one by applying [transform] to them.
|
* Maps elements from one structure to another one by applying [transform] to them.
|
||||||
|
@ -12,11 +12,11 @@ import space.kscience.kmath.misc.UnstableKMathAPI
|
|||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
|
|
||||||
public interface BufferAlgebraND<T, out A : Algebra<T>> : AlgebraND<T, A> {
|
public interface BufferAlgebraND<T, out A : Algebra<T>> : AlgebraND<T, A> {
|
||||||
public val indexerBuilder: (Shape) -> ShapeIndexer
|
public val indexerBuilder: (ShapeND) -> ShapeIndexer
|
||||||
public val bufferAlgebra: BufferAlgebra<T, A>
|
public val bufferAlgebra: BufferAlgebra<T, A>
|
||||||
override val elementAlgebra: A get() = bufferAlgebra.elementAlgebra
|
override val elementAlgebra: A get() = bufferAlgebra.elementAlgebra
|
||||||
|
|
||||||
override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): BufferND<T> {
|
override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): BufferND<T> {
|
||||||
val indexer = indexerBuilder(shape)
|
val indexer = indexerBuilder(shape)
|
||||||
return BufferND(
|
return BufferND(
|
||||||
indexer,
|
indexer,
|
||||||
@ -47,7 +47,7 @@ public interface BufferAlgebraND<T, out A : Algebra<T>> : AlgebraND<T, A> {
|
|||||||
zipInline(left.toBufferND(), right.toBufferND(), transform)
|
zipInline(left.toBufferND(), right.toBufferND(), transform)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
public val defaultIndexerBuilder: (Shape) -> ShapeIndexer = ::Strides
|
public val defaultIndexerBuilder: (ShapeND) -> ShapeIndexer = ::Strides
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,24 +99,24 @@ internal inline fun <T, A : Algebra<T>> BufferAlgebraND<T, A>.zipInline(
|
|||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
public open class BufferedGroupNDOps<T, out A : Group<T>>(
|
public open class BufferedGroupNDOps<T, out A : Group<T>>(
|
||||||
override val bufferAlgebra: BufferAlgebra<T, A>,
|
override val bufferAlgebra: BufferAlgebra<T, A>,
|
||||||
override val indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder,
|
override val indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder,
|
||||||
) : GroupOpsND<T, A>, BufferAlgebraND<T, A> {
|
) : GroupOpsND<T, A>, BufferAlgebraND<T, A> {
|
||||||
override fun StructureND<T>.unaryMinus(): StructureND<T> = map { -it }
|
override fun StructureND<T>.unaryMinus(): StructureND<T> = map { -it }
|
||||||
}
|
}
|
||||||
|
|
||||||
public open class BufferedRingOpsND<T, out A : Ring<T>>(
|
public open class BufferedRingOpsND<T, out A : Ring<T>>(
|
||||||
bufferAlgebra: BufferAlgebra<T, A>,
|
bufferAlgebra: BufferAlgebra<T, A>,
|
||||||
indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder,
|
indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder,
|
||||||
) : BufferedGroupNDOps<T, A>(bufferAlgebra, indexerBuilder), RingOpsND<T, A>
|
) : BufferedGroupNDOps<T, A>(bufferAlgebra, indexerBuilder), RingOpsND<T, A>
|
||||||
|
|
||||||
public open class BufferedFieldOpsND<T, out A : Field<T>>(
|
public open class BufferedFieldOpsND<T, out A : Field<T>>(
|
||||||
bufferAlgebra: BufferAlgebra<T, A>,
|
bufferAlgebra: BufferAlgebra<T, A>,
|
||||||
indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder,
|
indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder,
|
||||||
) : BufferedRingOpsND<T, A>(bufferAlgebra, indexerBuilder), FieldOpsND<T, A> {
|
) : BufferedRingOpsND<T, A>(bufferAlgebra, indexerBuilder), FieldOpsND<T, A> {
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
elementAlgebra: A,
|
elementAlgebra: A,
|
||||||
indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder,
|
indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder,
|
||||||
) : this(BufferFieldOps(elementAlgebra), indexerBuilder)
|
) : this(BufferFieldOps(elementAlgebra), indexerBuilder)
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
@ -131,7 +131,7 @@ public val <T, A : Field<T>> BufferAlgebra<T, A>.nd: BufferedFieldOpsND<T, A> ge
|
|||||||
public fun <T, A : Algebra<T>> BufferAlgebraND<T, A>.structureND(
|
public fun <T, A : Algebra<T>> BufferAlgebraND<T, A>.structureND(
|
||||||
vararg shape: Int,
|
vararg shape: Int,
|
||||||
initializer: A.(IntArray) -> T,
|
initializer: A.(IntArray) -> T,
|
||||||
): BufferND<T> = structureND(Shape(shape), initializer)
|
): BufferND<T> = structureND(ShapeND(shape), initializer)
|
||||||
|
|
||||||
public fun <T, EA : Algebra<T>, A> A.structureND(
|
public fun <T, EA : Algebra<T>, A> A.structureND(
|
||||||
initializer: EA.(IntArray) -> T,
|
initializer: EA.(IntArray) -> T,
|
||||||
|
@ -24,7 +24,7 @@ public open class BufferND<out T>(
|
|||||||
@PerformancePitfall
|
@PerformancePitfall
|
||||||
override operator fun get(index: IntArray): T = buffer[indices.offset(index)]
|
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)
|
override fun toString(): String = StructureND.toString(this)
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND<Double, DoubleField>(D
|
|||||||
transform: DoubleField.(Double, Double) -> Double,
|
transform: DoubleField.(Double, Double) -> Double,
|
||||||
): BufferND<Double> = zipInline(left.toBufferND(), right.toBufferND()) { l, r -> DoubleField.transform(l, r) }
|
): BufferND<Double> = zipInline(left.toBufferND(), right.toBufferND()) { l, r -> DoubleField.transform(l, r) }
|
||||||
|
|
||||||
override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): DoubleBufferND {
|
override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): DoubleBufferND {
|
||||||
val indexer = indexerBuilder(shape)
|
val indexer = indexerBuilder(shape)
|
||||||
return DoubleBufferND(
|
return DoubleBufferND(
|
||||||
indexer,
|
indexer,
|
||||||
@ -189,7 +189,7 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND<Double, DoubleField>(D
|
|||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(UnstableKMathAPI::class)
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public class DoubleFieldND(override val shape: Shape) :
|
public class DoubleFieldND(override val shape: ShapeND) :
|
||||||
DoubleFieldOpsND(), FieldND<Double, DoubleField>, NumbersAddOps<StructureND<Double>>,
|
DoubleFieldOpsND(), FieldND<Double, DoubleField>, NumbersAddOps<StructureND<Double>>,
|
||||||
ExtendedField<StructureND<Double>> {
|
ExtendedField<StructureND<Double>> {
|
||||||
|
|
||||||
@ -231,8 +231,8 @@ public class DoubleFieldND(override val shape: Shape) :
|
|||||||
|
|
||||||
public val DoubleField.ndAlgebra: DoubleFieldOpsND get() = DoubleFieldOpsND
|
public val DoubleField.ndAlgebra: DoubleFieldOpsND get() = DoubleFieldOpsND
|
||||||
|
|
||||||
public fun DoubleField.ndAlgebra(vararg shape: Int): DoubleFieldND = DoubleFieldND(Shape(shape))
|
public fun DoubleField.ndAlgebra(vararg shape: Int): DoubleFieldND = DoubleFieldND(ShapeND(shape))
|
||||||
public fun DoubleField.ndAlgebra(shape: Shape): DoubleFieldND = DoubleFieldND(shape)
|
public fun DoubleField.ndAlgebra(shape: ShapeND): DoubleFieldND = DoubleFieldND(shape)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce a context for n-dimensional operations inside this real field
|
* 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
|
@UnstableKMathAPI
|
||||||
public inline fun <R> DoubleField.withNdAlgebra(vararg shape: Int, action: DoubleFieldND.() -> R): R {
|
public inline fun <R> DoubleField.withNdAlgebra(vararg shape: Int, action: DoubleFieldND.() -> R): R {
|
||||||
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
|
||||||
return DoubleFieldND(Shape(shape)).run(action)
|
return DoubleFieldND(ShapeND(shape)).run(action)
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ public class IntBufferND(
|
|||||||
|
|
||||||
public sealed class IntRingOpsND : BufferedRingOpsND<Int, IntRing>(IntRing.bufferAlgebra) {
|
public sealed class IntRingOpsND : BufferedRingOpsND<Int, IntRing>(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)
|
val indexer = indexerBuilder(shape)
|
||||||
return IntBufferND(
|
return IntBufferND(
|
||||||
indexer,
|
indexer,
|
||||||
@ -35,7 +35,7 @@ public sealed class IntRingOpsND : BufferedRingOpsND<Int, IntRing>(IntRing.buffe
|
|||||||
|
|
||||||
@OptIn(UnstableKMathAPI::class)
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public class IntRingND(
|
public class IntRingND(
|
||||||
override val shape: Shape
|
override val shape: ShapeND
|
||||||
) : IntRingOpsND(), RingND<Int, IntRing>, NumbersAddOps<StructureND<Int>> {
|
) : IntRingOpsND(), RingND<Int, IntRing>, NumbersAddOps<StructureND<Int>> {
|
||||||
|
|
||||||
override fun number(value: Number): BufferND<Int> {
|
override fun number(value: Number): BufferND<Int> {
|
||||||
@ -46,5 +46,5 @@ public class IntRingND(
|
|||||||
|
|
||||||
public inline fun <R> IntRing.withNdAlgebra(vararg shape: Int, action: IntRingND.() -> R): R {
|
public inline fun <R> IntRing.withNdAlgebra(vararg shape: Int, action: IntRingND.() -> R): R {
|
||||||
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
|
||||||
return IntRingND(Shape(shape)).run(action)
|
return IntRingND(ShapeND(shape)).run(action)
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ public class PermutedStructureND<T>(
|
|||||||
public val permutation: (IntArray) -> IntArray,
|
public val permutation: (IntArray) -> IntArray,
|
||||||
) : StructureND<T> {
|
) : StructureND<T> {
|
||||||
|
|
||||||
override val shape: Shape
|
override val shape: ShapeND
|
||||||
get() = origin.shape
|
get() = origin.shape
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
@ -28,7 +28,7 @@ public fun <T> StructureND<T>.permute(
|
|||||||
|
|
||||||
public class PermutedMutableStructureND<T>(
|
public class PermutedMutableStructureND<T>(
|
||||||
public val origin: MutableStructureND<T>,
|
public val origin: MutableStructureND<T>,
|
||||||
override val shape: Shape = origin.shape,
|
override val shape: ShapeND = origin.shape,
|
||||||
public val permutation: (IntArray) -> IntArray,
|
public val permutation: (IntArray) -> IntArray,
|
||||||
) : MutableStructureND<T> {
|
) : MutableStructureND<T> {
|
||||||
|
|
||||||
@ -45,6 +45,6 @@ public class PermutedMutableStructureND<T>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun <T> MutableStructureND<T>.permute(
|
public fun <T> MutableStructureND<T>.permute(
|
||||||
newShape: Shape = shape,
|
newShape: ShapeND = shape,
|
||||||
permutation: (IntArray) -> IntArray,
|
permutation: (IntArray) -> IntArray,
|
||||||
): PermutedMutableStructureND<T> = PermutedMutableStructureND(this, newShape, permutation)
|
): PermutedMutableStructureND<T> = PermutedMutableStructureND(this, newShape, permutation)
|
@ -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<Int> = 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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,7 +12,7 @@ import kotlin.native.concurrent.ThreadLocal
|
|||||||
* A converter from linear index to multivariate index
|
* A converter from linear index to multivariate index
|
||||||
*/
|
*/
|
||||||
public interface ShapeIndexer : Iterable<IntArray> {
|
public interface ShapeIndexer : Iterable<IntArray> {
|
||||||
public val shape: Shape
|
public val shape: ShapeND
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get linear index from multidimensional index
|
* Get linear index from multidimensional index
|
||||||
@ -68,7 +68,7 @@ public abstract class Strides : ShapeIndexer {
|
|||||||
/**
|
/**
|
||||||
* Column-first [Strides]. Columns are represented as continuous arrays
|
* 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]
|
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.
|
* @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 {
|
override val strides: IntArray by lazy {
|
||||||
val nDim = shape.size
|
val nDim = shape.size
|
||||||
@ -163,9 +163,9 @@ public class RowStrides(override val shape: Shape) : Strides() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ThreadLocal
|
@ThreadLocal
|
||||||
private val defaultStridesCache = HashMap<Shape, Strides>()
|
private val defaultStridesCache = HashMap<ShapeND, Strides>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cached builder for default strides
|
* Cached builder for default strides
|
||||||
*/
|
*/
|
||||||
public fun Strides(shape: Shape): Strides = defaultStridesCache.getOrPut(shape) { RowStrides(shape) }
|
public fun Strides(shape: ShapeND): Strides = defaultStridesCache.getOrPut(shape) { RowStrides(shape) }
|
@ -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<Int> = 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)
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@ public sealed class ShortRingOpsND : BufferedRingOpsND<Short, ShortRing>(ShortRi
|
|||||||
|
|
||||||
@OptIn(UnstableKMathAPI::class)
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public class ShortRingND(
|
public class ShortRingND(
|
||||||
override val shape: Shape
|
override val shape: ShapeND
|
||||||
) : ShortRingOpsND(), RingND<Short, ShortRing>, NumbersAddOps<StructureND<Short>> {
|
) : ShortRingOpsND(), RingND<Short, ShortRing>, NumbersAddOps<StructureND<Short>> {
|
||||||
|
|
||||||
override fun number(value: Number): BufferND<Short> {
|
override fun number(value: Number): BufferND<Short> {
|
||||||
@ -30,5 +30,5 @@ public class ShortRingND(
|
|||||||
|
|
||||||
public inline fun <R> ShortRing.withNdAlgebra(vararg shape: Int, action: ShortRingND.() -> R): R {
|
public inline fun <R> ShortRing.withNdAlgebra(vararg shape: Int, action: ShortRingND.() -> R): R {
|
||||||
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
|
||||||
return ShortRingND(Shape(shape)).run(action)
|
return ShortRingND(ShapeND(shape)).run(action)
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ public interface MutableStructure1D<T> : Structure1D<T>, MutableStructureND<T>,
|
|||||||
*/
|
*/
|
||||||
@JvmInline
|
@JvmInline
|
||||||
private value class Structure1DWrapper<out T>(val structure: StructureND<T>) : Structure1D<T> {
|
private value class Structure1DWrapper<out T>(val structure: StructureND<T>) : Structure1D<T> {
|
||||||
override val shape: Shape get() = structure.shape
|
override val shape: ShapeND get() = structure.shape
|
||||||
override val size: Int get() = structure.shape[0]
|
override val size: Int get() = structure.shape[0]
|
||||||
|
|
||||||
@PerformancePitfall
|
@PerformancePitfall
|
||||||
@ -60,7 +60,7 @@ private value class Structure1DWrapper<out T>(val structure: StructureND<T>) : S
|
|||||||
* A 1D wrapper for a mutable nd-structure
|
* A 1D wrapper for a mutable nd-structure
|
||||||
*/
|
*/
|
||||||
private class MutableStructure1DWrapper<T>(val structure: MutableStructureND<T>) : MutableStructure1D<T> {
|
private class MutableStructure1DWrapper<T>(val structure: MutableStructureND<T>) : MutableStructure1D<T> {
|
||||||
override val shape: Shape get() = structure.shape
|
override val shape: ShapeND get() = structure.shape
|
||||||
override val size: Int get() = structure.shape[0]
|
override val size: Int get() = structure.shape[0]
|
||||||
|
|
||||||
@PerformancePitfall
|
@PerformancePitfall
|
||||||
@ -90,7 +90,7 @@ private class MutableStructure1DWrapper<T>(val structure: MutableStructureND<T>)
|
|||||||
*/
|
*/
|
||||||
@JvmInline
|
@JvmInline
|
||||||
private value class Buffer1DWrapper<out T>(val buffer: Buffer<T>) : Structure1D<T> {
|
private value class Buffer1DWrapper<out T>(val buffer: Buffer<T>) : Structure1D<T> {
|
||||||
override val shape: Shape get() = Shape(buffer.size)
|
override val shape: ShapeND get() = ShapeND(buffer.size)
|
||||||
override val size: Int get() = buffer.size
|
override val size: Int get() = buffer.size
|
||||||
|
|
||||||
@PerformancePitfall
|
@PerformancePitfall
|
||||||
@ -102,7 +102,7 @@ private value class Buffer1DWrapper<out T>(val buffer: Buffer<T>) : Structure1D<
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal class MutableBuffer1DWrapper<T>(val buffer: MutableBuffer<T>) : MutableStructure1D<T> {
|
internal class MutableBuffer1DWrapper<T>(val buffer: MutableBuffer<T>) : MutableStructure1D<T> {
|
||||||
override val shape: Shape get() = Shape(buffer.size)
|
override val shape: ShapeND get() = ShapeND(buffer.size)
|
||||||
override val size: Int get() = buffer.size
|
override val size: Int get() = buffer.size
|
||||||
|
|
||||||
@PerformancePitfall
|
@PerformancePitfall
|
||||||
|
@ -29,7 +29,7 @@ public interface Structure2D<out T> : StructureND<T> {
|
|||||||
*/
|
*/
|
||||||
public val colNum: Int
|
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.
|
* The buffer of rows of this structure. It gets elements from the structure dynamically.
|
||||||
@ -102,7 +102,7 @@ public interface MutableStructure2D<T> : Structure2D<T>, MutableStructureND<T> {
|
|||||||
*/
|
*/
|
||||||
@JvmInline
|
@JvmInline
|
||||||
private value class Structure2DWrapper<out T>(val structure: StructureND<T>) : Structure2D<T> {
|
private value class Structure2DWrapper<out T>(val structure: StructureND<T>) : Structure2D<T> {
|
||||||
override val shape: Shape get() = structure.shape
|
override val shape: ShapeND get() = structure.shape
|
||||||
|
|
||||||
override val rowNum: Int get() = shape[0]
|
override val rowNum: Int get() = shape[0]
|
||||||
override val colNum: Int get() = shape[1]
|
override val colNum: Int get() = shape[1]
|
||||||
@ -120,7 +120,7 @@ private value class Structure2DWrapper<out T>(val structure: StructureND<T>) : S
|
|||||||
* A 2D wrapper for a mutable nd-structure
|
* A 2D wrapper for a mutable nd-structure
|
||||||
*/
|
*/
|
||||||
private class MutableStructure2DWrapper<T>(val structure: MutableStructureND<T>) : MutableStructure2D<T> {
|
private class MutableStructure2DWrapper<T>(val structure: MutableStructureND<T>) : MutableStructure2D<T> {
|
||||||
override val shape: Shape get() = structure.shape
|
override val shape: ShapeND get() = structure.shape
|
||||||
|
|
||||||
override val rowNum: Int get() = shape[0]
|
override val rowNum: Int get() = shape[0]
|
||||||
override val colNum: Int get() = shape[1]
|
override val colNum: Int get() = shape[1]
|
||||||
|
@ -33,7 +33,7 @@ public interface StructureND<out T> : Featured<StructureFeature>, WithShape {
|
|||||||
* The shape of structure i.e., non-empty sequence of non-negative integers that specify sizes of dimensions of
|
* The shape of structure i.e., non-empty sequence of non-negative integers that specify sizes of dimensions of
|
||||||
* this structure.
|
* 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].
|
* The count of dimensions in this structure. It should be equal to size of [shape].
|
||||||
@ -147,13 +147,13 @@ public interface StructureND<out T> : Featured<StructureFeature>, WithShape {
|
|||||||
): BufferND<T> = BufferND(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) })
|
): BufferND<T> = BufferND(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) })
|
||||||
|
|
||||||
public fun <T> buffered(
|
public fun <T> buffered(
|
||||||
shape: Shape,
|
shape: ShapeND,
|
||||||
bufferFactory: BufferFactory<T> = BufferFactory.boxing(),
|
bufferFactory: BufferFactory<T> = BufferFactory.boxing(),
|
||||||
initializer: (IntArray) -> T,
|
initializer: (IntArray) -> T,
|
||||||
): BufferND<T> = buffered(ColumnStrides(shape), bufferFactory, initializer)
|
): BufferND<T> = buffered(ColumnStrides(shape), bufferFactory, initializer)
|
||||||
|
|
||||||
public inline fun <reified T : Any> auto(
|
public inline fun <reified T : Any> auto(
|
||||||
shape: Shape,
|
shape: ShapeND,
|
||||||
crossinline initializer: (IntArray) -> T,
|
crossinline initializer: (IntArray) -> T,
|
||||||
): BufferND<T> = auto(ColumnStrides(shape), initializer)
|
): BufferND<T> = auto(ColumnStrides(shape), initializer)
|
||||||
|
|
||||||
@ -162,13 +162,13 @@ public interface StructureND<out T> : Featured<StructureFeature>, WithShape {
|
|||||||
vararg shape: Int,
|
vararg shape: Int,
|
||||||
crossinline initializer: (IntArray) -> T,
|
crossinline initializer: (IntArray) -> T,
|
||||||
): BufferND<T> =
|
): BufferND<T> =
|
||||||
auto(ColumnStrides(Shape(shape)), initializer)
|
auto(ColumnStrides(ShapeND(shape)), initializer)
|
||||||
|
|
||||||
public inline fun <T : Any> auto(
|
public inline fun <T : Any> auto(
|
||||||
type: KClass<T>,
|
type: KClass<T>,
|
||||||
vararg shape: Int,
|
vararg shape: Int,
|
||||||
crossinline initializer: (IntArray) -> T,
|
crossinline initializer: (IntArray) -> T,
|
||||||
): BufferND<T> = auto(type, ColumnStrides(Shape(shape)), initializer)
|
): BufferND<T> = auto(type, ColumnStrides(ShapeND(shape)), initializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import space.kscience.kmath.misc.PerformancePitfall
|
|||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
|
||||||
public open class VirtualStructureND<T>(
|
public open class VirtualStructureND<T>(
|
||||||
override val shape: Shape,
|
override val shape: ShapeND,
|
||||||
public val producer: (IntArray) -> T,
|
public val producer: (IntArray) -> T,
|
||||||
) : StructureND<T> {
|
) : StructureND<T> {
|
||||||
|
|
||||||
@ -22,12 +22,12 @@ public open class VirtualStructureND<T>(
|
|||||||
|
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class VirtualDoubleStructureND(
|
public class VirtualDoubleStructureND(
|
||||||
shape: Shape,
|
shape: ShapeND,
|
||||||
producer: (IntArray) -> Double,
|
producer: (IntArray) -> Double,
|
||||||
) : VirtualStructureND<Double>(shape, producer)
|
) : VirtualStructureND<Double>(shape, producer)
|
||||||
|
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class VirtualIntStructureND(
|
public class VirtualIntStructureND(
|
||||||
shape: Shape,
|
shape: ShapeND,
|
||||||
producer: (IntArray) -> Int,
|
producer: (IntArray) -> Int,
|
||||||
) : VirtualStructureND<Int>(shape, producer)
|
) : VirtualStructureND<Int>(shape, producer)
|
@ -15,9 +15,9 @@ public fun <T, A : Algebra<T>> AlgebraND<T, A>.structureND(
|
|||||||
shapeFirst: Int,
|
shapeFirst: Int,
|
||||||
vararg shapeRest: Int,
|
vararg shapeRest: Int,
|
||||||
initializer: A.(IntArray) -> T
|
initializer: A.(IntArray) -> T
|
||||||
): StructureND<T> = structureND(Shape(shapeFirst, *shapeRest), initializer)
|
): StructureND<T> = structureND(ShapeND(shapeFirst, *shapeRest), initializer)
|
||||||
|
|
||||||
public fun <T, A : Group<T>> AlgebraND<T, A>.zero(shape: Shape): StructureND<T> = structureND(shape) { zero }
|
public fun <T, A : Group<T>> AlgebraND<T, A>.zero(shape: ShapeND): StructureND<T> = structureND(shape) { zero }
|
||||||
|
|
||||||
@JvmName("zeroVarArg")
|
@JvmName("zeroVarArg")
|
||||||
public fun <T, A : Group<T>> AlgebraND<T, A>.zero(
|
public fun <T, A : Group<T>> AlgebraND<T, A>.zero(
|
||||||
@ -25,7 +25,7 @@ public fun <T, A : Group<T>> AlgebraND<T, A>.zero(
|
|||||||
vararg shapeRest: Int,
|
vararg shapeRest: Int,
|
||||||
): StructureND<T> = structureND(shapeFirst, *shapeRest) { zero }
|
): StructureND<T> = structureND(shapeFirst, *shapeRest) { zero }
|
||||||
|
|
||||||
public fun <T, A : Ring<T>> AlgebraND<T, A>.one(shape: Shape): StructureND<T> = structureND(shape) { one }
|
public fun <T, A : Ring<T>> AlgebraND<T, A>.one(shape: ShapeND): StructureND<T> = structureND(shape) { one }
|
||||||
|
|
||||||
@JvmName("oneVarArg")
|
@JvmName("oneVarArg")
|
||||||
public fun <T, A : Ring<T>> AlgebraND<T, A>.one(
|
public fun <T, A : Ring<T>> AlgebraND<T, A>.one(
|
||||||
|
@ -28,7 +28,7 @@ internal class BufferAccessor2D<T>(
|
|||||||
|
|
||||||
//TODO optimize wrapper
|
//TODO optimize wrapper
|
||||||
fun MutableBuffer<T>.collect(): Structure2D<T> = StructureND.buffered(
|
fun MutableBuffer<T>.collect(): Structure2D<T> = StructureND.buffered(
|
||||||
ColumnStrides(Shape(rowNum, colNum)),
|
ColumnStrides(ShapeND(rowNum, colNum)),
|
||||||
factory
|
factory
|
||||||
) { (i, j) ->
|
) { (i, j) ->
|
||||||
get(i, j)
|
get(i, j)
|
||||||
|
@ -10,7 +10,7 @@ import kotlin.test.Test
|
|||||||
class StridesTest {
|
class StridesTest {
|
||||||
@Test
|
@Test
|
||||||
fun checkRowBasedStrides() {
|
fun checkRowBasedStrides() {
|
||||||
val strides = RowStrides(Shape(3, 3))
|
val strides = RowStrides(ShapeND(3, 3))
|
||||||
var counter = 0
|
var counter = 0
|
||||||
for(i in 0..2){
|
for(i in 0..2){
|
||||||
for(j in 0..2){
|
for(j in 0..2){
|
||||||
@ -24,7 +24,7 @@ class StridesTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun checkColumnBasedStrides() {
|
fun checkColumnBasedStrides() {
|
||||||
val strides = ColumnStrides(Shape(3, 3))
|
val strides = ColumnStrides(ShapeND(3, 3))
|
||||||
var counter = 0
|
var counter = 0
|
||||||
for(i in 0..2){
|
for(i in 0..2){
|
||||||
for(j in 0..2){
|
for(j in 0..2){
|
||||||
|
@ -9,12 +9,12 @@ import kotlinx.coroutines.*
|
|||||||
import space.kscience.kmath.coroutines.Math
|
import space.kscience.kmath.coroutines.Math
|
||||||
import space.kscience.kmath.misc.PerformancePitfall
|
import space.kscience.kmath.misc.PerformancePitfall
|
||||||
import space.kscience.kmath.nd.ColumnStrides
|
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.nd.StructureND
|
||||||
|
|
||||||
public class LazyStructureND<out T>(
|
public class LazyStructureND<out T>(
|
||||||
public val scope: CoroutineScope,
|
public val scope: CoroutineScope,
|
||||||
override val shape: Shape,
|
override val shape: ShapeND,
|
||||||
public val function: suspend (IntArray) -> T,
|
public val function: suspend (IntArray) -> T,
|
||||||
) : StructureND<T> {
|
) : StructureND<T> {
|
||||||
private val cache: MutableMap<IntArray, Deferred<T>> = HashMap()
|
private val cache: MutableMap<IntArray, Deferred<T>> = HashMap()
|
||||||
@ -35,20 +35,24 @@ public class LazyStructureND<out T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(PerformancePitfall::class)
|
||||||
public fun <T> StructureND<T>.async(index: IntArray): Deferred<T> =
|
public fun <T> StructureND<T>.async(index: IntArray): Deferred<T> =
|
||||||
if (this is LazyStructureND<T>) this@async.async(index) else CompletableDeferred(get(index))
|
if (this is LazyStructureND<T>) this@async.async(index) else CompletableDeferred(get(index))
|
||||||
|
|
||||||
|
@OptIn(PerformancePitfall::class)
|
||||||
public suspend fun <T> StructureND<T>.await(index: IntArray): T =
|
public suspend fun <T> StructureND<T>.await(index: IntArray): T =
|
||||||
if (this is LazyStructureND<T>) await(index) else get(index)
|
if (this is LazyStructureND<T>) await(index) else get(index)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PENDING would benefit from KEEP-176
|
* PENDING would benefit from KEEP-176
|
||||||
*/
|
*/
|
||||||
|
@OptIn(PerformancePitfall::class)
|
||||||
public inline fun <T, R> StructureND<T>.mapAsyncIndexed(
|
public inline fun <T, R> StructureND<T>.mapAsyncIndexed(
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
crossinline function: suspend (T, index: IntArray) -> R,
|
crossinline function: suspend (T, index: IntArray) -> R,
|
||||||
): LazyStructureND<R> = LazyStructureND(scope, shape) { index -> function(get(index), index) }
|
): LazyStructureND<R> = LazyStructureND(scope, shape) { index -> function(get(index), index) }
|
||||||
|
|
||||||
|
@OptIn(PerformancePitfall::class)
|
||||||
public inline fun <T, R> StructureND<T>.mapAsync(
|
public inline fun <T, R> StructureND<T>.mapAsync(
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
crossinline function: suspend (T) -> R,
|
crossinline function: suspend (T) -> R,
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
package space.kscience.kmath.dimensions
|
package space.kscience.kmath.dimensions
|
||||||
|
|
||||||
import space.kscience.kmath.linear.*
|
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.nd.Structure2D
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.Ring
|
import space.kscience.kmath.operations.Ring
|
||||||
@ -48,7 +48,7 @@ public interface DMatrix<out T, R : Dimension, C : Dimension> : Structure2D<T> {
|
|||||||
public value class DMatrixWrapper<out T, R : Dimension, C : Dimension>(
|
public value class DMatrixWrapper<out T, R : Dimension, C : Dimension>(
|
||||||
private val structure: Structure2D<T>,
|
private val structure: Structure2D<T>,
|
||||||
) : DMatrix<T, R, C> {
|
) : DMatrix<T, R, C> {
|
||||||
override val shape: Shape get() = structure.shape
|
override val shape: ShapeND get() = structure.shape
|
||||||
override val rowNum: Int get() = shape[0]
|
override val rowNum: Int get() = shape[0]
|
||||||
override val colNum: Int get() = shape[1]
|
override val colNum: Int get() = shape[1]
|
||||||
override operator fun get(i: Int, j: Int): T = structure[i, j]
|
override operator fun get(i: Int, j: Int): T = structure[i, j]
|
||||||
|
@ -10,7 +10,7 @@ import space.kscience.kmath.linear.Point
|
|||||||
import space.kscience.kmath.misc.PerformancePitfall
|
import space.kscience.kmath.misc.PerformancePitfall
|
||||||
import space.kscience.kmath.nd.ColumnStrides
|
import space.kscience.kmath.nd.ColumnStrides
|
||||||
import space.kscience.kmath.nd.FieldOpsND
|
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.nd.StructureND
|
||||||
import space.kscience.kmath.operations.Group
|
import space.kscience.kmath.operations.Group
|
||||||
import space.kscience.kmath.operations.ScaleOperations
|
import space.kscience.kmath.operations.ScaleOperations
|
||||||
@ -45,7 +45,7 @@ public class HistogramND<T : Comparable<T>, D : Domain<T>, V : Any>(
|
|||||||
*/
|
*/
|
||||||
public interface HistogramGroupND<T : Comparable<T>, D : Domain<T>, V : Any> :
|
public interface HistogramGroupND<T : Comparable<T>, D : Domain<T>, V : Any> :
|
||||||
Group<HistogramND<T, D, V>>, ScaleOperations<HistogramND<T, D, V>> {
|
Group<HistogramND<T, D, V>>, ScaleOperations<HistogramND<T, D, V>> {
|
||||||
public val shape: Shape
|
public val shape: ShapeND
|
||||||
public val valueAlgebraND: FieldOpsND<V, *> //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape),
|
public val valueAlgebraND: FieldOpsND<V, *> //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,7 +39,7 @@ public class UniformHistogramGroupND<V : Any, A : Field<V>>(
|
|||||||
|
|
||||||
public val dimension: Int get() = lower.size
|
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] }
|
private val binSize = DoubleBuffer(dimension) { (upper[it] - lower[it]) / binNums[it] }
|
||||||
|
|
||||||
|
@ -7,13 +7,13 @@ package space.kscience.kmath.multik
|
|||||||
|
|
||||||
import org.jetbrains.kotlinx.multik.ndarray.data.*
|
import org.jetbrains.kotlinx.multik.ndarray.data.*
|
||||||
import space.kscience.kmath.misc.PerformancePitfall
|
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 space.kscience.kmath.tensors.api.Tensor
|
||||||
import kotlin.jvm.JvmInline
|
import kotlin.jvm.JvmInline
|
||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
public value class MultikTensor<T>(public val array: MutableMultiArray<T, DN>) : Tensor<T> {
|
public value class MultikTensor<T>(public val array: MutableMultiArray<T, DN>) : Tensor<T> {
|
||||||
override val shape: Shape get() = Shape(array.shape)
|
override val shape: ShapeND get() = ShapeND(array.shape)
|
||||||
|
|
||||||
@PerformancePitfall
|
@PerformancePitfall
|
||||||
override fun get(index: IntArray): T = array[index]
|
override fun get(index: IntArray): T = array[index]
|
||||||
|
@ -32,7 +32,7 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>>(
|
|||||||
protected val multikStat: Statistics = multikEngine.getStatistics()
|
protected val multikStat: Statistics = multikEngine.getStatistics()
|
||||||
|
|
||||||
@OptIn(UnsafeKMathAPI::class)
|
@OptIn(UnsafeKMathAPI::class)
|
||||||
override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): MultikTensor<T> {
|
override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): MultikTensor<T> {
|
||||||
val strides = ColumnStrides(shape)
|
val strides = ColumnStrides(shape)
|
||||||
val memoryView = initMemoryView<T>(strides.linearSize, type)
|
val memoryView = initMemoryView<T>(strides.linearSize, type)
|
||||||
strides.asSequence().forEachIndexed { linearIndex, tensorIndex ->
|
strides.asSequence().forEachIndexed { linearIndex, tensorIndex ->
|
||||||
@ -123,7 +123,7 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>>(
|
|||||||
public fun MutableMultiArray<T, *>.wrap(): MultikTensor<T> = MultikTensor(this.asDNArray())
|
public fun MutableMultiArray<T, *>.wrap(): MultikTensor<T> = MultikTensor(this.asDNArray())
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
override fun StructureND<T>.valueOrNull(): T? = if (shape contentEquals Shape(1)) {
|
override fun StructureND<T>.valueOrNull(): T? = if (shape contentEquals ShapeND(1)) {
|
||||||
get(intArrayOf(0))
|
get(intArrayOf(0))
|
||||||
} else null
|
} else null
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>>(
|
|||||||
|
|
||||||
override fun StructureND<T>.transposed(i: Int, j: Int): MultikTensor<T> = asMultik().array.transpose(i, j).wrap()
|
override fun StructureND<T>.transposed(i: Int, j: Int): MultikTensor<T> = asMultik().array.transpose(i, j).wrap()
|
||||||
|
|
||||||
override fun Tensor<T>.view(shape: Shape): MultikTensor<T> {
|
override fun Tensor<T>.view(shape: ShapeND): MultikTensor<T> {
|
||||||
require(shape.asList().all { it > 0 })
|
require(shape.asList().all { it > 0 })
|
||||||
require(shape.linearSize == this.shape.size) {
|
require(shape.linearSize == this.shape.size) {
|
||||||
"Cannot reshape array of size ${this.shape.size} into a new shape ${
|
"Cannot reshape array of size ${this.shape.size} into a new shape ${
|
||||||
@ -223,7 +223,7 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val mt = asMultik().array
|
val mt = asMultik().array
|
||||||
return if (Shape(mt.shape).contentEquals(shape)) {
|
return if (ShapeND(mt.shape).contentEquals(shape)) {
|
||||||
mt
|
mt
|
||||||
} else {
|
} else {
|
||||||
@OptIn(UnsafeKMathAPI::class)
|
@OptIn(UnsafeKMathAPI::class)
|
||||||
|
@ -7,7 +7,7 @@ package space.kscience.kmath.multik
|
|||||||
|
|
||||||
import org.jetbrains.kotlinx.multik.default.DefaultEngine
|
import org.jetbrains.kotlinx.multik.default.DefaultEngine
|
||||||
import space.kscience.kmath.misc.PerformancePitfall
|
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.StructureND
|
||||||
import space.kscience.kmath.nd.one
|
import space.kscience.kmath.nd.one
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
@ -29,8 +29,8 @@ internal class MultikNDTest {
|
|||||||
fun dotResult() {
|
fun dotResult() {
|
||||||
val dim = 100
|
val dim = 100
|
||||||
|
|
||||||
val tensor1 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12224)
|
val tensor1 = DoubleTensorAlgebra.randomNormal(shape = ShapeND(dim, dim), 12224)
|
||||||
val tensor2 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12225)
|
val tensor2 = DoubleTensorAlgebra.randomNormal(shape = ShapeND(dim, dim), 12225)
|
||||||
|
|
||||||
val multikResult = with(multikAlgebra) {
|
val multikResult = with(multikAlgebra) {
|
||||||
tensor1 dot tensor2
|
tensor1 dot tensor2
|
||||||
|
@ -33,7 +33,8 @@ public sealed interface Nd4jArrayAlgebra<T, out C : Algebra<T>> : AlgebraND<T, C
|
|||||||
*/
|
*/
|
||||||
public val StructureND<T>.ndArray: INDArray
|
public val StructureND<T>.ndArray: INDArray
|
||||||
|
|
||||||
override fun structureND(shape: Shape, initializer: C.(IntArray) -> T): Nd4jArrayStructure<T> {
|
@OptIn(PerformancePitfall::class)
|
||||||
|
override fun structureND(shape: ShapeND, initializer: C.(IntArray) -> T): Nd4jArrayStructure<T> {
|
||||||
@OptIn(UnsafeKMathAPI::class)
|
@OptIn(UnsafeKMathAPI::class)
|
||||||
val struct: Nd4jArrayStructure<T> = Nd4j.create(*shape.asArray())!!.wrap()
|
val struct: Nd4jArrayStructure<T> = Nd4j.create(*shape.asArray())!!.wrap()
|
||||||
struct.indicesIterator().forEach { struct[it] = elementAlgebra.initializer(it) }
|
struct.indicesIterator().forEach { struct[it] = elementAlgebra.initializer(it) }
|
||||||
@ -224,10 +225,10 @@ public open class DoubleNd4jArrayFieldOps : Nd4jArrayExtendedFieldOps<Double, Do
|
|||||||
|
|
||||||
public val DoubleField.nd4j: DoubleNd4jArrayFieldOps get() = DoubleNd4jArrayFieldOps
|
public val DoubleField.nd4j: DoubleNd4jArrayFieldOps get() = DoubleNd4jArrayFieldOps
|
||||||
|
|
||||||
public class DoubleNd4jArrayField(override val shape: Shape) : DoubleNd4jArrayFieldOps(), FieldND<Double, DoubleField>
|
public class DoubleNd4jArrayField(override val shape: ShapeND) : DoubleNd4jArrayFieldOps(), FieldND<Double, DoubleField>
|
||||||
|
|
||||||
public fun DoubleField.nd4j(shapeFirst: Int, vararg shapeRest: Int): DoubleNd4jArrayField =
|
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<Float, Floa
|
|||||||
public companion object : FloatNd4jArrayFieldOps()
|
public companion object : FloatNd4jArrayFieldOps()
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FloatNd4jArrayField(override val shape: Shape) : FloatNd4jArrayFieldOps(), RingND<Float, FloatField>
|
public class FloatNd4jArrayField(override val shape: ShapeND) : FloatNd4jArrayFieldOps(), RingND<Float, FloatField>
|
||||||
|
|
||||||
public val FloatField.nd4j: FloatNd4jArrayFieldOps get() = FloatNd4jArrayFieldOps
|
public val FloatField.nd4j: FloatNd4jArrayFieldOps get() = FloatNd4jArrayFieldOps
|
||||||
|
|
||||||
public fun FloatField.nd4j(shapeFirst: Int, vararg shapeRest: Int): FloatNd4jArrayField =
|
public fun FloatField.nd4j(shapeFirst: Int, vararg shapeRest: Int): FloatNd4jArrayField =
|
||||||
FloatNd4jArrayField(Shape(shapeFirst, * shapeRest))
|
FloatNd4jArrayField(ShapeND(shapeFirst, * shapeRest))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents [RingND] over [Nd4jArrayIntStructure].
|
* Represents [RingND] over [Nd4jArrayIntStructure].
|
||||||
@ -312,7 +313,7 @@ public open class IntNd4jArrayRingOps : Nd4jArrayRingOps<Int, IntRing> {
|
|||||||
|
|
||||||
public val IntRing.nd4j: IntNd4jArrayRingOps get() = IntNd4jArrayRingOps
|
public val IntRing.nd4j: IntNd4jArrayRingOps get() = IntNd4jArrayRingOps
|
||||||
|
|
||||||
public class IntNd4jArrayRing(override val shape: Shape) : IntNd4jArrayRingOps(), RingND<Int, IntRing>
|
public class IntNd4jArrayRing(override val shape: ShapeND) : IntNd4jArrayRingOps(), RingND<Int, IntRing>
|
||||||
|
|
||||||
public fun IntRing.nd4j(shapeFirst: Int, vararg shapeRest: Int): IntNd4jArrayRing =
|
public fun IntRing.nd4j(shapeFirst: Int, vararg shapeRest: Int): IntNd4jArrayRing =
|
||||||
IntNd4jArrayRing(Shape(shapeFirst, * shapeRest))
|
IntNd4jArrayRing(ShapeND(shapeFirst, * shapeRest))
|
@ -21,7 +21,7 @@ public sealed class Nd4jArrayStructure<T> : MutableStructureND<T> {
|
|||||||
*/
|
*/
|
||||||
public abstract val ndArray: INDArray
|
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<Pair<IntArray, T>>
|
internal abstract fun elementsIterator(): Iterator<Pair<IntArray, T>>
|
||||||
internal fun indicesIterator(): Iterator<IntArray> = ndArray.indicesIterator()
|
internal fun indicesIterator(): Iterator<IntArray> = ndArray.indicesIterator()
|
||||||
|
@ -37,7 +37,7 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
|
|||||||
*/
|
*/
|
||||||
public val StructureND<T>.ndArray: INDArray
|
public val StructureND<T>.ndArray: INDArray
|
||||||
|
|
||||||
override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): Nd4jArrayStructure<T>
|
override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): Nd4jArrayStructure<T>
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
override fun StructureND<T>.map(transform: A.(T) -> T): Nd4jArrayStructure<T> =
|
override fun StructureND<T>.map(transform: A.(T) -> T): Nd4jArrayStructure<T> =
|
||||||
@ -108,7 +108,7 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
|
|||||||
ndArray.max(keepDim, dim).wrap()
|
ndArray.max(keepDim, dim).wrap()
|
||||||
|
|
||||||
@OptIn(UnsafeKMathAPI::class)
|
@OptIn(UnsafeKMathAPI::class)
|
||||||
override fun Tensor<T>.view(shape: Shape): Nd4jArrayStructure<T> = ndArray.reshape(shape.asArray()).wrap()
|
override fun Tensor<T>.view(shape: ShapeND): Nd4jArrayStructure<T> = ndArray.reshape(shape.asArray()).wrap()
|
||||||
|
|
||||||
override fun Tensor<T>.viewAs(other: StructureND<T>): Nd4jArrayStructure<T> = view(other.shape)
|
override fun Tensor<T>.viewAs(other: StructureND<T>): Nd4jArrayStructure<T> = view(other.shape)
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra<Double, DoubleField> {
|
|||||||
override fun INDArray.wrap(): Nd4jArrayStructure<Double> = asDoubleStructure()
|
override fun INDArray.wrap(): Nd4jArrayStructure<Double> = asDoubleStructure()
|
||||||
|
|
||||||
@OptIn(UnsafeKMathAPI::class)
|
@OptIn(UnsafeKMathAPI::class)
|
||||||
override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): Nd4jArrayStructure<Double> {
|
override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): Nd4jArrayStructure<Double> {
|
||||||
val array: INDArray = Nd4j.zeros(*shape.asArray())
|
val array: INDArray = Nd4j.zeros(*shape.asArray())
|
||||||
val indices = ColumnStrides(shape)
|
val indices = ColumnStrides(shape)
|
||||||
indices.asSequence().forEach { index ->
|
indices.asSequence().forEach { index ->
|
||||||
@ -198,7 +198,7 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra<Double, DoubleField> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun StructureND<Double>.valueOrNull(): Double? =
|
override fun StructureND<Double>.valueOrNull(): Double? =
|
||||||
if (shape contentEquals Shape(1)) ndArray.getDouble(0) else null
|
if (shape contentEquals ShapeND(1)) ndArray.getDouble(0) else null
|
||||||
|
|
||||||
// TODO rewrite
|
// TODO rewrite
|
||||||
override fun diagonalEmbedding(
|
override fun diagonalEmbedding(
|
||||||
|
@ -14,7 +14,7 @@ import space.kscience.kmath.expressions.Symbol
|
|||||||
import space.kscience.kmath.misc.PerformancePitfall
|
import space.kscience.kmath.misc.PerformancePitfall
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.nd.ColumnStrides
|
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.nd.StructureND
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.PowerOperations
|
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(
|
public class DoubleTensorFlowAlgebra internal constructor(
|
||||||
graph: Graph,
|
graph: Graph,
|
||||||
@ -37,7 +37,7 @@ public class DoubleTensorFlowAlgebra internal constructor(
|
|||||||
override val elementAlgebra: DoubleField get() = DoubleField
|
override val elementAlgebra: DoubleField get() = DoubleField
|
||||||
|
|
||||||
override fun structureND(
|
override fun structureND(
|
||||||
shape: Shape,
|
shape: ShapeND,
|
||||||
initializer: DoubleField.(IntArray) -> Double,
|
initializer: DoubleField.(IntArray) -> Double,
|
||||||
): StructureND<Double> {
|
): StructureND<Double> {
|
||||||
val res = TFloat64.tensorOf(org.tensorflow.ndarray.Shape.of(*shape.toLongArray())) { array ->
|
val res = TFloat64.tensorOf(org.tensorflow.ndarray.Shape.of(*shape.toLongArray())) { array ->
|
||||||
|
@ -20,7 +20,7 @@ import org.tensorflow.types.family.TType
|
|||||||
import space.kscience.kmath.misc.PerformancePitfall
|
import space.kscience.kmath.misc.PerformancePitfall
|
||||||
import space.kscience.kmath.misc.UnsafeKMathAPI
|
import space.kscience.kmath.misc.UnsafeKMathAPI
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
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.StructureND
|
||||||
import space.kscience.kmath.nd.asArray
|
import space.kscience.kmath.nd.asArray
|
||||||
import space.kscience.kmath.nd.contentEquals
|
import space.kscience.kmath.nd.contentEquals
|
||||||
@ -41,12 +41,14 @@ public sealed interface TensorFlowTensor<T> : Tensor<T>
|
|||||||
*/
|
*/
|
||||||
@JvmInline
|
@JvmInline
|
||||||
public value class TensorFlowArray<T>(public val tensor: NdArray<T>) : Tensor<T> {
|
public value class TensorFlowArray<T>(public val tensor: NdArray<T>) : Tensor<T> {
|
||||||
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())
|
override fun get(index: IntArray): T = tensor.getObject(*index.toLongArray())
|
||||||
|
|
||||||
//TODO implement native element sequence
|
//TODO implement native element sequence
|
||||||
|
|
||||||
|
@PerformancePitfall
|
||||||
override fun set(index: IntArray, value: T) {
|
override fun set(index: IntArray, value: T) {
|
||||||
tensor.setObject(value, *index.toLongArray())
|
tensor.setObject(value, *index.toLongArray())
|
||||||
}
|
}
|
||||||
@ -65,7 +67,7 @@ public abstract class TensorFlowOutput<T, TT : TType>(
|
|||||||
public var output: Output<TT> = output
|
public var output: Output<TT> = output
|
||||||
internal set
|
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<T>
|
protected abstract fun org.tensorflow.Tensor.actualizeTensor(): NdArray<T>
|
||||||
|
|
||||||
@ -99,7 +101,7 @@ public abstract class TensorFlowAlgebra<T, TT : TNumber, A : Ring<T>> internal c
|
|||||||
|
|
||||||
protected abstract fun const(value: T): Constant<TT>
|
protected abstract fun const(value: T): Constant<TT>
|
||||||
|
|
||||||
override fun StructureND<T>.valueOrNull(): T? = if (shape contentEquals Shape(1))
|
override fun StructureND<T>.valueOrNull(): T? = if (shape contentEquals ShapeND(1))
|
||||||
get(intArrayOf(0)) else null
|
get(intArrayOf(0)) else null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -195,7 +197,7 @@ public abstract class TensorFlowAlgebra<T, TT : TNumber, A : Ring<T>> internal c
|
|||||||
ops.linalg.transpose(it, ops.constant(intArrayOf(i, j)))
|
ops.linalg.transpose(it, ops.constant(intArrayOf(i, j)))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun Tensor<T>.view(shape: Shape): Tensor<T> = operate {
|
override fun Tensor<T>.view(shape: ShapeND): Tensor<T> = operate {
|
||||||
@OptIn(UnsafeKMathAPI::class)
|
@OptIn(UnsafeKMathAPI::class)
|
||||||
ops.reshape(it, ops.constant(shape.asArray()))
|
ops.reshape(it, ops.constant(shape.asArray()))
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ package space.kscience.kmath.tensorflow
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
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.get
|
||||||
import space.kscience.kmath.nd.structureND
|
import space.kscience.kmath.nd.structureND
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
@ -32,8 +32,8 @@ class DoubleTensorFlowOps {
|
|||||||
fun dot(){
|
fun dot(){
|
||||||
val dim = 1000
|
val dim = 1000
|
||||||
|
|
||||||
val tensor1 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12224)
|
val tensor1 = DoubleTensorAlgebra.randomNormal(shape = ShapeND(dim, dim), 12224)
|
||||||
val tensor2 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12225)
|
val tensor2 = DoubleTensorAlgebra.randomNormal(shape = ShapeND(dim, dim), 12225)
|
||||||
|
|
||||||
DoubleField.produceWithTF {
|
DoubleField.produceWithTF {
|
||||||
tensor1 dot tensor2
|
tensor1 dot tensor2
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
package space.kscience.kmath.tensors.api
|
package space.kscience.kmath.tensors.api
|
||||||
|
|
||||||
import space.kscience.kmath.nd.RingOpsND
|
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.nd.StructureND
|
||||||
import space.kscience.kmath.operations.Ring
|
import space.kscience.kmath.operations.Ring
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ public interface TensorAlgebra<T, A : Ring<T>> : RingOpsND<T, A> {
|
|||||||
* @param shape the desired size
|
* @param shape the desired size
|
||||||
* @return tensor with new shape
|
* @return tensor with new shape
|
||||||
*/
|
*/
|
||||||
public fun Tensor<T>.view(shape: Shape): Tensor<T>
|
public fun Tensor<T>.view(shape: ShapeND): Tensor<T>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View this tensor as the same size as [other].
|
* View this tensor as the same size as [other].
|
||||||
|
@ -7,7 +7,7 @@ package space.kscience.kmath.tensors.core
|
|||||||
|
|
||||||
import space.kscience.kmath.misc.PerformancePitfall
|
import space.kscience.kmath.misc.PerformancePitfall
|
||||||
import space.kscience.kmath.nd.RowStrides
|
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.nd.Strides
|
||||||
import space.kscience.kmath.structures.MutableBuffer
|
import space.kscience.kmath.structures.MutableBuffer
|
||||||
import space.kscience.kmath.tensors.api.Tensor
|
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]
|
* Represents [Tensor] over a [MutableBuffer] intended to be used through [DoubleTensor] and [IntTensor]
|
||||||
*/
|
*/
|
||||||
public abstract class BufferedTensor<T>(
|
public abstract class BufferedTensor<T>(
|
||||||
override val shape: Shape,
|
override val shape: ShapeND,
|
||||||
) : Tensor<T> {
|
) : Tensor<T> {
|
||||||
|
|
||||||
public abstract val source: MutableBuffer<T>
|
public abstract val source: MutableBuffer<T>
|
||||||
|
@ -84,7 +84,7 @@ public inline fun OffsetDoubleBuffer.mapInPlace(operation: (Double) -> Double) {
|
|||||||
* [DoubleTensor] always uses row-based strides
|
* [DoubleTensor] always uses row-based strides
|
||||||
*/
|
*/
|
||||||
public class DoubleTensor(
|
public class DoubleTensor(
|
||||||
shape: Shape,
|
shape: ShapeND,
|
||||||
override val source: OffsetDoubleBuffer,
|
override val source: OffsetDoubleBuffer,
|
||||||
) : BufferedTensor<Double>(shape), MutableStructureNDOfDouble {
|
) : BufferedTensor<Double>(shape), MutableStructureNDOfDouble {
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ public class DoubleTensor(
|
|||||||
require(linearSize == source.size) { "Source buffer size must be equal tensor size" }
|
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)
|
@OptIn(PerformancePitfall::class)
|
||||||
@ -147,7 +147,7 @@ public value class DoubleTensor2D(public val tensor: DoubleTensor) : MutableStru
|
|||||||
override fun elements(): Sequence<Pair<IntArray, Double>> = tensor.elements()
|
override fun elements(): Sequence<Pair<IntArray, Double>> = tensor.elements()
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
override fun get(index: IntArray): Double = tensor[index]
|
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)
|
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
|
val n = shape.size
|
||||||
check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" }
|
check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" }
|
||||||
val matrixOffset = shape[n - 1] * shape[n - 2]
|
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
|
val size = matrixShape.linearSize
|
||||||
for (i in 0 until linearSize / matrixOffset) {
|
for (i in 0 until linearSize / matrixOffset) {
|
||||||
|
@ -92,7 +92,7 @@ public open class DoubleTensorAlgebra :
|
|||||||
|
|
||||||
override fun StructureND<Double>.valueOrNull(): Double? {
|
override fun StructureND<Double>.valueOrNull(): Double? {
|
||||||
val dt = asDoubleTensor()
|
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<Double>.value(): Double = valueOrNull()
|
override fun StructureND<Double>.value(): Double = valueOrNull()
|
||||||
@ -105,7 +105,7 @@ public open class DoubleTensorAlgebra :
|
|||||||
* @param array one-dimensional data array.
|
* @param array one-dimensional data array.
|
||||||
* @return tensor with the [shape] shape and [array] data.
|
* @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)
|
checkNotEmptyShape(shape)
|
||||||
checkEmptyDoubleBuffer(array)
|
checkEmptyDoubleBuffer(array)
|
||||||
checkBufferShapeConsistency(shape, array)
|
checkBufferShapeConsistency(shape, array)
|
||||||
@ -119,7 +119,7 @@ public open class DoubleTensorAlgebra :
|
|||||||
* @param initializer mapping tensor indices to values.
|
* @param initializer mapping tensor indices to values.
|
||||||
* @return tensor with the [shape] shape and data generated by the [initializer].
|
* @return tensor with the [shape] shape and data generated by the [initializer].
|
||||||
*/
|
*/
|
||||||
override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray(
|
override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray(
|
||||||
shape,
|
shape,
|
||||||
RowStrides(shape).asSequence().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray()
|
RowStrides(shape).asSequence().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray()
|
||||||
)
|
)
|
||||||
@ -127,7 +127,7 @@ public open class DoubleTensorAlgebra :
|
|||||||
override fun Tensor<Double>.getTensor(i: Int): DoubleTensor {
|
override fun Tensor<Double>.getTensor(i: Int): DoubleTensor {
|
||||||
val dt = asDoubleTensor()
|
val dt = asDoubleTensor()
|
||||||
val lastShape = shape.last(shape.size - 1)
|
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(
|
return DoubleTensor(
|
||||||
newShape,
|
newShape,
|
||||||
dt.source.view(newShape.linearSize * i, newShape.linearSize)
|
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.
|
* @param shape array of integers defining the shape of the output tensor.
|
||||||
* @return tensor with the [shape] shape and filled with [value].
|
* @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)
|
checkNotEmptyShape(shape)
|
||||||
val buffer = DoubleBuffer(shape.linearSize) { value }
|
val buffer = DoubleBuffer(shape.linearSize) { value }
|
||||||
return DoubleTensor(shape, buffer)
|
return DoubleTensor(shape, buffer)
|
||||||
@ -165,7 +165,7 @@ public open class DoubleTensorAlgebra :
|
|||||||
* @param shape array of integers defining the shape of the output tensor.
|
* @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.
|
* @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.
|
* 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.
|
* @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.
|
* @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.
|
* 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.
|
* @return a 2-D tensor with ones on the diagonal and zeros elsewhere.
|
||||||
*/
|
*/
|
||||||
public fun eye(n: Int): DoubleTensor {
|
public fun eye(n: Int): DoubleTensor {
|
||||||
val shape = Shape(n, n)
|
val shape = ShapeND(n, n)
|
||||||
val buffer = DoubleBuffer(n * n) { 0.0 }
|
val buffer = DoubleBuffer(n * n) { 0.0 }
|
||||||
val res = DoubleTensor(shape, buffer)
|
val res = DoubleTensor(shape, buffer)
|
||||||
for (i in 0 until n) {
|
for (i in 0 until n) {
|
||||||
@ -306,7 +306,7 @@ public open class DoubleTensorAlgebra :
|
|||||||
// return resTensor
|
// return resTensor
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun Tensor<Double>.view(shape: Shape): DoubleTensor {
|
override fun Tensor<Double>.view(shape: ShapeND): DoubleTensor {
|
||||||
checkView(asDoubleTensor(), shape)
|
checkView(asDoubleTensor(), shape)
|
||||||
return DoubleTensor(shape, asDoubleTensor().source)
|
return DoubleTensor(shape, asDoubleTensor().source)
|
||||||
}
|
}
|
||||||
@ -346,7 +346,7 @@ public open class DoubleTensorAlgebra :
|
|||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public infix fun StructureND<Double>.matmul(other: StructureND<Double>): DoubleTensor {
|
public infix fun StructureND<Double>.matmul(other: StructureND<Double>): DoubleTensor {
|
||||||
if (shape.size == 1 && other.shape.size == 1) {
|
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
|
var penultimateDim = false
|
||||||
@ -358,7 +358,7 @@ public open class DoubleTensorAlgebra :
|
|||||||
|
|
||||||
if (shape.size == 1) {
|
if (shape.size == 1) {
|
||||||
penultimateDim = true
|
penultimateDim = true
|
||||||
newThis = newThis.view(Shape(1) + shape)
|
newThis = newThis.view(ShapeND(1) + shape)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other.shape.size == 1) {
|
if (other.shape.size == 1) {
|
||||||
@ -396,7 +396,7 @@ public open class DoubleTensorAlgebra :
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
return if (penultimateDim) {
|
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) {
|
} else if (lastDim) {
|
||||||
resTensor.view(resTensor.shape.first(resTensor.shape.size - 1))
|
resTensor.view(resTensor.shape.first(resTensor.shape.size - 1))
|
||||||
} else {
|
} else {
|
||||||
@ -506,7 +506,7 @@ public open class DoubleTensorAlgebra :
|
|||||||
* @return tensor of a given shape filled with numbers from the normal distribution
|
* @return tensor of a given shape filled with numbers from the normal distribution
|
||||||
* with `0.0` mean and `1.0` standard deviation.
|
* 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))
|
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" }
|
check(tensors.isNotEmpty()) { "List must have at least 1 element" }
|
||||||
val shape = tensors[0].shape
|
val shape = tensors[0].shape
|
||||||
check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" }
|
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<Double> = tensors.flatMap {
|
// val resBuffer: List<Double> = tensors.flatMap {
|
||||||
// it.asDoubleTensor().source.array.drop(it.asDoubleTensor().bufferStart)
|
// it.asDoubleTensor().source.array.drop(it.asDoubleTensor().bufferStart)
|
||||||
// .take(it.asDoubleTensor().linearSize)
|
// .take(it.asDoubleTensor().linearSize)
|
||||||
@ -685,9 +685,9 @@ public open class DoubleTensorAlgebra :
|
|||||||
check(tensors.isNotEmpty()) { "List must have at least 1 element" }
|
check(tensors.isNotEmpty()) { "List must have at least 1 element" }
|
||||||
val n = tensors.size
|
val n = tensors.size
|
||||||
val m = tensors[0].shape[0]
|
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(
|
val resTensor = DoubleTensor(
|
||||||
Shape(n, n),
|
ShapeND(n, n),
|
||||||
DoubleBuffer(n * n) { 0.0 }
|
DoubleBuffer(n * n) { 0.0 }
|
||||||
)
|
)
|
||||||
for (i in 0 until n) {
|
for (i in 0 until n) {
|
||||||
@ -875,9 +875,9 @@ public open class DoubleTensorAlgebra :
|
|||||||
val size = dimension
|
val size = dimension
|
||||||
val commonShape = shape.slice(0 until size - 2)
|
val commonShape = shape.slice(0 until size - 2)
|
||||||
val (n, m) = shape.slice(size - 2 until size)
|
val (n, m) = shape.slice(size - 2 until size)
|
||||||
val uTensor = zeros(commonShape + Shape(min(n, m), n))
|
val uTensor = zeros(commonShape + ShapeND(min(n, m), n))
|
||||||
val sTensor = zeros(commonShape + Shape(min(n, m)))
|
val sTensor = zeros(commonShape + ShapeND(min(n, m)))
|
||||||
val vTensor = zeros(commonShape + Shape(min(n, m), m))
|
val vTensor = zeros(commonShape + ShapeND(min(n, m), m))
|
||||||
|
|
||||||
val matrices = asDoubleTensor().matrices
|
val matrices = asDoubleTensor().matrices
|
||||||
val uTensors = uTensor.matrices
|
val uTensors = uTensor.matrices
|
||||||
@ -988,7 +988,7 @@ public open class DoubleTensorAlgebra :
|
|||||||
|
|
||||||
val n = shape.size
|
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)
|
set(n - 2, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
package space.kscience.kmath.tensors.core
|
package space.kscience.kmath.tensors.core
|
||||||
|
|
||||||
import space.kscience.kmath.misc.PerformancePitfall
|
import space.kscience.kmath.misc.PerformancePitfall
|
||||||
import space.kscience.kmath.nd.Shape
|
import space.kscience.kmath.nd.ShapeND
|
||||||
import space.kscience.kmath.structures.*
|
import space.kscience.kmath.structures.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,7 +75,7 @@ public inline fun OffsetIntBuffer.mapInPlace(operation: (Int) -> Int) {
|
|||||||
* Default [BufferedTensor] implementation for [Int] values
|
* Default [BufferedTensor] implementation for [Int] values
|
||||||
*/
|
*/
|
||||||
public class IntTensor(
|
public class IntTensor(
|
||||||
shape: Shape,
|
shape: ShapeND,
|
||||||
override val source: OffsetIntBuffer,
|
override val source: OffsetIntBuffer,
|
||||||
) : BufferedTensor<Int>(shape) {
|
) : BufferedTensor<Int>(shape) {
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ public class IntTensor(
|
|||||||
require(linearSize == source.size) { "Source buffer size must be equal tensor size" }
|
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)
|
@OptIn(PerformancePitfall::class)
|
||||||
override fun get(index: IntArray): Int = this.source[indices.offset(index)]
|
override fun get(index: IntArray): Int = this.source[indices.offset(index)]
|
||||||
|
@ -89,7 +89,7 @@ public open class IntTensorAlgebra : TensorAlgebra<Int, IntRing> {
|
|||||||
|
|
||||||
override fun StructureND<Int>.valueOrNull(): Int? {
|
override fun StructureND<Int>.valueOrNull(): Int? {
|
||||||
val dt = asIntTensor()
|
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<Int>.value(): Int = valueOrNull()
|
override fun StructureND<Int>.value(): Int = valueOrNull()
|
||||||
@ -102,7 +102,7 @@ public open class IntTensorAlgebra : TensorAlgebra<Int, IntRing> {
|
|||||||
* @param array one-dimensional data array.
|
* @param array one-dimensional data array.
|
||||||
* @return tensor with the [shape] shape and [array] data.
|
* @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)
|
checkNotEmptyShape(shape)
|
||||||
check(array.isNotEmpty()) { "Illegal empty buffer provided" }
|
check(array.isNotEmpty()) { "Illegal empty buffer provided" }
|
||||||
check(array.size == shape.linearSize) {
|
check(array.size == shape.linearSize) {
|
||||||
@ -118,7 +118,7 @@ public open class IntTensorAlgebra : TensorAlgebra<Int, IntRing> {
|
|||||||
* @param initializer mapping tensor indices to values.
|
* @param initializer mapping tensor indices to values.
|
||||||
* @return tensor with the [shape] shape and data generated by the [initializer].
|
* @return tensor with the [shape] shape and data generated by the [initializer].
|
||||||
*/
|
*/
|
||||||
override fun structureND(shape: Shape, initializer: IntRing.(IntArray) -> Int): IntTensor = fromArray(
|
override fun structureND(shape: ShapeND, initializer: IntRing.(IntArray) -> Int): IntTensor = fromArray(
|
||||||
shape,
|
shape,
|
||||||
RowStrides(shape).asSequence().map { IntRing.initializer(it) }.toMutableList().toIntArray()
|
RowStrides(shape).asSequence().map { IntRing.initializer(it) }.toMutableList().toIntArray()
|
||||||
)
|
)
|
||||||
@ -126,7 +126,7 @@ public open class IntTensorAlgebra : TensorAlgebra<Int, IntRing> {
|
|||||||
override fun Tensor<Int>.getTensor(i: Int): IntTensor {
|
override fun Tensor<Int>.getTensor(i: Int): IntTensor {
|
||||||
val dt = asIntTensor()
|
val dt = asIntTensor()
|
||||||
val lastShape = shape.last(shape.size - 1)
|
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))
|
return IntTensor(newShape, dt.source.view(newShape.linearSize * i))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ public open class IntTensorAlgebra : TensorAlgebra<Int, IntRing> {
|
|||||||
* @param shape array of integers defining the shape of the output tensor.
|
* @param shape array of integers defining the shape of the output tensor.
|
||||||
* @return tensor with the [shape] shape and filled with [value].
|
* @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)
|
checkNotEmptyShape(shape)
|
||||||
val buffer = IntBuffer(shape.linearSize) { value }
|
val buffer = IntBuffer(shape.linearSize) { value }
|
||||||
return IntTensor(shape, buffer)
|
return IntTensor(shape, buffer)
|
||||||
@ -161,7 +161,7 @@ public open class IntTensorAlgebra : TensorAlgebra<Int, IntRing> {
|
|||||||
* @param shape array of integers defining the shape of the output tensor.
|
* @param shape array of integers defining the shape of the output tensor.
|
||||||
* @return tensor filled with the scalar value `0`, with the [shape] shape.
|
* @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.
|
* 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<Int, IntRing> {
|
|||||||
* @param shape array of integers defining the shape of the output tensor.
|
* @param shape array of integers defining the shape of the output tensor.
|
||||||
* @return tensor filled with the scalar value `1`, with the [shape] shape.
|
* @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.
|
* 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<Int, IntRing> {
|
|||||||
* @return a 2-D tensor with ones on the diagonal and zeros elsewhere.
|
* @return a 2-D tensor with ones on the diagonal and zeros elsewhere.
|
||||||
*/
|
*/
|
||||||
public fun eye(n: Int): IntTensor {
|
public fun eye(n: Int): IntTensor {
|
||||||
val shape = Shape(n, n)
|
val shape = ShapeND(n, n)
|
||||||
val buffer = IntBuffer(n * n) { 0 }
|
val buffer = IntBuffer(n * n) { 0 }
|
||||||
val res = IntTensor(shape, buffer)
|
val res = IntTensor(shape, buffer)
|
||||||
for (i in 0 until n) {
|
for (i in 0 until n) {
|
||||||
@ -287,7 +287,7 @@ public open class IntTensorAlgebra : TensorAlgebra<Int, IntRing> {
|
|||||||
// return resTensor
|
// return resTensor
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun Tensor<Int>.view(shape: Shape): IntTensor {
|
override fun Tensor<Int>.view(shape: ShapeND): IntTensor {
|
||||||
checkView(asIntTensor(), shape)
|
checkView(asIntTensor(), shape)
|
||||||
return IntTensor(shape, asIntTensor().source)
|
return IntTensor(shape, asIntTensor().source)
|
||||||
}
|
}
|
||||||
@ -388,7 +388,7 @@ public open class IntTensorAlgebra : TensorAlgebra<Int, IntRing> {
|
|||||||
check(tensors.isNotEmpty()) { "List must have at least 1 element" }
|
check(tensors.isNotEmpty()) { "List must have at least 1 element" }
|
||||||
val shape = tensors[0].shape
|
val shape = tensors[0].shape
|
||||||
check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" }
|
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<Int> = tensors.flatMap {
|
// val resBuffer: List<Int> = tensors.flatMap {
|
||||||
// it.asIntTensor().source.array.drop(it.asIntTensor().bufferStart)
|
// it.asIntTensor().source.array.drop(it.asIntTensor().bufferStart)
|
||||||
// .take(it.asIntTensor().linearSize)
|
// .take(it.asIntTensor().linearSize)
|
||||||
|
@ -32,7 +32,7 @@ internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTenso
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun broadcastShapes(shapes: List<Shape>): Shape {
|
internal fun broadcastShapes(shapes: List<ShapeND>): ShapeND {
|
||||||
var totalDim = 0
|
var totalDim = 0
|
||||||
for (shape in shapes) {
|
for (shape in shapes) {
|
||||||
totalDim = max(totalDim, shape.size)
|
totalDim = max(totalDim, shape.size)
|
||||||
@ -57,10 +57,10 @@ internal fun broadcastShapes(shapes: List<Shape>): 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) {
|
require(tensor.shape.size <= newShape.size) {
|
||||||
"Tensor is not compatible with the new shape"
|
"Tensor is not compatible with the new shape"
|
||||||
}
|
}
|
||||||
@ -120,7 +120,7 @@ internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List<DoubleTen
|
|||||||
var curMultiIndex = tensor.shape.slice(0..tensor.shape.size - 3).asArray()
|
var curMultiIndex = tensor.shape.slice(0..tensor.shape.size - 3).asArray()
|
||||||
curMultiIndex = IntArray(totalMultiIndex.size - curMultiIndex.size) { 1 } + curMultiIndex
|
curMultiIndex = IntArray(totalMultiIndex.size - curMultiIndex.size) { 1 } + curMultiIndex
|
||||||
|
|
||||||
val newTensor = DoubleTensor(Shape(curMultiIndex) + matrixShape, tensor.source)
|
val newTensor = DoubleTensor(ShapeND(curMultiIndex) + matrixShape, tensor.source)
|
||||||
|
|
||||||
for (i in curMultiIndex.indices) {
|
for (i in curMultiIndex.indices) {
|
||||||
if (curMultiIndex[i] != 1) {
|
if (curMultiIndex[i] != 1) {
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.tensors.core.internal
|
package space.kscience.kmath.tensors.core.internal
|
||||||
|
|
||||||
import space.kscience.kmath.nd.Shape
|
import space.kscience.kmath.nd.ShapeND
|
||||||
import space.kscience.kmath.nd.StructureND
|
import space.kscience.kmath.nd.StructureND
|
||||||
import space.kscience.kmath.nd.contentEquals
|
import space.kscience.kmath.nd.contentEquals
|
||||||
import space.kscience.kmath.nd.linearSize
|
import space.kscience.kmath.nd.linearSize
|
||||||
@ -15,7 +15,7 @@ import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
|
|||||||
import space.kscience.kmath.tensors.core.asDoubleTensor
|
import space.kscience.kmath.tensors.core.asDoubleTensor
|
||||||
|
|
||||||
|
|
||||||
internal fun checkNotEmptyShape(shape: Shape) =
|
internal fun checkNotEmptyShape(shape: ShapeND) =
|
||||||
check(shape.size > 0) {
|
check(shape.size > 0) {
|
||||||
"Illegal empty shape provided"
|
"Illegal empty shape provided"
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ internal fun checkEmptyDoubleBuffer(buffer: DoubleArray) = check(buffer.isNotEmp
|
|||||||
"Illegal empty buffer provided"
|
"Illegal empty buffer provided"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun checkBufferShapeConsistency(shape: Shape, buffer: DoubleArray) =
|
internal fun checkBufferShapeConsistency(shape: ShapeND, buffer: DoubleArray) =
|
||||||
check(buffer.size == shape.linearSize) {
|
check(buffer.size == shape.linearSize) {
|
||||||
"Inconsistent shape ${shape} for buffer of size ${buffer.size} provided"
|
"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"
|
"Cannot transpose $i to $j for a tensor of dim $dim"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun <T> checkView(a: Tensor<T>, shape: Shape) =
|
internal fun <T> checkView(a: Tensor<T>, shape: ShapeND) =
|
||||||
check(a.shape.linearSize == shape.linearSize)
|
check(a.shape.linearSize == shape.linearSize)
|
||||||
|
|
||||||
internal fun checkSquareMatrix(shape: Shape) {
|
internal fun checkSquareMatrix(shape: ShapeND) {
|
||||||
val n = shape.size
|
val n = shape.size
|
||||||
check(n >= 2) {
|
check(n >= 2) {
|
||||||
"Expected tensor with 2 or more dimensions, got size $n instead"
|
"Expected tensor with 2 or more dimensions, got size $n instead"
|
||||||
|
@ -156,7 +156,7 @@ internal val DoubleTensor.vectors: List<DoubleTensor>
|
|||||||
get() {
|
get() {
|
||||||
val n = shape.size
|
val n = shape.size
|
||||||
val vectorOffset = shape[n - 1]
|
val vectorOffset = shape[n - 1]
|
||||||
val vectorShape = Shape(shape.last())
|
val vectorShape = ShapeND(shape.last())
|
||||||
|
|
||||||
return List(linearSize / vectorOffset) { index ->
|
return List(linearSize / vectorOffset) { index ->
|
||||||
val offset = index * vectorOffset
|
val offset = index * vectorOffset
|
||||||
@ -173,7 +173,7 @@ internal val DoubleTensor.matrices: List<DoubleTensor>
|
|||||||
val n = shape.size
|
val n = shape.size
|
||||||
check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" }
|
check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" }
|
||||||
val matrixOffset = shape[n - 1] * shape[n - 2]
|
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
|
val size = matrixShape.linearSize
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.tensors.core.internal
|
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.first
|
||||||
import space.kscience.kmath.nd.last
|
import space.kscience.kmath.nd.last
|
||||||
import space.kscience.kmath.operations.asSequence
|
import space.kscience.kmath.operations.asSequence
|
||||||
@ -55,7 +55,7 @@ internal val IntTensor.matrices: VirtualBuffer<IntTensor>
|
|||||||
val n = shape.size
|
val n = shape.size
|
||||||
check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" }
|
check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" }
|
||||||
val matrixOffset = shape[n - 1] * shape[n - 2]
|
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 ->
|
return VirtualBuffer(linearSize / matrixOffset) { index ->
|
||||||
val offset = index * matrixOffset
|
val offset = index * matrixOffset
|
||||||
|
@ -95,7 +95,7 @@ internal fun <T> StructureND<T>.setUpPivots(): IntTensor {
|
|||||||
pivotsShape[n - 2] = m + 1
|
pivotsShape[n - 2] = m + 1
|
||||||
|
|
||||||
return IntTensor(
|
return IntTensor(
|
||||||
Shape(pivotsShape),
|
ShapeND(pivotsShape),
|
||||||
IntBuffer(pivotsShape.reduce(Int::times)) { 0 }
|
IntBuffer(pivotsShape.reduce(Int::times)) { 0 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -240,10 +240,10 @@ internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10)
|
|||||||
val b: DoubleTensor
|
val b: DoubleTensor
|
||||||
if (n > m) {
|
if (n > m) {
|
||||||
b = a.transposed(0, 1).dot(a)
|
b = a.transposed(0, 1).dot(a)
|
||||||
v = DoubleTensor(Shape(m), DoubleBuffer.randomUnitVector(m, 0))
|
v = DoubleTensor(ShapeND(m), DoubleBuffer.randomUnitVector(m, 0))
|
||||||
} else {
|
} else {
|
||||||
b = a.dot(a.transposed(0, 1))
|
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
|
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()
|
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 v: DoubleTensor
|
||||||
var u: DoubleTensor
|
var u: DoubleTensor
|
||||||
|
@ -8,15 +8,15 @@
|
|||||||
package space.kscience.kmath.tensors.core
|
package space.kscience.kmath.tensors.core
|
||||||
|
|
||||||
import space.kscience.kmath.misc.PerformancePitfall
|
import space.kscience.kmath.misc.PerformancePitfall
|
||||||
import space.kscience.kmath.nd.Shape
|
import space.kscience.kmath.nd.ShapeND
|
||||||
import kotlin.jvm.JvmName
|
import kotlin.jvm.JvmName
|
||||||
|
|
||||||
@JvmName("varArgOne")
|
@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")
|
@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)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.tensors.core
|
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.contentEquals
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.tensors.core.internal.broadcastOuterTensors
|
import space.kscience.kmath.tensors.core.internal.broadcastOuterTensors
|
||||||
@ -21,38 +21,38 @@ internal class TestBroadcasting {
|
|||||||
fun testBroadcastShapes() = DoubleTensorAlgebra {
|
fun testBroadcastShapes() = DoubleTensorAlgebra {
|
||||||
assertTrue(
|
assertTrue(
|
||||||
broadcastShapes(
|
broadcastShapes(
|
||||||
listOf(Shape(2, 3), Shape(1, 3), Shape(1, 1, 1))
|
listOf(ShapeND(2, 3), ShapeND(1, 3), ShapeND(1, 1, 1))
|
||||||
) contentEquals Shape(1, 2, 3)
|
) contentEquals ShapeND(1, 2, 3)
|
||||||
)
|
)
|
||||||
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
broadcastShapes(
|
broadcastShapes(
|
||||||
listOf(Shape(6, 7), Shape(5, 6, 1), Shape(7), Shape(5, 1, 7))
|
listOf(ShapeND(6, 7), ShapeND(5, 6, 1), ShapeND(7), ShapeND(5, 1, 7))
|
||||||
) contentEquals Shape(5, 6, 7)
|
) contentEquals ShapeND(5, 6, 7)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBroadcastTo() = DoubleTensorAlgebra {
|
fun testBroadcastTo() = DoubleTensorAlgebra {
|
||||||
val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor1 = fromArray(ShapeND(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 tensor2 = fromArray(ShapeND(1, 3), doubleArrayOf(10.0, 20.0, 30.0))
|
||||||
|
|
||||||
val res = broadcastTo(tensor2, tensor1.shape)
|
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))
|
assertTrue(res.source contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBroadcastTensors() = DoubleTensorAlgebra {
|
fun testBroadcastTensors() = DoubleTensorAlgebra {
|
||||||
val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor1 = fromArray(ShapeND(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 tensor2 = fromArray(ShapeND(1, 3), doubleArrayOf(10.0, 20.0, 30.0))
|
||||||
val tensor3 = fromArray(Shape(1, 1, 1), doubleArrayOf(500.0))
|
val tensor3 = fromArray(ShapeND(1, 1, 1), doubleArrayOf(500.0))
|
||||||
|
|
||||||
val res = broadcastTensors(tensor1, tensor2, tensor3)
|
val res = broadcastTensors(tensor1, tensor2, tensor3)
|
||||||
|
|
||||||
assertTrue(res[0].shape contentEquals Shape(1, 2, 3))
|
assertTrue(res[0].shape contentEquals ShapeND(1, 2, 3))
|
||||||
assertTrue(res[1].shape contentEquals Shape(1, 2, 3))
|
assertTrue(res[1].shape contentEquals ShapeND(1, 2, 3))
|
||||||
assertTrue(res[2].shape contentEquals Shape(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[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))
|
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
|
@Test
|
||||||
fun testBroadcastOuterTensors() = DoubleTensorAlgebra {
|
fun testBroadcastOuterTensors() = DoubleTensorAlgebra {
|
||||||
val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor1 = fromArray(ShapeND(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 tensor2 = fromArray(ShapeND(1, 3), doubleArrayOf(10.0, 20.0, 30.0))
|
||||||
val tensor3 = fromArray(Shape(1, 1, 1), doubleArrayOf(500.0))
|
val tensor3 = fromArray(ShapeND(1, 1, 1), doubleArrayOf(500.0))
|
||||||
|
|
||||||
val res = broadcastOuterTensors(tensor1, tensor2, tensor3)
|
val res = broadcastOuterTensors(tensor1, tensor2, tensor3)
|
||||||
|
|
||||||
assertTrue(res[0].shape contentEquals Shape(1, 2, 3))
|
assertTrue(res[0].shape contentEquals ShapeND(1, 2, 3))
|
||||||
assertTrue(res[1].shape contentEquals Shape(1, 1, 3))
|
assertTrue(res[1].shape contentEquals ShapeND(1, 1, 3))
|
||||||
assertTrue(res[2].shape contentEquals Shape(1, 1, 1))
|
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[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))
|
assertTrue(res[1].source contentEquals doubleArrayOf(10.0, 20.0, 30.0))
|
||||||
@ -78,37 +78,37 @@ internal class TestBroadcasting {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBroadcastOuterTensorsShapes() = DoubleTensorAlgebra {
|
fun testBroadcastOuterTensorsShapes() = DoubleTensorAlgebra {
|
||||||
val tensor1 = fromArray(Shape(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) { 0.0 })
|
val tensor1 = fromArray(ShapeND(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 tensor2 = fromArray(ShapeND(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 tensor3 = fromArray(ShapeND(1, 1), doubleArrayOf(500.0))
|
||||||
|
|
||||||
val res = broadcastOuterTensors(tensor1, tensor2, tensor3)
|
val res = broadcastOuterTensors(tensor1, tensor2, tensor3)
|
||||||
|
|
||||||
assertTrue(res[0].shape contentEquals Shape(4, 2, 5, 3, 2, 3))
|
assertTrue(res[0].shape contentEquals ShapeND(4, 2, 5, 3, 2, 3))
|
||||||
assertTrue(res[1].shape contentEquals Shape(4, 2, 5, 3, 3, 3))
|
assertTrue(res[1].shape contentEquals ShapeND(4, 2, 5, 3, 3, 3))
|
||||||
assertTrue(res[2].shape contentEquals Shape(4, 2, 5, 3, 1, 1))
|
assertTrue(res[2].shape contentEquals ShapeND(4, 2, 5, 3, 1, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMinusTensor() = BroadcastDoubleTensorAlgebra.invoke {
|
fun testMinusTensor() = BroadcastDoubleTensorAlgebra.invoke {
|
||||||
val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor1 = fromArray(ShapeND(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 tensor2 = fromArray(ShapeND(1, 3), doubleArrayOf(10.0, 20.0, 30.0))
|
||||||
val tensor3 = fromArray(Shape(1, 1, 1), doubleArrayOf(500.0))
|
val tensor3 = fromArray(ShapeND(1, 1, 1), doubleArrayOf(500.0))
|
||||||
|
|
||||||
val tensor21 = tensor2 - tensor1
|
val tensor21 = tensor2 - tensor1
|
||||||
val tensor31 = tensor3 - tensor1
|
val tensor31 = tensor3 - tensor1
|
||||||
val tensor32 = tensor3 - tensor2
|
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(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(
|
assertTrue(
|
||||||
tensor31.source
|
tensor31.source
|
||||||
contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0)
|
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))
|
assertTrue(tensor32.source contentEquals doubleArrayOf(490.0, 480.0, 470.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.tensors.core
|
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.operations.invoke
|
||||||
import space.kscience.kmath.structures.asBuffer
|
import space.kscience.kmath.structures.asBuffer
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
@ -14,7 +14,7 @@ import kotlin.test.assertTrue
|
|||||||
|
|
||||||
internal class TestDoubleAnalyticTensorAlgebra {
|
internal class TestDoubleAnalyticTensorAlgebra {
|
||||||
|
|
||||||
val shape = Shape(2, 1, 3, 2)
|
val shape = ShapeND(2, 1, 3, 2)
|
||||||
val buffer = doubleArrayOf(
|
val buffer = doubleArrayOf(
|
||||||
27.1, 20.0, 19.84,
|
27.1, 20.0, 19.84,
|
||||||
23.123, 3.0, 2.0,
|
23.123, 3.0, 2.0,
|
||||||
@ -103,7 +103,7 @@ internal class TestDoubleAnalyticTensorAlgebra {
|
|||||||
assertTrue { tensor.floor() eq expectedTensor(::floor) }
|
assertTrue { tensor.floor() eq expectedTensor(::floor) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val shape2 = Shape(2, 2)
|
val shape2 = ShapeND(2, 2)
|
||||||
val buffer2 = doubleArrayOf(
|
val buffer2 = doubleArrayOf(
|
||||||
1.0, 2.0,
|
1.0, 2.0,
|
||||||
-3.0, 4.0
|
-3.0, 4.0
|
||||||
@ -115,13 +115,13 @@ internal class TestDoubleAnalyticTensorAlgebra {
|
|||||||
assertTrue { tensor2.min() == -3.0 }
|
assertTrue { tensor2.min() == -3.0 }
|
||||||
assertTrue {
|
assertTrue {
|
||||||
tensor2.min(0, true) eq fromArray(
|
tensor2.min(0, true) eq fromArray(
|
||||||
Shape(1, 2),
|
ShapeND(1, 2),
|
||||||
doubleArrayOf(-3.0, 2.0)
|
doubleArrayOf(-3.0, 2.0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
assertTrue {
|
assertTrue {
|
||||||
tensor2.min(1, false) eq fromArray(
|
tensor2.min(1, false) eq fromArray(
|
||||||
Shape(2),
|
ShapeND(2),
|
||||||
doubleArrayOf(1.0, -3.0)
|
doubleArrayOf(1.0, -3.0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -132,13 +132,13 @@ internal class TestDoubleAnalyticTensorAlgebra {
|
|||||||
assertTrue { tensor2.max() == 4.0 }
|
assertTrue { tensor2.max() == 4.0 }
|
||||||
assertTrue {
|
assertTrue {
|
||||||
tensor2.max(0, true) eq fromArray(
|
tensor2.max(0, true) eq fromArray(
|
||||||
Shape(1, 2),
|
ShapeND(1, 2),
|
||||||
doubleArrayOf(1.0, 4.0)
|
doubleArrayOf(1.0, 4.0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
assertTrue {
|
assertTrue {
|
||||||
tensor2.max(1, false) eq fromArray(
|
tensor2.max(1, false) eq fromArray(
|
||||||
Shape(2),
|
ShapeND(2),
|
||||||
doubleArrayOf(2.0, 4.0)
|
doubleArrayOf(2.0, 4.0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -149,13 +149,13 @@ internal class TestDoubleAnalyticTensorAlgebra {
|
|||||||
assertTrue { tensor2.sum() == 4.0 }
|
assertTrue { tensor2.sum() == 4.0 }
|
||||||
assertTrue {
|
assertTrue {
|
||||||
tensor2.sum(0, true) eq fromArray(
|
tensor2.sum(0, true) eq fromArray(
|
||||||
Shape(1, 2),
|
ShapeND(1, 2),
|
||||||
doubleArrayOf(-2.0, 6.0)
|
doubleArrayOf(-2.0, 6.0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
assertTrue {
|
assertTrue {
|
||||||
tensor2.sum(1, false) eq fromArray(
|
tensor2.sum(1, false) eq fromArray(
|
||||||
Shape(2),
|
ShapeND(2),
|
||||||
doubleArrayOf(3.0, 1.0)
|
doubleArrayOf(3.0, 1.0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -166,13 +166,13 @@ internal class TestDoubleAnalyticTensorAlgebra {
|
|||||||
assertTrue { tensor2.mean() == 1.0 }
|
assertTrue { tensor2.mean() == 1.0 }
|
||||||
assertTrue {
|
assertTrue {
|
||||||
tensor2.mean(0, true) eq fromArray(
|
tensor2.mean(0, true) eq fromArray(
|
||||||
Shape(1, 2),
|
ShapeND(1, 2),
|
||||||
doubleArrayOf(-1.0, 3.0)
|
doubleArrayOf(-1.0, 3.0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
assertTrue {
|
assertTrue {
|
||||||
tensor2.mean(1, false) eq fromArray(
|
tensor2.mean(1, false) eq fromArray(
|
||||||
Shape(2),
|
ShapeND(2),
|
||||||
doubleArrayOf(1.5, 0.5)
|
doubleArrayOf(1.5, 0.5)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.tensors.core
|
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.contentEquals
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.tensors.core.internal.svd1d
|
import space.kscience.kmath.tensors.core.internal.svd1d
|
||||||
@ -19,7 +19,7 @@ internal class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
@Test
|
@Test
|
||||||
fun testDetLU() = DoubleTensorAlgebra {
|
fun testDetLU() = DoubleTensorAlgebra {
|
||||||
val tensor = fromArray(
|
val tensor = fromArray(
|
||||||
Shape(2, 2, 2),
|
ShapeND(2, 2, 2),
|
||||||
doubleArrayOf(
|
doubleArrayOf(
|
||||||
1.0, 3.0,
|
1.0, 3.0,
|
||||||
1.0, 2.0,
|
1.0, 2.0,
|
||||||
@ -29,7 +29,7 @@ internal class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val expectedTensor = fromArray(
|
val expectedTensor = fromArray(
|
||||||
Shape(2, 1),
|
ShapeND(2, 1),
|
||||||
doubleArrayOf(
|
doubleArrayOf(
|
||||||
-1.0,
|
-1.0,
|
||||||
-7.0
|
-7.0
|
||||||
@ -45,7 +45,7 @@ internal class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
fun testDet() = DoubleTensorAlgebra {
|
fun testDet() = DoubleTensorAlgebra {
|
||||||
val expectedValue = 0.019827417
|
val expectedValue = 0.019827417
|
||||||
val m = fromArray(
|
val m = fromArray(
|
||||||
Shape(3, 3), doubleArrayOf(
|
ShapeND(3, 3), doubleArrayOf(
|
||||||
2.1843, 1.4391, -0.4845,
|
2.1843, 1.4391, -0.4845,
|
||||||
1.4391, 1.7772, 0.4055,
|
1.4391, 1.7772, 0.4055,
|
||||||
-0.4845, 0.4055, 0.7519
|
-0.4845, 0.4055, 0.7519
|
||||||
@ -59,7 +59,7 @@ internal class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
fun testDetSingle() = DoubleTensorAlgebra {
|
fun testDetSingle() = DoubleTensorAlgebra {
|
||||||
val expectedValue = 48.151623
|
val expectedValue = 48.151623
|
||||||
val m = fromArray(
|
val m = fromArray(
|
||||||
Shape(1, 1), doubleArrayOf(
|
ShapeND(1, 1), doubleArrayOf(
|
||||||
expectedValue
|
expectedValue
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -70,7 +70,7 @@ internal class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
@Test
|
@Test
|
||||||
fun testInvLU() = DoubleTensorAlgebra {
|
fun testInvLU() = DoubleTensorAlgebra {
|
||||||
val tensor = fromArray(
|
val tensor = fromArray(
|
||||||
Shape(2, 2, 2),
|
ShapeND(2, 2, 2),
|
||||||
doubleArrayOf(
|
doubleArrayOf(
|
||||||
1.0, 0.0,
|
1.0, 0.0,
|
||||||
0.0, 2.0,
|
0.0, 2.0,
|
||||||
@ -80,7 +80,7 @@ internal class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val expectedTensor = fromArray(
|
val expectedTensor = fromArray(
|
||||||
Shape(2, 2, 2), doubleArrayOf(
|
ShapeND(2, 2, 2), doubleArrayOf(
|
||||||
1.0, 0.0,
|
1.0, 0.0,
|
||||||
0.0, 0.5,
|
0.0, 0.5,
|
||||||
0.0, 1.0,
|
0.0, 1.0,
|
||||||
@ -94,14 +94,14 @@ internal class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testScalarProduct() = DoubleTensorAlgebra {
|
fun testScalarProduct() = DoubleTensorAlgebra {
|
||||||
val a = fromArray(Shape(3), doubleArrayOf(1.8, 2.5, 6.8))
|
val a = fromArray(ShapeND(3), doubleArrayOf(1.8, 2.5, 6.8))
|
||||||
val b = fromArray(Shape(3), doubleArrayOf(5.5, 2.6, 6.4))
|
val b = fromArray(ShapeND(3), doubleArrayOf(5.5, 2.6, 6.4))
|
||||||
assertEquals(a.dot(b).value(), 59.92)
|
assertEquals(a.dot(b).value(), 59.92)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testQR() = DoubleTensorAlgebra {
|
fun testQR() = DoubleTensorAlgebra {
|
||||||
val shape = Shape(2, 2, 2)
|
val shape = ShapeND(2, 2, 2)
|
||||||
val buffer = doubleArrayOf(
|
val buffer = doubleArrayOf(
|
||||||
1.0, 3.0,
|
1.0, 3.0,
|
||||||
1.0, 2.0,
|
1.0, 2.0,
|
||||||
@ -122,7 +122,7 @@ internal class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLU() = DoubleTensorAlgebra {
|
fun testLU() = DoubleTensorAlgebra {
|
||||||
val shape = Shape(2, 2, 2)
|
val shape = ShapeND(2, 2, 2)
|
||||||
val buffer = doubleArrayOf(
|
val buffer = doubleArrayOf(
|
||||||
1.0, 3.0,
|
1.0, 3.0,
|
||||||
1.0, 2.0,
|
1.0, 2.0,
|
||||||
@ -142,9 +142,9 @@ internal class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCholesky() = DoubleTensorAlgebra {
|
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(
|
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 low = sigma.cholesky()
|
||||||
val sigmChol = low matmul low.transposed()
|
val sigmChol = low matmul low.transposed()
|
||||||
@ -153,24 +153,24 @@ internal class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSVD1D() = DoubleTensorAlgebra {
|
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)
|
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[0]) - 0.386) < 0.01 }
|
||||||
assertTrue { abs(abs(res.source[1]) - 0.922) < 0.01 }
|
assertTrue { abs(abs(res.source[1]) - 0.922) < 0.01 }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSVD() = DoubleTensorAlgebra {
|
fun testSVD() = DoubleTensorAlgebra {
|
||||||
testSVDFor(fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)))
|
testSVDFor(fromArray(ShapeND(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, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBatchedSVD() = DoubleTensorAlgebra {
|
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 (tensorU, tensorS, tensorV) = tensor.svd()
|
||||||
val tensorSVD = tensorU matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed())
|
val tensorSVD = tensorU matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed())
|
||||||
assertTrue(tensor.eq(tensorSVD))
|
assertTrue(tensor.eq(tensorSVD))
|
||||||
@ -178,7 +178,7 @@ internal class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBatchedSymEig() = DoubleTensorAlgebra {
|
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 tensorSigma = tensor + tensor.transposed()
|
||||||
val (tensorS, tensorV) = tensorSigma.symEig()
|
val (tensorS, tensorV) = tensorSigma.symEig()
|
||||||
val tensorSigmaCalc = tensorV matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed())
|
val tensorSigmaCalc = tensorV matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed())
|
||||||
|
@ -21,14 +21,14 @@ internal class TestDoubleTensor {
|
|||||||
@Test
|
@Test
|
||||||
fun testValue() = DoubleTensorAlgebra {
|
fun testValue() = DoubleTensorAlgebra {
|
||||||
val value = 12.5
|
val value = 12.5
|
||||||
val tensor = fromArray(Shape(1), doubleArrayOf(value))
|
val tensor = fromArray(ShapeND(1), doubleArrayOf(value))
|
||||||
assertEquals(tensor.value(), value)
|
assertEquals(tensor.value(), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
@Test
|
@Test
|
||||||
fun testStrides() = DoubleTensorAlgebra {
|
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)
|
assertEquals(tensor[intArrayOf(0, 1)], 5.8)
|
||||||
assertTrue(
|
assertTrue(
|
||||||
tensor.elements().map { it.second }.toList()
|
tensor.elements().map { it.second }.toList()
|
||||||
@ -38,7 +38,7 @@ internal class TestDoubleTensor {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testGet() = DoubleTensorAlgebra {
|
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()
|
val matrix = tensor.getTensor(0).asDoubleTensor2D()
|
||||||
assertEquals(matrix[0, 1], 5.8)
|
assertEquals(matrix[0, 1], 5.8)
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ internal class TestDoubleTensor {
|
|||||||
val doubleArray = DoubleBuffer(1.0, 2.0, 3.0)
|
val doubleArray = DoubleBuffer(1.0, 2.0, 3.0)
|
||||||
|
|
||||||
// create ND buffers, no data is copied
|
// create ND buffers, no data is copied
|
||||||
val ndArray: MutableBufferND<Double> = DoubleBufferND(ColumnStrides(Shape(3)), doubleArray)
|
val ndArray: MutableBufferND<Double> = DoubleBufferND(ColumnStrides(ShapeND(3)), doubleArray)
|
||||||
|
|
||||||
// map to tensors
|
// map to tensors
|
||||||
val tensorArray = ndArray.asDoubleTensor() // Data is copied because of strides change.
|
val tensorArray = ndArray.asDoubleTensor() // Data is copied because of strides change.
|
||||||
@ -91,7 +91,7 @@ internal class TestDoubleTensor {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test2D() = with(DoubleTensorAlgebra) {
|
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())
|
//println(tensor.toPrettyString())
|
||||||
val tensor2d = tensor.asDoubleTensor2D()
|
val tensor2d = tensor.asDoubleTensor2D()
|
||||||
assertBufferEquals(DoubleBuffer(1.0, 0.0, -1.0), tensor2d.rows[1])
|
assertBufferEquals(DoubleBuffer(1.0, 0.0, -1.0), tensor2d.rows[1])
|
||||||
@ -100,7 +100,7 @@ internal class TestDoubleTensor {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMatrixIteration() = with(DoubleTensorAlgebra) {
|
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 ->
|
tensor.forEachMatrix { index, matrix ->
|
||||||
println(index.joinToString { it.toString() })
|
println(index.joinToString { it.toString() })
|
||||||
println(matrix)
|
println(matrix)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
package space.kscience.kmath.tensors.core
|
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.contentEquals
|
||||||
import space.kscience.kmath.nd.get
|
import space.kscience.kmath.nd.get
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
@ -20,53 +20,53 @@ internal class TestDoubleTensorAlgebra {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDoublePlus() = DoubleTensorAlgebra {
|
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
|
val res = 10.0 + tensor
|
||||||
assertTrue(res.source contentEquals doubleArrayOf(11.0, 12.0))
|
assertTrue(res.source contentEquals doubleArrayOf(11.0, 12.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDoubleDiv() = DoubleTensorAlgebra {
|
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
|
val res = 2.0 / tensor
|
||||||
assertTrue(res.source contentEquals doubleArrayOf(1.0, 0.5))
|
assertTrue(res.source contentEquals doubleArrayOf(1.0, 0.5))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDivDouble() = DoubleTensorAlgebra {
|
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
|
val res = tensor / 2.5
|
||||||
assertTrue(res.source contentEquals doubleArrayOf(4.0, 2.0))
|
assertTrue(res.source contentEquals doubleArrayOf(4.0, 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTranspose1x1() = DoubleTensorAlgebra {
|
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)
|
val res = tensor.transposed(0, 0)
|
||||||
|
|
||||||
assertTrue(res.asDoubleTensor().source contentEquals doubleArrayOf(0.0))
|
assertTrue(res.asDoubleTensor().source contentEquals doubleArrayOf(0.0))
|
||||||
assertTrue(res.shape contentEquals Shape(1))
|
assertTrue(res.shape contentEquals ShapeND(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTranspose3x2() = DoubleTensorAlgebra {
|
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)
|
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.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
|
@Test
|
||||||
fun testTranspose1x2x3() = DoubleTensorAlgebra {
|
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 res01 = tensor.transposed(0, 1)
|
||||||
val res02 = tensor.transposed(-3, 2)
|
val res02 = tensor.transposed(-3, 2)
|
||||||
val res12 = tensor.transposed()
|
val res12 = tensor.transposed()
|
||||||
|
|
||||||
assertTrue(res01.shape contentEquals Shape(2, 1, 3))
|
assertTrue(res01.shape contentEquals ShapeND(2, 1, 3))
|
||||||
assertTrue(res02.shape contentEquals Shape(3, 2, 1))
|
assertTrue(res02.shape contentEquals ShapeND(3, 2, 1))
|
||||||
assertTrue(res12.shape contentEquals Shape(1, 3, 2))
|
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(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))
|
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
|
@Test
|
||||||
fun testLinearStructure() = DoubleTensorAlgebra {
|
fun testLinearStructure() = DoubleTensorAlgebra {
|
||||||
val shape = Shape(3)
|
val shape = ShapeND(3)
|
||||||
val tensorA = full(value = -4.5, shape = shape)
|
val tensorA = full(value = -4.5, shape = shape)
|
||||||
val tensorB = full(value = 10.9, shape = shape)
|
val tensorB = full(value = 10.9, shape = shape)
|
||||||
val tensorC = full(value = 789.3, shape = shape)
|
val tensorC = full(value = 789.3, shape = shape)
|
||||||
@ -107,28 +107,28 @@ internal class TestDoubleTensorAlgebra {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDot() = DoubleTensorAlgebra {
|
fun testDot() = DoubleTensorAlgebra {
|
||||||
val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor1 = fromArray(ShapeND(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 tensor11 = fromArray(ShapeND(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 tensor2 = fromArray(ShapeND(3), doubleArrayOf(10.0, 20.0, 30.0))
|
||||||
val tensor3 = fromArray(Shape(1, 1, 3), doubleArrayOf(-1.0, -2.0, -3.0))
|
val tensor3 = fromArray(ShapeND(1, 1, 3), doubleArrayOf(-1.0, -2.0, -3.0))
|
||||||
val tensor4 = fromArray(Shape(2, 3, 3), (1..18).map { it.toDouble() }.toDoubleArray())
|
val tensor4 = fromArray(ShapeND(2, 3, 3), (1..18).map { it.toDouble() }.toDoubleArray())
|
||||||
val tensor5 = fromArray(Shape(2, 3, 3), (1..18).map { 1 + it.toDouble() }.toDoubleArray())
|
val tensor5 = fromArray(ShapeND(2, 3, 3), (1..18).map { 1 + it.toDouble() }.toDoubleArray())
|
||||||
|
|
||||||
val res12 = tensor1.dot(tensor2)
|
val res12 = tensor1.dot(tensor2)
|
||||||
assertTrue(res12.source contentEquals doubleArrayOf(140.0, 320.0))
|
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)
|
val res32 = tensor3.matmul(tensor2)
|
||||||
assertTrue(res32.source contentEquals doubleArrayOf(-140.0))
|
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)
|
val res22 = tensor2.dot(tensor2)
|
||||||
assertTrue(res22.source contentEquals doubleArrayOf(1400.0))
|
assertTrue(res22.source contentEquals doubleArrayOf(1400.0))
|
||||||
assertTrue(res22.shape contentEquals Shape(1))
|
assertTrue(res22.shape contentEquals ShapeND(1))
|
||||||
|
|
||||||
val res11 = tensor1.dot(tensor11)
|
val res11 = tensor1.dot(tensor11)
|
||||||
assertTrue(res11.source contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0))
|
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)
|
val res45 = tensor4.matmul(tensor5)
|
||||||
assertTrue(
|
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
|
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
|
@Test
|
||||||
fun testDiagonalEmbedding() = DoubleTensorAlgebra {
|
fun testDiagonalEmbedding() = DoubleTensorAlgebra {
|
||||||
val tensor1 = fromArray(Shape(3), doubleArrayOf(10.0, 20.0, 30.0))
|
val tensor1 = fromArray(ShapeND(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 tensor2 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
val tensor3 = zeros(Shape(2, 3, 4, 5))
|
val tensor3 = zeros(ShapeND(2, 3, 4, 5))
|
||||||
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
diagonalEmbedding(tensor3, 0, 3, 4).shape contentEquals
|
diagonalEmbedding(tensor3, 0, 3, 4).shape contentEquals
|
||||||
Shape(2, 3, 4, 5, 5)
|
ShapeND(2, 3, 4, 5, 5)
|
||||||
)
|
)
|
||||||
assertTrue(
|
assertTrue(
|
||||||
diagonalEmbedding(tensor3, 1, 3, 4).shape contentEquals
|
diagonalEmbedding(tensor3, 1, 3, 4).shape contentEquals
|
||||||
Shape(2, 3, 4, 6, 6)
|
ShapeND(2, 3, 4, 6, 6)
|
||||||
)
|
)
|
||||||
assertTrue(
|
assertTrue(
|
||||||
diagonalEmbedding(tensor3, 2, 0, 3).shape contentEquals
|
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)
|
val diagonal1 = diagonalEmbedding(tensor1, 0, 1, 0)
|
||||||
assertTrue(diagonal1.shape contentEquals Shape(3, 3))
|
assertTrue(diagonal1.shape contentEquals ShapeND(3, 3))
|
||||||
assertTrue(
|
assertTrue(
|
||||||
diagonal1.source contentEquals
|
diagonal1.source contentEquals
|
||||||
doubleArrayOf(10.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 30.0)
|
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)
|
val diagonal1Offset = diagonalEmbedding(tensor1, 1, 1, 0)
|
||||||
assertTrue(diagonal1Offset.shape contentEquals Shape(4, 4))
|
assertTrue(diagonal1Offset.shape contentEquals ShapeND(4, 4))
|
||||||
assertTrue(
|
assertTrue(
|
||||||
diagonal1Offset.source contentEquals
|
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)
|
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)
|
val diagonal2 = diagonalEmbedding(tensor2, 1, 0, 2)
|
||||||
assertTrue(diagonal2.shape contentEquals Shape(4, 2, 4))
|
assertTrue(diagonal2.shape contentEquals ShapeND(4, 2, 4))
|
||||||
assertTrue(
|
assertTrue(
|
||||||
diagonal2.source contentEquals
|
diagonal2.source contentEquals
|
||||||
doubleArrayOf(
|
doubleArrayOf(
|
||||||
@ -188,9 +188,9 @@ internal class TestDoubleTensorAlgebra {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testEq() = DoubleTensorAlgebra {
|
fun testEq() = DoubleTensorAlgebra {
|
||||||
val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor1 = fromArray(ShapeND(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 tensor2 = fromArray(ShapeND(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 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 tensor1)
|
||||||
assertTrue(tensor1 eq tensor2)
|
assertTrue(tensor1 eq tensor2)
|
||||||
@ -204,7 +204,7 @@ internal class TestDoubleTensorAlgebra {
|
|||||||
val l = tensor.getTensor(0).map { it + 1.0 }
|
val l = tensor.getTensor(0).map { it + 1.0 }
|
||||||
val r = tensor.getTensor(1).map { it - 1.0 }
|
val r = tensor.getTensor(1).map { it - 1.0 }
|
||||||
val res = l + r
|
val res = l + r
|
||||||
assertTrue { Shape(5, 5) contentEquals res.shape }
|
assertTrue { ShapeND(5, 5) contentEquals res.shape }
|
||||||
assertEquals(2.0, res[4, 4])
|
assertEquals(2.0, res[4, 4])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ public open class ViktorFieldOpsND :
|
|||||||
override val elementAlgebra: DoubleField get() = DoubleField
|
override val elementAlgebra: DoubleField get() = DoubleField
|
||||||
|
|
||||||
@OptIn(UnsafeKMathAPI::class)
|
@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 {
|
F64Array(*shape.asArray()).apply {
|
||||||
ColumnStrides(shape).asSequence().forEach { index ->
|
ColumnStrides(shape).asSequence().forEach { index ->
|
||||||
set(value = DoubleField.initializer(index), indices = index)
|
set(value = DoubleField.initializer(index), indices = index)
|
||||||
@ -46,7 +46,7 @@ public open class ViktorFieldOpsND :
|
|||||||
@PerformancePitfall
|
@PerformancePitfall
|
||||||
override fun StructureND<Double>.map(transform: DoubleField.(Double) -> Double): ViktorStructureND =
|
override fun StructureND<Double>.map(transform: DoubleField.(Double) -> Double): ViktorStructureND =
|
||||||
F64Array(*shape.asArray()).apply {
|
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)
|
set(value = DoubleField.transform(this@map[index]), indices = index)
|
||||||
}
|
}
|
||||||
}.asStructure()
|
}.asStructure()
|
||||||
@ -56,7 +56,7 @@ public open class ViktorFieldOpsND :
|
|||||||
override fun StructureND<Double>.mapIndexed(
|
override fun StructureND<Double>.mapIndexed(
|
||||||
transform: DoubleField.(index: IntArray, Double) -> Double,
|
transform: DoubleField.(index: IntArray, Double) -> Double,
|
||||||
): ViktorStructureND = F64Array(*shape.asArray()).apply {
|
): 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)
|
set(value = DoubleField.transform(index, this@mapIndexed[index]), indices = index)
|
||||||
}
|
}
|
||||||
}.asStructure()
|
}.asStructure()
|
||||||
@ -127,7 +127,7 @@ public open class ViktorFieldND(
|
|||||||
private val shapeAsArray: IntArray,
|
private val shapeAsArray: IntArray,
|
||||||
) : ViktorFieldOpsND(), FieldND<Double, DoubleField>, NumbersAddOps<StructureND<Double>> {
|
) : ViktorFieldOpsND(), FieldND<Double, DoubleField>, NumbersAddOps<StructureND<Double>> {
|
||||||
|
|
||||||
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() }
|
override val zero: ViktorStructureND by lazy { F64Array.full(init = 0.0, shape = shapeAsArray).asStructure() }
|
||||||
|
@ -9,11 +9,11 @@ import org.jetbrains.bio.viktor.F64Array
|
|||||||
import space.kscience.kmath.misc.PerformancePitfall
|
import space.kscience.kmath.misc.PerformancePitfall
|
||||||
import space.kscience.kmath.nd.ColumnStrides
|
import space.kscience.kmath.nd.ColumnStrides
|
||||||
import space.kscience.kmath.nd.MutableStructureND
|
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")
|
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||||
public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructureND<Double> {
|
public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructureND<Double> {
|
||||||
override val shape: Shape get() = Shape(f64Buffer.shape)
|
override val shape: ShapeND get() = ShapeND(f64Buffer.shape)
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
override inline fun get(index: IntArray): Double = f64Buffer.get(*index)
|
override inline fun get(index: IntArray): Double = f64Buffer.get(*index)
|
||||||
|
Loading…
Reference in New Issue
Block a user