KMP library for tensors #300
@ -32,7 +32,7 @@ public interface LinearOpsTensorAlgebra<T, TensorType : TensorStructure<T>> :
|
||||
public fun TensorType.lu(): Pair<TensorType, IntTensor>
|
||||
|
||||
//https://pytorch.org/docs/stable/generated/torch.lu_unpack.html
|
||||
public fun luPivot(aLU: TensorType, pivots: IntTensor): Triple<TensorType, TensorType, TensorType>
|
||||
public fun luPivot(lu: TensorType, pivots: IntTensor): Triple<TensorType, TensorType, TensorType>
|
||||
|
||||
//https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd
|
||||
public fun TensorType.svd(): Triple<TensorType, TensorType, TensorType>
|
||||
|
@ -144,5 +144,7 @@ public class RealAnalyticTensorAlgebra:
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public inline fun <R> RealAnalyticTensorAlgebra(block: RealTensorAlgebra.() -> R): R =
|
||||
RealAnalyticTensorAlgebra().block()
|
@ -1,6 +1,7 @@
|
||||
package space.kscience.kmath.tensors
|
||||
|
||||
import space.kscience.kmath.structures.array
|
||||
import space.kscience.kmath.structures.toDoubleArray
|
||||
import space.kscience.kmath.structures.toIntArray
|
||||
|
||||
public class RealLinearOpsTensorAlgebra :
|
||||
LinearOpsTensorAlgebra<Double, RealTensor>,
|
||||
@ -80,7 +81,7 @@ public class RealLinearOpsTensorAlgebra :
|
||||
// todo checks
|
||||
val n = lu.shape[0]
|
||||
val p = lu.zeroesLike()
|
||||
pivots.buffer.array.forEachIndexed { i, pivot ->
|
||||
pivots.buffer.toIntArray().forEachIndexed { i, pivot ->
|
||||
p[i, pivot] = 1.0
|
||||
}
|
||||
val l = lu.zeroesLike()
|
||||
@ -130,4 +131,4 @@ public class RealLinearOpsTensorAlgebra :
|
||||
}
|
||||
|
||||
public inline fun <R> RealLinearOpsTensorAlgebra(block: RealTensorAlgebra.() -> R): R =
|
||||
RealTensorAlgebra().block()
|
||||
RealLinearOpsTensorAlgebra().block()
|
@ -1,6 +1,6 @@
|
||||
package space.kscience.kmath.tensors
|
||||
|
||||
import space.kscience.kmath.structures.array
|
||||
import space.kscience.kmath.structures.toDoubleArray
|
||||
|
||||
|
||||
public open class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealTensor> {
|
||||
@ -9,7 +9,7 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealT
|
||||
check(this.shape contentEquals intArrayOf(1)) {
|
||||
"Inconsistent value for tensor of shape ${shape.toList()}"
|
||||
}
|
||||
return this.buffer.array[0]
|
||||
return this.buffer.toDoubleArray()[0]
|
||||
}
|
||||
|
||||
override fun zeros(shape: IntArray): RealTensor {
|
||||
@ -32,13 +32,13 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealT
|
||||
|
||||
override fun RealTensor.copy(): RealTensor {
|
||||
// should be rework as soon as copy() method for NDBuffer will be available
|
||||
return RealTensor(this.shape, this.buffer.array.copyOf())
|
||||
return RealTensor(this.shape, this.buffer.toDoubleArray().copyOf())
|
||||
}
|
||||
|
||||
|
||||
override fun Double.plus(other: RealTensor): RealTensor {
|
||||
val resBuffer = DoubleArray(other.buffer.size) { i ->
|
||||
other.buffer.array[i] + this
|
||||
other.buffer.toDoubleArray()[i] + this
|
||||
}
|
||||
return RealTensor(other.shape, resBuffer)
|
||||
}
|
||||
@ -50,34 +50,34 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealT
|
||||
val newThis = broadcast[0]
|
||||
val newOther = broadcast[1]
|
||||
val resBuffer = DoubleArray(newThis.buffer.size) { i ->
|
||||
newThis.buffer.array[i] + newOther.buffer.array[i]
|
||||
newThis.buffer.toDoubleArray()[i] + newOther.buffer.toDoubleArray()[i]
|
||||
}
|
||||
return RealTensor(newThis.shape, resBuffer)
|
||||
}
|
||||
|
||||
override fun RealTensor.plusAssign(value: Double) {
|
||||
for (i in this.buffer.array.indices) {
|
||||
this.buffer.array[i] += value
|
||||
for (i in this.buffer.toDoubleArray().indices) {
|
||||
this.buffer.toDoubleArray()[i] += value
|
||||
}
|
||||
}
|
||||
|
||||
override fun RealTensor.plusAssign(other: RealTensor) {
|
||||
//todo should be change with broadcasting
|
||||
for (i in this.buffer.array.indices) {
|
||||
this.buffer.array[i] += other.buffer.array[i]
|
||||
for (i in this.buffer.toDoubleArray().indices) {
|
||||
this.buffer.toDoubleArray()[i] += other.buffer.toDoubleArray()[i]
|
||||
}
|
||||
}
|
||||
|
||||
override fun Double.minus(other: RealTensor): RealTensor {
|
||||
val resBuffer = DoubleArray(other.buffer.size) { i ->
|
||||
this - other.buffer.array[i]
|
||||
this - other.buffer.toDoubleArray()[i]
|
||||
}
|
||||
return RealTensor(other.shape, resBuffer)
|
||||
}
|
||||
|
||||
override fun RealTensor.minus(value: Double): RealTensor {
|
||||
val resBuffer = DoubleArray(this.buffer.size) { i ->
|
||||
this.buffer.array[i] - value
|
||||
this.buffer.toDoubleArray()[i] - value
|
||||
}
|
||||
return RealTensor(this.shape, resBuffer)
|
||||
}
|
||||
@ -87,14 +87,14 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealT
|
||||
val newThis = broadcast[0]
|
||||
val newOther = broadcast[1]
|
||||
val resBuffer = DoubleArray(newThis.buffer.size) { i ->
|
||||
newThis.buffer.array[i] - newOther.buffer.array[i]
|
||||
newThis.buffer.toDoubleArray()[i] - newOther.buffer.toDoubleArray()[i]
|
||||
}
|
||||
return RealTensor(newThis.shape, resBuffer)
|
||||
}
|
||||
|
||||
override fun RealTensor.minusAssign(value: Double) {
|
||||
for (i in this.buffer.array.indices) {
|
||||
this.buffer.array[i] -= value
|
||||
for (i in this.buffer.toDoubleArray().indices) {
|
||||
this.buffer.toDoubleArray()[i] -= value
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealT
|
||||
override fun Double.times(other: RealTensor): RealTensor {
|
||||
//todo should be change with broadcasting
|
||||
val resBuffer = DoubleArray(other.buffer.size) { i ->
|
||||
other.buffer.array[i] * this
|
||||
other.buffer.toDoubleArray()[i] * this
|
||||
}
|
||||
return RealTensor(other.shape, resBuffer)
|
||||
}
|
||||
@ -116,28 +116,28 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealT
|
||||
override fun RealTensor.times(other: RealTensor): RealTensor {
|
||||
//todo should be change with broadcasting
|
||||
val resBuffer = DoubleArray(this.buffer.size) { i ->
|
||||
this.buffer.array[i] * other.buffer.array[i]
|
||||
this.buffer.toDoubleArray()[i] * other.buffer.toDoubleArray()[i]
|
||||
}
|
||||
return RealTensor(this.shape, resBuffer)
|
||||
}
|
||||
|
||||
override fun RealTensor.timesAssign(value: Double) {
|
||||
//todo should be change with broadcasting
|
||||
for (i in this.buffer.array.indices) {
|
||||
this.buffer.array[i] *= value
|
||||
for (i in this.buffer.toDoubleArray().indices) {
|
||||
this.buffer.toDoubleArray()[i] *= value
|
||||
}
|
||||
}
|
||||
|
||||
override fun RealTensor.timesAssign(other: RealTensor) {
|
||||
//todo should be change with broadcasting
|
||||
for (i in this.buffer.array.indices) {
|
||||
this.buffer.array[i] *= other.buffer.array[i]
|
||||
for (i in this.buffer.toDoubleArray().indices) {
|
||||
this.buffer.toDoubleArray()[i] *= other.buffer.toDoubleArray()[i]
|
||||
}
|
||||
}
|
||||
|
||||
override fun RealTensor.unaryMinus(): RealTensor {
|
||||
val resBuffer = DoubleArray(this.buffer.size) { i ->
|
||||
this.buffer.array[i].unaryMinus()
|
||||
this.buffer.toDoubleArray()[i].unaryMinus()
|
||||
}
|
||||
return RealTensor(this.shape, resBuffer)
|
||||
}
|
||||
@ -158,14 +158,14 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealT
|
||||
newMultiIndex[i] = newMultiIndex[j].also { newMultiIndex[j] = newMultiIndex[i] }
|
||||
|
||||
val linearIndex = resTensor.strides.offset(newMultiIndex)
|
||||
resTensor.buffer.array[linearIndex] = this.buffer.array[offset]
|
||||
resTensor.buffer.toDoubleArray()[linearIndex] = this.buffer.toDoubleArray()[offset]
|
||||
}
|
||||
return resTensor
|
||||
}
|
||||
|
||||
|
||||
override fun RealTensor.view(shape: IntArray): RealTensor {
|
||||
return RealTensor(shape, this.buffer.array)
|
||||
return RealTensor(shape, this.buffer.toDoubleArray())
|
||||
}
|
||||
|
||||
override fun RealTensor.viewAs(other: RealTensor): RealTensor {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package space.kscience.kmath.tensors
|
||||
|
||||
import space.kscience.kmath.structures.array
|
||||
import space.kscience.kmath.structures.toDoubleArray
|
||||
import kotlin.math.max
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ internal inline fun broadcastTensors(vararg tensors: RealTensor): List<RealTenso
|
||||
}
|
||||
|
||||
val curLinearIndex = tensor.strides.offset(curMultiIndex)
|
||||
resTensor.buffer.array[linearIndex] = tensor.buffer.array[curLinearIndex]
|
||||
resTensor.buffer.toDoubleArray()[linearIndex] = tensor.buffer.toDoubleArray()[curLinearIndex]
|
||||
}
|
||||
res.add(resTensor)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package space.kscience.kmath.tensors
|
||||
|
||||
|
||||
import space.kscience.kmath.structures.array
|
||||
import space.kscience.kmath.structures.toDoubleArray
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
@ -19,6 +19,6 @@ class TestRealTensor {
|
||||
fun stridesTest(){
|
||||
val tensor = RealTensor(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4))
|
||||
assertEquals(tensor[intArrayOf(0,1)], 5.8)
|
||||
assertTrue(tensor.elements().map{ it.second }.toList().toDoubleArray() contentEquals tensor.buffer.array)
|
||||
assertTrue(tensor.elements().map{ it.second }.toList().toDoubleArray() contentEquals tensor.buffer.toDoubleArray())
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package space.kscience.kmath.tensors
|
||||
|
||||
import space.kscience.kmath.structures.array
|
||||
import space.kscience.kmath.structures.toDoubleArray
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
@ -10,7 +10,7 @@ class TestRealTensorAlgebra {
|
||||
fun doublePlus() = RealTensorAlgebra {
|
||||
val tensor = RealTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0))
|
||||
val res = 10.0 + tensor
|
||||
assertTrue(res.buffer.array contentEquals doubleArrayOf(11.0,12.0))
|
||||
assertTrue(res.buffer.toDoubleArray() contentEquals doubleArrayOf(11.0,12.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -18,7 +18,7 @@ class TestRealTensorAlgebra {
|
||||
val tensor = RealTensor(intArrayOf(1), doubleArrayOf(0.0))
|
||||
val res = tensor.transpose(0, 0)
|
||||
|
||||
assertTrue(res.buffer.array contentEquals doubleArrayOf(0.0))
|
||||
assertTrue(res.buffer.toDoubleArray() contentEquals doubleArrayOf(0.0))
|
||||
assertTrue(res.shape contentEquals intArrayOf(1))
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ class TestRealTensorAlgebra {
|
||||
val tensor = RealTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||
val res = tensor.transpose(1, 0)
|
||||
|
||||
assertTrue(res.buffer.array contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0))
|
||||
assertTrue(res.buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0))
|
||||
assertTrue(res.shape contentEquals intArrayOf(2, 3))
|
||||
}
|
||||
|
||||
@ -42,9 +42,9 @@ class TestRealTensorAlgebra {
|
||||
assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1))
|
||||
assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2))
|
||||
|
||||
assertTrue(res01.buffer.array contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||
assertTrue(res02.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0))
|
||||
assertTrue(res12.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0))
|
||||
assertTrue(res01.buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||
assertTrue(res02.buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0))
|
||||
assertTrue(res12.buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -70,9 +70,9 @@ class TestRealTensorAlgebra {
|
||||
assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3))
|
||||
assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3))
|
||||
|
||||
assertTrue(res[0].buffer.array contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||
assertTrue(res[1].buffer.array contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0))
|
||||
assertTrue(res[2].buffer.array contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0))
|
||||
assertTrue(res[0].buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||
assertTrue(res[1].buffer.toDoubleArray() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0))
|
||||
assertTrue(res[2].buffer.toDoubleArray() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -82,14 +82,14 @@ class TestRealTensorAlgebra {
|
||||
val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0))
|
||||
|
||||
assertTrue((tensor2 - tensor1).shape contentEquals intArrayOf(2, 3))
|
||||
assertTrue((tensor2 - tensor1).buffer.array contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0))
|
||||
assertTrue((tensor2 - tensor1).buffer.toDoubleArray() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0))
|
||||
|
||||
assertTrue((tensor3 - tensor1).shape contentEquals intArrayOf(1, 2, 3))
|
||||
assertTrue((tensor3 - tensor1).buffer.array
|
||||
assertTrue((tensor3 - tensor1).buffer.toDoubleArray()
|
||||
contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0))
|
||||
|
||||
assertTrue((tensor3 - tensor2).shape contentEquals intArrayOf(1, 1, 3))
|
||||
assertTrue((tensor3 - tensor2).buffer.array contentEquals doubleArrayOf(490.0, 480.0, 470.0))
|
||||
assertTrue((tensor3 - tensor2).buffer.toDoubleArray() contentEquals doubleArrayOf(490.0, 480.0, 470.0))
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user