forked from kscience/kmath
basic implements & refactor tensor structure & and new tensor algebra methods
This commit is contained in:
parent
90f4ff06fd
commit
fe55856a26
@ -3,6 +3,8 @@ package space.kscience.kmath.tensors
|
|||||||
import space.kscience.kmath.nd.MutableNDBuffer
|
import space.kscience.kmath.nd.MutableNDBuffer
|
||||||
import space.kscience.kmath.structures.RealBuffer
|
import space.kscience.kmath.structures.RealBuffer
|
||||||
import space.kscience.kmath.structures.array
|
import space.kscience.kmath.structures.array
|
||||||
|
import kotlin.js.JsName
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
|
||||||
public class RealTensor(
|
public class RealTensor(
|
||||||
@ -13,46 +15,80 @@ public class RealTensor(
|
|||||||
MutableNDBuffer<Double>(
|
MutableNDBuffer<Double>(
|
||||||
TensorStrides(shape),
|
TensorStrides(shape),
|
||||||
RealBuffer(buffer)
|
RealBuffer(buffer)
|
||||||
) {
|
)
|
||||||
/*
|
|
||||||
* TODO: Andrei remove item()
|
|
||||||
*/
|
|
||||||
override fun item(): Double {
|
|
||||||
check(buffer.size > 0) { "The tensor is empty" }
|
|
||||||
return buffer[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealTensor> {
|
public class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealTensor> {
|
||||||
|
|
||||||
|
//rename to item?
|
||||||
override fun RealTensor.value(): Double {
|
override fun RealTensor.value(): Double {
|
||||||
TODO("Andrei")
|
check(this.dimension == 0) {
|
||||||
|
// todo change message
|
||||||
|
"This tensor has shape ${shape.toList()}"
|
||||||
|
}
|
||||||
|
return this.buffer.array[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun eye(n: Int): RealTensor {
|
||||||
|
val shape = intArrayOf(n, n)
|
||||||
|
val buffer = DoubleArray(n * n) { 0.0 }
|
||||||
|
val res = RealTensor(shape, buffer)
|
||||||
|
for (i in 0 until n) {
|
||||||
|
res[intArrayOf(i, i)] = 1.0
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun zeros(shape: IntArray): RealTensor {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun zeroesLike(other: RealTensor): RealTensor {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ones(shape: IntArray): RealTensor {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onesLike(shape: IntArray): RealTensor {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun RealTensor.copy(): RealTensor {
|
||||||
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun Double.plus(other: RealTensor): RealTensor {
|
override fun Double.plus(other: RealTensor): RealTensor {
|
||||||
val n = other.buffer.size
|
//todo should be change with broadcasting
|
||||||
val arr = other.buffer.array
|
val resBuffer = DoubleArray(other.buffer.size) { i ->
|
||||||
val res = DoubleArray(n)
|
other.buffer.array[i] + this
|
||||||
for (i in 1..n)
|
}
|
||||||
res[i - 1] = arr[i - 1] + this
|
return RealTensor(other.shape, resBuffer)
|
||||||
return RealTensor(other.shape, res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun RealTensor.plus(value: Double): RealTensor {
|
//todo should be change with broadcasting
|
||||||
TODO("Andrei")
|
override fun RealTensor.plus(value: Double): RealTensor = value + this
|
||||||
}
|
|
||||||
|
|
||||||
override fun RealTensor.plus(other: RealTensor): RealTensor {
|
override fun RealTensor.plus(other: RealTensor): RealTensor {
|
||||||
TODO("Andrei")
|
//todo should be change with broadcasting
|
||||||
|
val resBuffer = DoubleArray(this.buffer.size) { i ->
|
||||||
|
this.buffer.array[i] + other.buffer.array[i]
|
||||||
|
}
|
||||||
|
return RealTensor(this.shape, resBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun RealTensor.plusAssign(value: Double) {
|
override fun RealTensor.plusAssign(value: Double) {
|
||||||
TODO("Andrei")
|
//todo should be change with broadcasting
|
||||||
|
for (i in this.buffer.array.indices) {
|
||||||
|
this.buffer.array[i] += value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun RealTensor.plusAssign(other: RealTensor) {
|
override fun RealTensor.plusAssign(other: RealTensor) {
|
||||||
TODO("Andrei")
|
//todo should be change with broadcasting
|
||||||
|
for (i in this.buffer.array.indices) {
|
||||||
|
this.buffer.array[i] += other.buffer.array[i]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun Double.minus(other: RealTensor): RealTensor {
|
override fun Double.minus(other: RealTensor): RealTensor {
|
||||||
@ -76,27 +112,43 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealTensor
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun Double.times(other: RealTensor): RealTensor {
|
override fun Double.times(other: RealTensor): RealTensor {
|
||||||
TODO("Andrei")
|
//todo should be change with broadcasting
|
||||||
|
val resBuffer = DoubleArray(other.buffer.size) { i ->
|
||||||
|
other.buffer.array[i] * this
|
||||||
|
}
|
||||||
|
return RealTensor(other.shape, resBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun RealTensor.times(value: Double): RealTensor {
|
//todo should be change with broadcasting
|
||||||
TODO("Andrei")
|
override fun RealTensor.times(value: Double): RealTensor = value * this
|
||||||
}
|
|
||||||
|
|
||||||
override fun RealTensor.times(other: RealTensor): RealTensor {
|
override fun RealTensor.times(other: RealTensor): RealTensor {
|
||||||
TODO("Andrei")
|
//todo should be change with broadcasting
|
||||||
|
val resBuffer = DoubleArray(this.buffer.size) { i ->
|
||||||
|
this.buffer.array[i] * other.buffer.array[i]
|
||||||
|
}
|
||||||
|
return RealTensor(this.shape, resBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun RealTensor.timesAssign(value: Double) {
|
override fun RealTensor.timesAssign(value: Double) {
|
||||||
TODO("Andrei")
|
//todo should be change with broadcasting
|
||||||
|
for (i in this.buffer.array.indices) {
|
||||||
|
this.buffer.array[i] *= value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun RealTensor.timesAssign(other: RealTensor) {
|
override fun RealTensor.timesAssign(other: RealTensor) {
|
||||||
TODO("Andrei")
|
//todo should be change with broadcasting
|
||||||
|
for (i in this.buffer.array.indices) {
|
||||||
|
this.buffer.array[i] *= other.buffer.array[i]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun RealTensor.unaryMinus(): RealTensor {
|
override fun RealTensor.unaryMinus(): RealTensor {
|
||||||
TODO("Andrei")
|
val resBuffer = DoubleArray(this.buffer.size) { i ->
|
||||||
|
this.buffer.array[i].unaryMinus()
|
||||||
|
}
|
||||||
|
return RealTensor(this.shape, resBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun RealTensor.dot(other: RealTensor): RealTensor {
|
override fun RealTensor.dot(other: RealTensor): RealTensor {
|
||||||
@ -124,11 +176,11 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealTensor
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun RealTensor.view(shape: IntArray): RealTensor {
|
override fun RealTensor.view(shape: IntArray): RealTensor {
|
||||||
TODO("Andrei")
|
return RealTensor(shape, this.buffer.array)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun RealTensor.view_as(other: RealTensor): RealTensor {
|
override fun RealTensor.viewAs(other: RealTensor): RealTensor {
|
||||||
TODO("Andrei")
|
return this.view(other.shape)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun RealTensor.abs(): RealTensor {
|
override fun RealTensor.abs(): RealTensor {
|
||||||
@ -147,10 +199,18 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealTensor
|
|||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun RealTensor.div(value: Double): RealTensor {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
override fun RealTensor.div(other: RealTensor): RealTensor {
|
override fun RealTensor.div(other: RealTensor): RealTensor {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun RealTensor.divAssign(value: Double) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
override fun RealTensor.divAssign(other: RealTensor) {
|
override fun RealTensor.divAssign(other: RealTensor) {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
@ -172,15 +232,10 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra<Double, RealTensor
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun RealTensor.lu(): Pair<RealTensor, RealTensor> {
|
override fun RealTensor.lu(): Pair<RealTensor, RealTensor> {
|
||||||
/**
|
TODO()
|
||||||
* Main first task for @AndreiKingsley
|
|
||||||
* Compare with the implementation of [LupDecomposition]
|
|
||||||
* and provide a common API
|
|
||||||
*/
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun lu_unpack(A_LU: RealTensor, pivots: RealTensor): Triple<RealTensor, RealTensor, RealTensor> {
|
override fun luUnpack(A_LU: RealTensor, pivots: RealTensor): Triple<RealTensor, RealTensor, RealTensor> {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,14 @@ public interface TensorAlgebra<T, TensorType : TensorStructure<T>> {
|
|||||||
|
|
||||||
public fun TensorType.value(): T
|
public fun TensorType.value(): T
|
||||||
|
|
||||||
|
public fun eye(n: Int): TensorType
|
||||||
|
public fun zeros(shape: IntArray): TensorType
|
||||||
|
public fun zeroesLike(other: TensorType): TensorType
|
||||||
|
public fun ones(shape: IntArray): TensorType
|
||||||
|
public fun onesLike(shape: IntArray): TensorType
|
||||||
|
|
||||||
|
public fun TensorType.copy(): TensorType
|
||||||
|
|
||||||
public operator fun T.plus(other: TensorType): TensorType
|
public operator fun T.plus(other: TensorType): TensorType
|
||||||
public operator fun TensorType.plus(value: T): TensorType
|
public operator fun TensorType.plus(value: T): TensorType
|
||||||
public operator fun TensorType.plus(other: TensorType): TensorType
|
public operator fun TensorType.plus(other: TensorType): TensorType
|
||||||
@ -42,7 +50,7 @@ public interface TensorAlgebra<T, TensorType : TensorStructure<T>> {
|
|||||||
|
|
||||||
//https://pytorch.org/docs/stable/tensor_view.html
|
//https://pytorch.org/docs/stable/tensor_view.html
|
||||||
public fun TensorType.view(shape: IntArray): TensorType
|
public fun TensorType.view(shape: IntArray): TensorType
|
||||||
public fun TensorType.view_as(other: TensorType): TensorType
|
public fun TensorType.viewAs(other: TensorType): TensorType
|
||||||
|
|
||||||
//https://pytorch.org/docs/stable/generated/torch.abs.html
|
//https://pytorch.org/docs/stable/generated/torch.abs.html
|
||||||
public fun TensorType.abs(): TensorType
|
public fun TensorType.abs(): TensorType
|
||||||
@ -57,7 +65,9 @@ public interface TensorAlgebra<T, TensorType : TensorStructure<T>> {
|
|||||||
public interface TensorPartialDivisionAlgebra<T, TensorType : TensorStructure<T>> :
|
public interface TensorPartialDivisionAlgebra<T, TensorType : TensorStructure<T>> :
|
||||||
TensorAlgebra<T, TensorType> {
|
TensorAlgebra<T, TensorType> {
|
||||||
|
|
||||||
|
public operator fun TensorType.div(value: T): TensorType
|
||||||
public operator fun TensorType.div(other: TensorType): TensorType
|
public operator fun TensorType.div(other: TensorType): TensorType
|
||||||
|
public operator fun TensorType.divAssign(value: T)
|
||||||
public operator fun TensorType.divAssign(other: TensorType)
|
public operator fun TensorType.divAssign(other: TensorType)
|
||||||
|
|
||||||
//https://pytorch.org/docs/stable/generated/torch.exp.html
|
//https://pytorch.org/docs/stable/generated/torch.exp.html
|
||||||
@ -72,7 +82,7 @@ public interface TensorPartialDivisionAlgebra<T, TensorType : TensorStructure<T>
|
|||||||
public fun TensorType.lu(): Pair<TensorType, TensorType>
|
public fun TensorType.lu(): Pair<TensorType, TensorType>
|
||||||
|
|
||||||
//https://pytorch.org/docs/stable/generated/torch.lu_unpack.html
|
//https://pytorch.org/docs/stable/generated/torch.lu_unpack.html
|
||||||
public fun lu_unpack(A_LU: TensorType, pivots: TensorType): Triple<TensorType, TensorType, TensorType>
|
public fun luUnpack(A_LU: TensorType, pivots: TensorType): Triple<TensorType, TensorType, TensorType>
|
||||||
|
|
||||||
//https://pytorch.org/docs/stable/generated/torch.svd.html
|
//https://pytorch.org/docs/stable/generated/torch.svd.html
|
||||||
public fun TensorType.svd(): Triple<TensorType, TensorType, TensorType>
|
public fun TensorType.svd(): Triple<TensorType, TensorType, TensorType>
|
||||||
|
@ -5,7 +5,7 @@ import space.kscience.kmath.nd.offsetFromIndex
|
|||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
|
|
||||||
inline public fun stridesFromShape(shape: IntArray): IntArray {
|
public inline fun stridesFromShape(shape: IntArray): IntArray {
|
||||||
val nDim = shape.size
|
val nDim = shape.size
|
||||||
val res = IntArray(nDim)
|
val res = IntArray(nDim)
|
||||||
if (nDim == 0)
|
if (nDim == 0)
|
||||||
@ -22,7 +22,7 @@ inline public fun stridesFromShape(shape: IntArray): IntArray {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline public fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray {
|
public inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray {
|
||||||
val res = IntArray(nDim)
|
val res = IntArray(nDim)
|
||||||
var current = offset
|
var current = offset
|
||||||
var strideIndex = 0
|
var strideIndex = 0
|
||||||
|
@ -2,26 +2,5 @@ package space.kscience.kmath.tensors
|
|||||||
|
|
||||||
import space.kscience.kmath.nd.MutableNDStructure
|
import space.kscience.kmath.nd.MutableNDStructure
|
||||||
|
|
||||||
public interface TensorStructure<T> : MutableNDStructure<T> {
|
public typealias TensorStructure<T> = MutableNDStructure<T>
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: Andrei remove item() and value()
|
|
||||||
*/
|
|
||||||
public fun item(): T
|
|
||||||
|
|
||||||
// A tensor can have empty shape, in which case it represents just a value
|
|
||||||
public fun value(): T {
|
|
||||||
checkIsValue()
|
|
||||||
return item()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline fun <T> TensorStructure<T>.isValue(): Boolean {
|
|
||||||
return (dimension == 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline fun <T> TensorStructure<T>.isNotValue(): Boolean = !this.isValue()
|
|
||||||
|
|
||||||
public inline fun <T> TensorStructure<T>.checkIsValue(): Unit = check(this.isValue()) {
|
|
||||||
"This tensor has shape ${shape.toList()}"
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user