KMP library for tensors #300
@ -8,7 +8,7 @@ import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure
|
||||
|
||||
public open class BufferedTensor<T>(
|
||||
override val shape: IntArray,
|
||||
internal val buffer: MutableBuffer<T>,
|
||||
internal val mutableBuffer: MutableBuffer<T>,
|
||||
internal val bufferStart: Int
|
||||
) : TensorStructure<T> {
|
||||
public val linearStructure: TensorLinearStructure
|
||||
@ -17,10 +17,10 @@ public open class BufferedTensor<T>(
|
||||
public val numElements: Int
|
||||
get() = linearStructure.size
|
||||
|
||||
override fun get(index: IntArray): T = buffer[bufferStart + linearStructure.offset(index)]
|
||||
override fun get(index: IntArray): T = mutableBuffer[bufferStart + linearStructure.offset(index)]
|
||||
|
||||
override fun set(index: IntArray, value: T) {
|
||||
buffer[bufferStart + linearStructure.offset(index)] = value
|
||||
mutableBuffer[bufferStart + linearStructure.offset(index)] = value
|
||||
}
|
||||
|
||||
override fun elements(): Sequence<Pair<IntArray, T>> = linearStructure.indices().map {
|
||||
@ -37,33 +37,28 @@ public class IntTensor internal constructor(
|
||||
shape: IntArray,
|
||||
buffer: IntArray,
|
||||
offset: Int = 0
|
||||
) : BufferedTensor<Int>(shape, IntBuffer(buffer), offset) {
|
||||
internal constructor(bufferedTensor: BufferedTensor<Int>) :
|
||||
this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart)
|
||||
}
|
||||
) : BufferedTensor<Int>(shape, IntBuffer(buffer), offset)
|
||||
|
||||
public class DoubleTensor internal constructor(
|
||||
shape: IntArray,
|
||||
buffer: DoubleArray,
|
||||
offset: Int = 0
|
||||
) : BufferedTensor<Double>(shape, DoubleBuffer(buffer), offset) {
|
||||
internal constructor(bufferedTensor: BufferedTensor<Double>) :
|
||||
this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart)
|
||||
|
||||
override fun toString(): String = toPrettyString()
|
||||
|
||||
}
|
||||
|
||||
internal inline fun BufferedTensor<Int>.asTensor(): IntTensor = IntTensor(this)
|
||||
internal inline fun BufferedTensor<Double>.asTensor(): DoubleTensor = DoubleTensor(this)
|
||||
internal fun BufferedTensor<Int>.asTensor(): IntTensor =
|
||||
IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart)
|
||||
internal fun BufferedTensor<Double>.asTensor(): DoubleTensor =
|
||||
DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart)
|
||||
|
||||
internal inline fun <T> TensorStructure<T>.copyToBufferedTensor(): BufferedTensor<T> =
|
||||
internal fun <T> TensorStructure<T>.copyToBufferedTensor(): BufferedTensor<T> =
|
||||
BufferedTensor(
|
||||
this.shape,
|
||||
TensorLinearStructure(this.shape).indices().map(this::get).toMutableList().asMutableBuffer(), 0
|
||||
)
|
||||
|
||||
internal inline fun <T> TensorStructure<T>.toBufferedTensor(): BufferedTensor<T> = when (this) {
|
||||
internal fun <T> TensorStructure<T>.toBufferedTensor(): BufferedTensor<T> = when (this) {
|
||||
is BufferedTensor<T> -> this
|
||||
is MutableBufferND<T> -> if (this.strides.strides.toIntArray() contentEquals TensorLinearStructure(this.shape).strides)
|
||||
BufferedTensor(this.shape, this.mutableBuffer, 0) else this.copyToBufferedTensor()
|
||||
|
@ -21,7 +21,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
|
||||
val newThis = broadcast[0]
|
||||
val newOther = broadcast[1]
|
||||
val resBuffer = DoubleArray(newThis.linearStructure.size) { i ->
|
||||
newThis.buffer.array()[i] + newOther.buffer.array()[i]
|
||||
newThis.mutableBuffer.array()[i] + newOther.mutableBuffer.array()[i]
|
||||
}
|
||||
return DoubleTensor(newThis.shape, resBuffer)
|
||||
}
|
||||
@ -29,8 +29,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
|
||||
override fun TensorStructure<Double>.plusAssign(other: TensorStructure<Double>) {
|
||||
val newOther = broadcastTo(other.tensor, tensor.shape)
|
||||
for (i in 0 until tensor.linearStructure.size) {
|
||||
tensor.buffer.array()[tensor.bufferStart + i] +=
|
||||
newOther.buffer.array()[tensor.bufferStart + i]
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] +=
|
||||
newOther.mutableBuffer.array()[tensor.bufferStart + i]
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
|
||||
val newThis = broadcast[0]
|
||||
val newOther = broadcast[1]
|
||||
val resBuffer = DoubleArray(newThis.linearStructure.size) { i ->
|
||||
newThis.buffer.array()[i] - newOther.buffer.array()[i]
|
||||
newThis.mutableBuffer.array()[i] - newOther.mutableBuffer.array()[i]
|
||||
}
|
||||
return DoubleTensor(newThis.shape, resBuffer)
|
||||
}
|
||||
@ -47,8 +47,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
|
||||
override fun TensorStructure<Double>.minusAssign(other: TensorStructure<Double>) {
|
||||
val newOther = broadcastTo(other.tensor, tensor.shape)
|
||||
for (i in 0 until tensor.linearStructure.size) {
|
||||
tensor.buffer.array()[tensor.bufferStart + i] -=
|
||||
newOther.buffer.array()[tensor.bufferStart + i]
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] -=
|
||||
newOther.mutableBuffer.array()[tensor.bufferStart + i]
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,8 +57,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
|
||||
val newThis = broadcast[0]
|
||||
val newOther = broadcast[1]
|
||||
val resBuffer = DoubleArray(newThis.linearStructure.size) { i ->
|
||||
newThis.buffer.array()[newThis.bufferStart + i] *
|
||||
newOther.buffer.array()[newOther.bufferStart + i]
|
||||
newThis.mutableBuffer.array()[newThis.bufferStart + i] *
|
||||
newOther.mutableBuffer.array()[newOther.bufferStart + i]
|
||||
}
|
||||
return DoubleTensor(newThis.shape, resBuffer)
|
||||
}
|
||||
@ -66,8 +66,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
|
||||
override fun TensorStructure<Double>.timesAssign(other: TensorStructure<Double>) {
|
||||
val newOther = broadcastTo(other.tensor, tensor.shape)
|
||||
for (i in 0 until tensor.linearStructure.size) {
|
||||
tensor.buffer.array()[tensor.bufferStart + i] *=
|
||||
newOther.buffer.array()[tensor.bufferStart + i]
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] *=
|
||||
newOther.mutableBuffer.array()[tensor.bufferStart + i]
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,8 +76,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
|
||||
val newThis = broadcast[0]
|
||||
val newOther = broadcast[1]
|
||||
val resBuffer = DoubleArray(newThis.linearStructure.size) { i ->
|
||||
newThis.buffer.array()[newOther.bufferStart + i] /
|
||||
newOther.buffer.array()[newOther.bufferStart + i]
|
||||
newThis.mutableBuffer.array()[newOther.bufferStart + i] /
|
||||
newOther.mutableBuffer.array()[newOther.bufferStart + i]
|
||||
}
|
||||
return DoubleTensor(newThis.shape, resBuffer)
|
||||
}
|
||||
@ -85,8 +85,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
|
||||
override fun TensorStructure<Double>.divAssign(other: TensorStructure<Double>) {
|
||||
val newOther = broadcastTo(other.tensor, tensor.shape)
|
||||
for (i in 0 until tensor.linearStructure.size) {
|
||||
tensor.buffer.array()[tensor.bufferStart + i] /=
|
||||
newOther.buffer.array()[tensor.bufferStart + i]
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] /=
|
||||
newOther.mutableBuffer.array()[tensor.bufferStart + i]
|
||||
}
|
||||
}
|
||||
}
|
@ -106,7 +106,7 @@ public object DoubleLinearOpsTensorAlgebra :
|
||||
val matrixSize = matrix.shape.reduce { acc, i -> acc * i }
|
||||
val curMatrix = DoubleTensor(
|
||||
matrix.shape,
|
||||
matrix.buffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize).toDoubleArray()
|
||||
matrix.mutableBuffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize).toDoubleArray()
|
||||
)
|
||||
svdHelper(curMatrix, USV, m, n, epsilon)
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||
check(tensor.shape contentEquals intArrayOf(1)) {
|
||||
"Inconsistent value for tensor of shape ${shape.toList()}"
|
||||
}
|
||||
return tensor.buffer.array()[tensor.bufferStart]
|
||||
return tensor.mutableBuffer.array()[tensor.bufferStart]
|
||||
}
|
||||
|
||||
public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor {
|
||||
@ -43,7 +43,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||
val lastShape = tensor.shape.drop(1).toIntArray()
|
||||
val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1)
|
||||
val newStart = newShape.reduce(Int::times) * i + tensor.bufferStart
|
||||
return DoubleTensor(newShape, tensor.buffer.array(), newStart)
|
||||
return DoubleTensor(newShape, tensor.mutableBuffer.array(), newStart)
|
||||
}
|
||||
|
||||
public fun full(value: Double, shape: IntArray): DoubleTensor {
|
||||
@ -77,12 +77,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||
}
|
||||
|
||||
public fun TensorStructure<Double>.copy(): DoubleTensor {
|
||||
return DoubleTensor(tensor.shape, tensor.buffer.array().copyOf(), tensor.bufferStart)
|
||||
return DoubleTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart)
|
||||
}
|
||||
|
||||
override fun Double.plus(other: TensorStructure<Double>): DoubleTensor {
|
||||
val resBuffer = DoubleArray(other.tensor.numElements) { i ->
|
||||
other.tensor.buffer.array()[other.tensor.bufferStart + i] + this
|
||||
other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] + this
|
||||
}
|
||||
return DoubleTensor(other.shape, resBuffer)
|
||||
}
|
||||
@ -92,35 +92,35 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||
override fun TensorStructure<Double>.plus(other: TensorStructure<Double>): DoubleTensor {
|
||||
checkShapesCompatible(tensor, other.tensor)
|
||||
val resBuffer = DoubleArray(tensor.numElements) { i ->
|
||||
tensor.buffer.array()[i] + other.tensor.buffer.array()[i]
|
||||
tensor.mutableBuffer.array()[i] + other.tensor.mutableBuffer.array()[i]
|
||||
}
|
||||
return DoubleTensor(tensor.shape, resBuffer)
|
||||
}
|
||||
|
||||
override fun TensorStructure<Double>.plusAssign(value: Double) {
|
||||
for (i in 0 until tensor.numElements) {
|
||||
tensor.buffer.array()[tensor.bufferStart + i] += value
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] += value
|
||||
}
|
||||
}
|
||||
|
||||
override fun TensorStructure<Double>.plusAssign(other: TensorStructure<Double>) {
|
||||
checkShapesCompatible(tensor, other.tensor)
|
||||
for (i in 0 until tensor.numElements) {
|
||||
tensor.buffer.array()[tensor.bufferStart + i] +=
|
||||
other.tensor.buffer.array()[tensor.bufferStart + i]
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] +=
|
||||
other.tensor.mutableBuffer.array()[tensor.bufferStart + i]
|
||||
}
|
||||
}
|
||||
|
||||
override fun Double.minus(other: TensorStructure<Double>): DoubleTensor {
|
||||
val resBuffer = DoubleArray(other.tensor.numElements) { i ->
|
||||
this - other.tensor.buffer.array()[other.tensor.bufferStart + i]
|
||||
this - other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i]
|
||||
}
|
||||
return DoubleTensor(other.shape, resBuffer)
|
||||
}
|
||||
|
||||
override fun TensorStructure<Double>.minus(value: Double): DoubleTensor {
|
||||
val resBuffer = DoubleArray(tensor.numElements) { i ->
|
||||
tensor.buffer.array()[tensor.bufferStart + i] - value
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] - value
|
||||
}
|
||||
return DoubleTensor(tensor.shape, resBuffer)
|
||||
}
|
||||
@ -128,28 +128,28 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||
override fun TensorStructure<Double>.minus(other: TensorStructure<Double>): DoubleTensor {
|
||||
checkShapesCompatible(tensor, other)
|
||||
val resBuffer = DoubleArray(tensor.numElements) { i ->
|
||||
tensor.buffer.array()[i] - other.tensor.buffer.array()[i]
|
||||
tensor.mutableBuffer.array()[i] - other.tensor.mutableBuffer.array()[i]
|
||||
}
|
||||
return DoubleTensor(tensor.shape, resBuffer)
|
||||
}
|
||||
|
||||
override fun TensorStructure<Double>.minusAssign(value: Double) {
|
||||
for (i in 0 until tensor.numElements) {
|
||||
tensor.buffer.array()[tensor.bufferStart + i] -= value
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] -= value
|
||||
}
|
||||
}
|
||||
|
||||
override fun TensorStructure<Double>.minusAssign(other: TensorStructure<Double>) {
|
||||
checkShapesCompatible(tensor, other)
|
||||
for (i in 0 until tensor.numElements) {
|
||||
tensor.buffer.array()[tensor.bufferStart + i] -=
|
||||
other.tensor.buffer.array()[tensor.bufferStart + i]
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] -=
|
||||
other.tensor.mutableBuffer.array()[tensor.bufferStart + i]
|
||||
}
|
||||
}
|
||||
|
||||
override fun Double.times(other: TensorStructure<Double>): DoubleTensor {
|
||||
val resBuffer = DoubleArray(other.tensor.numElements) { i ->
|
||||
other.tensor.buffer.array()[other.tensor.bufferStart + i] * this
|
||||
other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] * this
|
||||
}
|
||||
return DoubleTensor(other.shape, resBuffer)
|
||||
}
|
||||
@ -159,36 +159,36 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||
override fun TensorStructure<Double>.times(other: TensorStructure<Double>): DoubleTensor {
|
||||
checkShapesCompatible(tensor, other)
|
||||
val resBuffer = DoubleArray(tensor.numElements) { i ->
|
||||
tensor.buffer.array()[tensor.bufferStart + i] *
|
||||
other.tensor.buffer.array()[other.tensor.bufferStart + i]
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] *
|
||||
other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i]
|
||||
}
|
||||
return DoubleTensor(tensor.shape, resBuffer)
|
||||
}
|
||||
|
||||
override fun TensorStructure<Double>.timesAssign(value: Double) {
|
||||
for (i in 0 until tensor.numElements) {
|
||||
tensor.buffer.array()[tensor.bufferStart + i] *= value
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] *= value
|
||||
}
|
||||
}
|
||||
|
||||
override fun TensorStructure<Double>.timesAssign(other: TensorStructure<Double>) {
|
||||
checkShapesCompatible(tensor, other)
|
||||
for (i in 0 until tensor.numElements) {
|
||||
tensor.buffer.array()[tensor.bufferStart + i] *=
|
||||
other.tensor.buffer.array()[tensor.bufferStart + i]
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] *=
|
||||
other.tensor.mutableBuffer.array()[tensor.bufferStart + i]
|
||||
}
|
||||
}
|
||||
|
||||
override fun Double.div(other: TensorStructure<Double>): DoubleTensor {
|
||||
val resBuffer = DoubleArray(other.tensor.numElements) { i ->
|
||||
this / other.tensor.buffer.array()[other.tensor.bufferStart + i]
|
||||
this / other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i]
|
||||
}
|
||||
return DoubleTensor(other.shape, resBuffer)
|
||||
}
|
||||
|
||||
override fun TensorStructure<Double>.div(value: Double): DoubleTensor {
|
||||
val resBuffer = DoubleArray(tensor.numElements) { i ->
|
||||
tensor.buffer.array()[tensor.bufferStart + i] / value
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] / value
|
||||
}
|
||||
return DoubleTensor(shape, resBuffer)
|
||||
}
|
||||
@ -196,29 +196,29 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||
override fun TensorStructure<Double>.div(other: TensorStructure<Double>): DoubleTensor {
|
||||
checkShapesCompatible(tensor, other)
|
||||
val resBuffer = DoubleArray(tensor.numElements) { i ->
|
||||
tensor.buffer.array()[other.tensor.bufferStart + i] /
|
||||
other.tensor.buffer.array()[other.tensor.bufferStart + i]
|
||||
tensor.mutableBuffer.array()[other.tensor.bufferStart + i] /
|
||||
other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i]
|
||||
}
|
||||
return DoubleTensor(tensor.shape, resBuffer)
|
||||
}
|
||||
|
||||
override fun TensorStructure<Double>.divAssign(value: Double) {
|
||||
for (i in 0 until tensor.numElements) {
|
||||
tensor.buffer.array()[tensor.bufferStart + i] /= value
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] /= value
|
||||
}
|
||||
}
|
||||
|
||||
override fun TensorStructure<Double>.divAssign(other: TensorStructure<Double>) {
|
||||
checkShapesCompatible(tensor, other)
|
||||
for (i in 0 until tensor.numElements) {
|
||||
tensor.buffer.array()[tensor.bufferStart + i] /=
|
||||
other.tensor.buffer.array()[tensor.bufferStart + i]
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i] /=
|
||||
other.tensor.mutableBuffer.array()[tensor.bufferStart + i]
|
||||
}
|
||||
}
|
||||
|
||||
override fun TensorStructure<Double>.unaryMinus(): DoubleTensor {
|
||||
val resBuffer = DoubleArray(tensor.numElements) { i ->
|
||||
tensor.buffer.array()[tensor.bufferStart + i].unaryMinus()
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + i].unaryMinus()
|
||||
}
|
||||
return DoubleTensor(tensor.shape, resBuffer)
|
||||
}
|
||||
@ -241,8 +241,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||
newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] }
|
||||
|
||||
val linearIndex = resTensor.linearStructure.offset(newMultiIndex)
|
||||
resTensor.buffer.array()[linearIndex] =
|
||||
tensor.buffer.array()[tensor.bufferStart + offset]
|
||||
resTensor.mutableBuffer.array()[linearIndex] =
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + offset]
|
||||
}
|
||||
return resTensor
|
||||
}
|
||||
@ -250,7 +250,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||
|
||||
override fun TensorStructure<Double>.view(shape: IntArray): DoubleTensor {
|
||||
checkView(tensor, shape)
|
||||
return DoubleTensor(shape, tensor.buffer.array(), tensor.bufferStart)
|
||||
return DoubleTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart)
|
||||
}
|
||||
|
||||
override fun TensorStructure<Double>.viewAs(other: TensorStructure<Double>): DoubleTensor {
|
||||
@ -259,7 +259,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||
|
||||
override infix fun TensorStructure<Double>.dot(other: TensorStructure<Double>): DoubleTensor {
|
||||
if (tensor.shape.size == 1 && other.shape.size == 1) {
|
||||
return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.buffer.array().sum()))
|
||||
return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.mutableBuffer.array().sum()))
|
||||
}
|
||||
|
||||
var newThis = tensor.copy()
|
||||
@ -361,7 +361,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||
public fun TensorStructure<Double>.map(transform: (Double) -> Double): DoubleTensor {
|
||||
return DoubleTensor(
|
||||
tensor.shape,
|
||||
tensor.buffer.array().map { transform(it) }.toDoubleArray(),
|
||||
tensor.mutableBuffer.array().map { transform(it) }.toDoubleArray(),
|
||||
tensor.bufferStart
|
||||
)
|
||||
}
|
||||
@ -382,7 +382,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||
return false
|
||||
}
|
||||
for (i in 0 until n) {
|
||||
if (!eqFunction(tensor.buffer[tensor.bufferStart + i], other.tensor.buffer[other.tensor.bufferStart + i])) {
|
||||
if (!eqFunction(tensor.mutableBuffer[tensor.bufferStart + i], other.tensor.mutableBuffer[other.tensor.bufferStart + i])) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: Doub
|
||||
}
|
||||
|
||||
val curLinearIndex = tensor.linearStructure.offset(curMultiIndex)
|
||||
resTensor.buffer.array()[linearIndex] =
|
||||
tensor.buffer.array()[tensor.bufferStart + curLinearIndex]
|
||||
resTensor.mutableBuffer.array()[linearIndex] =
|
||||
tensor.mutableBuffer.array()[tensor.bufferStart + curLinearIndex]
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ internal inline fun broadcastOuterTensors(vararg tensors: DoubleTensor): List<Do
|
||||
var curMultiIndex = tensor.shape.sliceArray(0..tensor.shape.size - 3).copyOf()
|
||||
curMultiIndex = IntArray(totalMultiIndex.size - curMultiIndex.size) { 1 } + curMultiIndex
|
||||
|
||||
val newTensor = DoubleTensor(curMultiIndex + matrixShape, tensor.buffer.array())
|
||||
val newTensor = DoubleTensor(curMultiIndex + matrixShape, tensor.mutableBuffer.array())
|
||||
|
||||
for (i in curMultiIndex.indices) {
|
||||
if (curMultiIndex[i] != 1) {
|
||||
@ -133,8 +133,8 @@ internal inline fun broadcastOuterTensors(vararg tensors: DoubleTensor): List<Do
|
||||
matrix.linearStructure.index(i)
|
||||
)
|
||||
|
||||
resTensor.buffer.array()[resTensor.bufferStart + newLinearIndex] =
|
||||
newTensor.buffer.array()[newTensor.bufferStart + curLinearIndex]
|
||||
resTensor.mutableBuffer.array()[resTensor.bufferStart + newLinearIndex] =
|
||||
newTensor.mutableBuffer.array()[newTensor.bufferStart + curLinearIndex]
|
||||
}
|
||||
}
|
||||
res += resTensor
|
||||
|
@ -18,7 +18,7 @@ internal inline fun <T> BufferedTensor<T>.vectorSequence(): Sequence<BufferedTen
|
||||
val vectorOffset = shape[n - 1]
|
||||
val vectorShape = intArrayOf(shape.last())
|
||||
for (offset in 0 until numElements step vectorOffset) {
|
||||
val vector = BufferedTensor(vectorShape, buffer, offset)
|
||||
val vector = BufferedTensor(vectorShape, mutableBuffer, offset)
|
||||
yield(vector)
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,7 @@ internal inline fun <T> BufferedTensor<T>.matrixSequence(): Sequence<BufferedTen
|
||||
val matrixOffset = shape[n - 1] * shape[n - 2]
|
||||
val matrixShape = intArrayOf(shape[n - 2], shape[n - 1])
|
||||
for (offset in 0 until numElements step matrixOffset) {
|
||||
val matrix = BufferedTensor(matrixShape, buffer, offset)
|
||||
val matrix = BufferedTensor(matrixShape, mutableBuffer, offset)
|
||||
yield(matrix)
|
||||
}
|
||||
}
|
||||
@ -322,16 +322,16 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper(
|
||||
}
|
||||
|
||||
val s = res.map { it.first }.toDoubleArray()
|
||||
val uBuffer = res.map { it.second }.flatMap { it.buffer.array().toList() }.toDoubleArray()
|
||||
val vBuffer = res.map { it.third }.flatMap { it.buffer.array().toList() }.toDoubleArray()
|
||||
val uBuffer = res.map { it.second }.flatMap { it.mutableBuffer.array().toList() }.toDoubleArray()
|
||||
val vBuffer = res.map { it.third }.flatMap { it.mutableBuffer.array().toList() }.toDoubleArray()
|
||||
for (i in uBuffer.indices) {
|
||||
matrixU.buffer.array()[matrixU.bufferStart + i] = uBuffer[i]
|
||||
matrixU.mutableBuffer.array()[matrixU.bufferStart + i] = uBuffer[i]
|
||||
}
|
||||
for (i in s.indices) {
|
||||
matrixS.buffer.array()[matrixS.bufferStart + i] = s[i]
|
||||
matrixS.mutableBuffer.array()[matrixS.bufferStart + i] = s[i]
|
||||
}
|
||||
for (i in vBuffer.indices) {
|
||||
matrixV.buffer.array()[matrixV.bufferStart + i] = vBuffer[i]
|
||||
matrixV.mutableBuffer.array()[matrixV.bufferStart + i] = vBuffer[i]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ internal class TestBroadcasting {
|
||||
|
||||
val res = broadcastTo(tensor2, tensor1.shape)
|
||||
assertTrue(res.shape contentEquals intArrayOf(2, 3))
|
||||
assertTrue(res.buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0))
|
||||
assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -45,9 +45,9 @@ internal class TestBroadcasting {
|
||||
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].mutableBuffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||
assertTrue(res[1].mutableBuffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0))
|
||||
assertTrue(res[2].mutableBuffer.array() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -62,9 +62,9 @@ internal class TestBroadcasting {
|
||||
assertTrue(res[1].shape contentEquals intArrayOf(1, 1, 3))
|
||||
assertTrue(res[2].shape contentEquals intArrayOf(1, 1, 1))
|
||||
|
||||
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))
|
||||
assertTrue(res[2].buffer.array() contentEquals doubleArrayOf(500.0))
|
||||
assertTrue(res[0].mutableBuffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||
assertTrue(res[1].mutableBuffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0))
|
||||
assertTrue(res[2].mutableBuffer.array() contentEquals doubleArrayOf(500.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -91,16 +91,16 @@ internal class TestBroadcasting {
|
||||
val tensor32 = tensor3 - tensor2
|
||||
|
||||
assertTrue(tensor21.shape contentEquals intArrayOf(2, 3))
|
||||
assertTrue(tensor21.buffer.array() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0))
|
||||
assertTrue(tensor21.mutableBuffer.array() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0))
|
||||
|
||||
assertTrue(tensor31.shape contentEquals intArrayOf(1, 2, 3))
|
||||
assertTrue(
|
||||
tensor31.buffer.array()
|
||||
tensor31.mutableBuffer.array()
|
||||
contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0)
|
||||
)
|
||||
|
||||
assertTrue(tensor32.shape contentEquals intArrayOf(1, 1, 3))
|
||||
assertTrue(tensor32.buffer.array() contentEquals doubleArrayOf(490.0, 480.0, 470.0))
|
||||
assertTrue(tensor32.mutableBuffer.array() contentEquals doubleArrayOf(490.0, 480.0, 470.0))
|
||||
}
|
||||
|
||||
}
|
@ -30,7 +30,7 @@ internal class TestDoubleAnalyticTensorAlgebra {
|
||||
fun testExp() = DoubleAnalyticTensorAlgebra.invoke {
|
||||
tensor.exp().let {
|
||||
assertTrue { shape contentEquals it.shape }
|
||||
assertTrue { buffer.fmap(::exp).epsEqual(it.buffer.array())}
|
||||
assertTrue { buffer.fmap(::exp).epsEqual(it.mutableBuffer.array())}
|
||||
}
|
||||
}
|
||||
}
|
@ -151,8 +151,8 @@ internal class TestDoubleLinearOpsTensorAlgebra {
|
||||
val res = svd1d(tensor2)
|
||||
|
||||
assertTrue(res.shape contentEquals intArrayOf(2))
|
||||
assertTrue { abs(abs(res.buffer.array()[res.bufferStart]) - 0.386) < 0.01 }
|
||||
assertTrue { abs(abs(res.buffer.array()[res.bufferStart + 1]) - 0.922) < 0.01 }
|
||||
assertTrue { abs(abs(res.mutableBuffer.array()[res.bufferStart]) - 0.386) < 0.01 }
|
||||
assertTrue { abs(abs(res.mutableBuffer.array()[res.bufferStart + 1]) - 0.922) < 0.01 }
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -6,7 +6,6 @@ import space.kscience.kmath.nd.as1D
|
||||
import space.kscience.kmath.nd.as2D
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.structures.DoubleBuffer
|
||||
import space.kscience.kmath.structures.asMutableBuffer
|
||||
import space.kscience.kmath.structures.toDoubleArray
|
||||
import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra
|
||||
import kotlin.test.Test
|
||||
@ -27,7 +26,7 @@ internal class TestDoubleTensor {
|
||||
val tensor = fromArray(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.toDoubleArray()
|
||||
tensor.elements().map { it.second }.toList().toDoubleArray() contentEquals tensor.mutableBuffer.toDoubleArray()
|
||||
)
|
||||
}
|
||||
|
||||
@ -71,7 +70,7 @@ internal class TestDoubleTensor {
|
||||
val tensorArrayPublic = ndArray.toTypedTensor() // public API, data copied twice
|
||||
val sharedTensorArray = tensorArrayPublic.toTypedTensor() // no data copied by matching type
|
||||
|
||||
assertTrue(tensorArray.buffer.array() contentEquals sharedTensorArray.buffer.array())
|
||||
assertTrue(tensorArray.mutableBuffer.array() contentEquals sharedTensorArray.mutableBuffer.array())
|
||||
|
||||
tensorArray[intArrayOf(0)] = 55.9
|
||||
assertEquals(tensorArrayPublic[intArrayOf(0)], 1.0)
|
||||
|
@ -13,21 +13,21 @@ internal class TestDoubleTensorAlgebra {
|
||||
fun doublePlus() = DoubleTensorAlgebra.invoke {
|
||||
val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0))
|
||||
val res = 10.0 + tensor
|
||||
assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0, 12.0))
|
||||
assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(11.0, 12.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doubleDiv() = DoubleTensorAlgebra.invoke {
|
||||
val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0))
|
||||
val res = 2.0/tensor
|
||||
assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 0.5))
|
||||
assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 0.5))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun divDouble() = DoubleTensorAlgebra.invoke {
|
||||
val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0))
|
||||
val res = tensor / 2.5
|
||||
assertTrue(res.buffer.array() contentEquals doubleArrayOf(4.0, 2.0))
|
||||
assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(4.0, 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -35,7 +35,7 @@ internal class TestDoubleTensorAlgebra {
|
||||
val tensor = fromArray(intArrayOf(1), doubleArrayOf(0.0))
|
||||
val res = tensor.transpose(0, 0)
|
||||
|
||||
assertTrue(res.buffer.array() contentEquals doubleArrayOf(0.0))
|
||||
assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(0.0))
|
||||
assertTrue(res.shape contentEquals intArrayOf(1))
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ internal class TestDoubleTensorAlgebra {
|
||||
val tensor = fromArray(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.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0))
|
||||
assertTrue(res.shape contentEquals intArrayOf(2, 3))
|
||||
}
|
||||
|
||||
@ -59,9 +59,9 @@ internal class TestDoubleTensorAlgebra {
|
||||
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.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||
assertTrue(res02.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0))
|
||||
assertTrue(res12.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -92,8 +92,8 @@ internal class TestDoubleTensorAlgebra {
|
||||
assignResult += tensorC
|
||||
assignResult += -39.4
|
||||
|
||||
assertTrue(expected.buffer.array() contentEquals result.buffer.array())
|
||||
assertTrue(expected.buffer.array() contentEquals assignResult.buffer.array())
|
||||
assertTrue(expected.mutableBuffer.array() contentEquals result.mutableBuffer.array())
|
||||
assertTrue(expected.mutableBuffer.array() contentEquals assignResult.mutableBuffer.array())
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -104,19 +104,19 @@ internal class TestDoubleTensorAlgebra {
|
||||
val tensor3 = fromArray(intArrayOf(1, 1, 3), doubleArrayOf(-1.0, -2.0, -3.0))
|
||||
|
||||
val res12 = tensor1.dot(tensor2)
|
||||
assertTrue(res12.buffer.array() contentEquals doubleArrayOf(140.0, 320.0))
|
||||
assertTrue(res12.mutableBuffer.array() contentEquals doubleArrayOf(140.0, 320.0))
|
||||
assertTrue(res12.shape contentEquals intArrayOf(2))
|
||||
|
||||
val res32 = tensor3.dot(tensor2)
|
||||
assertTrue(res32.buffer.array() contentEquals doubleArrayOf(-140.0))
|
||||
assertTrue(res32.mutableBuffer.array() contentEquals doubleArrayOf(-140.0))
|
||||
assertTrue(res32.shape contentEquals intArrayOf(1, 1))
|
||||
|
||||
val res22 = tensor2.dot(tensor2)
|
||||
assertTrue(res22.buffer.array() contentEquals doubleArrayOf(1400.0))
|
||||
assertTrue(res22.mutableBuffer.array() contentEquals doubleArrayOf(1400.0))
|
||||
assertTrue(res22.shape contentEquals intArrayOf(1))
|
||||
|
||||
val res11 = tensor1.dot(tensor11)
|
||||
assertTrue(res11.buffer.array() contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0))
|
||||
assertTrue(res11.mutableBuffer.array() contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0))
|
||||
assertTrue(res11.shape contentEquals intArrayOf(2, 2))
|
||||
|
||||
var tensor4 = fromArray(intArrayOf(10, 3, 4), DoubleArray(10 * 3 * 4) {0.0})
|
||||
@ -147,17 +147,17 @@ internal class TestDoubleTensorAlgebra {
|
||||
|
||||
val diagonal1 = diagonalEmbedding(tensor1, 0, 1, 0)
|
||||
assertTrue(diagonal1.shape contentEquals intArrayOf(3, 3))
|
||||
assertTrue(diagonal1.buffer.array() contentEquals
|
||||
assertTrue(diagonal1.mutableBuffer.array() contentEquals
|
||||
doubleArrayOf(10.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 30.0))
|
||||
|
||||
val diagonal1Offset = diagonalEmbedding(tensor1, 1, 1, 0)
|
||||
assertTrue(diagonal1Offset.shape contentEquals intArrayOf(4, 4))
|
||||
assertTrue(diagonal1Offset.buffer.array() contentEquals
|
||||
assertTrue(diagonal1Offset.mutableBuffer.array() contentEquals
|
||||
doubleArrayOf(0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 30.0, 0.0))
|
||||
|
||||
val diagonal2 = diagonalEmbedding(tensor2, 1, 0, 2)
|
||||
assertTrue(diagonal2.shape contentEquals intArrayOf(4, 2, 4))
|
||||
assertTrue(diagonal2.buffer.array() contentEquals
|
||||
assertTrue(diagonal2.mutableBuffer.array() contentEquals
|
||||
doubleArrayOf(
|
||||
0.0, 1.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0,
|
||||
0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 5.0, 0.0,
|
||||
|
Loading…
Reference in New Issue
Block a user