diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index e412ab5bb..afa03d5a7 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -27,7 +27,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> - newThis.mutableBuffer.array()[i] + newOther.mutableBuffer.array()[i] + newThis.mutableBuffer[i] + newOther.mutableBuffer[i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -35,8 +35,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun Tensor.plusAssign(arg: StructureND) { val newOther = broadcastTo(arg.tensor, tensor.shape) for (i in 0 until tensor.indices.linearSize) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] += - newOther.mutableBuffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer[tensor.bufferStart + i] += + newOther.mutableBuffer[tensor.bufferStart + i] } } @@ -45,7 +45,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> - newThis.mutableBuffer.array()[i] - newOther.mutableBuffer.array()[i] + newThis.mutableBuffer[i] - newOther.mutableBuffer[i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -53,8 +53,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun Tensor.minusAssign(arg: StructureND) { val newOther = broadcastTo(arg.tensor, tensor.shape) for (i in 0 until tensor.indices.linearSize) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] -= - newOther.mutableBuffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer[tensor.bufferStart + i] -= + newOther.mutableBuffer[tensor.bufferStart + i] } } @@ -63,8 +63,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> - newThis.mutableBuffer.array()[newThis.bufferStart + i] * - newOther.mutableBuffer.array()[newOther.bufferStart + i] + newThis.mutableBuffer[newThis.bufferStart + i] * + newOther.mutableBuffer[newOther.bufferStart + i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -72,8 +72,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun Tensor.timesAssign(arg: StructureND) { val newOther = broadcastTo(arg.tensor, tensor.shape) for (i in 0 until tensor.indices.linearSize) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] *= - newOther.mutableBuffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer[tensor.bufferStart + i] *= + newOther.mutableBuffer[tensor.bufferStart + i] } } @@ -82,8 +82,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> - newThis.mutableBuffer.array()[newOther.bufferStart + i] / - newOther.mutableBuffer.array()[newOther.bufferStart + i] + newThis.mutableBuffer[newOther.bufferStart + i] / + newOther.mutableBuffer[newOther.bufferStart + i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -91,8 +91,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun Tensor.divAssign(arg: StructureND) { val newOther = broadcastTo(arg.tensor, tensor.shape) for (i in 0 until tensor.indices.linearSize) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] /= - newOther.mutableBuffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer[tensor.bufferStart + i] /= + newOther.mutableBuffer[tensor.bufferStart + i] } } } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index d83c70bd9..9e1c3942c 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -89,7 +89,7 @@ public open class DoubleTensorAlgebra : } override fun StructureND.valueOrNull(): Double? = if (tensor.shape contentEquals intArrayOf(1)) - tensor.mutableBuffer.array()[tensor.bufferStart] else null + tensor.mutableBuffer[tensor.bufferStart] else null override fun StructureND.value(): Double = valueOrNull() ?: throw IllegalArgumentException("The tensor shape is $shape, but value method is allowed only for shape [1]") @@ -208,7 +208,7 @@ public open class DoubleTensorAlgebra : override fun Double.plus(arg: StructureND): DoubleTensor { val resBuffer = DoubleArray(arg.tensor.numElements) { i -> - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + this + arg.tensor.mutableBuffer[arg.tensor.bufferStart + i] + this } return DoubleTensor(arg.shape, resBuffer) } @@ -218,35 +218,35 @@ public open class DoubleTensorAlgebra : override fun StructureND.plus(arg: StructureND): DoubleTensor { checkShapesCompatible(tensor, arg.tensor) val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[i] + arg.tensor.mutableBuffer.array()[i] + tensor.mutableBuffer[i] + arg.tensor.mutableBuffer[i] } return DoubleTensor(tensor.shape, resBuffer) } override fun Tensor.plusAssign(value: Double) { for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] += value + tensor.mutableBuffer[tensor.bufferStart + i] += value } } override fun Tensor.plusAssign(arg: StructureND) { checkShapesCompatible(tensor, arg.tensor) for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] += - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer[tensor.bufferStart + i] += + arg.tensor.mutableBuffer[tensor.bufferStart + i] } } override fun Double.minus(arg: StructureND): DoubleTensor { val resBuffer = DoubleArray(arg.tensor.numElements) { i -> - this - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + this - arg.tensor.mutableBuffer[arg.tensor.bufferStart + i] } return DoubleTensor(arg.shape, resBuffer) } override fun StructureND.minus(arg: Double): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i] - arg + tensor.mutableBuffer[tensor.bufferStart + i] - arg } return DoubleTensor(tensor.shape, resBuffer) } @@ -254,28 +254,28 @@ public open class DoubleTensorAlgebra : override fun StructureND.minus(arg: StructureND): DoubleTensor { checkShapesCompatible(tensor, arg) val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[i] - arg.tensor.mutableBuffer.array()[i] + tensor.mutableBuffer[i] - arg.tensor.mutableBuffer[i] } return DoubleTensor(tensor.shape, resBuffer) } override fun Tensor.minusAssign(value: Double) { for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] -= value + tensor.mutableBuffer[tensor.bufferStart + i] -= value } } override fun Tensor.minusAssign(arg: StructureND) { checkShapesCompatible(tensor, arg) for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] -= - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer[tensor.bufferStart + i] -= + arg.tensor.mutableBuffer[tensor.bufferStart + i] } } override fun Double.times(arg: StructureND): DoubleTensor { val resBuffer = DoubleArray(arg.tensor.numElements) { i -> - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] * this + arg.tensor.mutableBuffer[arg.tensor.bufferStart + i] * this } return DoubleTensor(arg.shape, resBuffer) } @@ -285,36 +285,36 @@ public open class DoubleTensorAlgebra : override fun StructureND.times(arg: StructureND): DoubleTensor { checkShapesCompatible(tensor, arg) val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i] * - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + tensor.mutableBuffer[tensor.bufferStart + i] * + arg.tensor.mutableBuffer[arg.tensor.bufferStart + i] } return DoubleTensor(tensor.shape, resBuffer) } override fun Tensor.timesAssign(value: Double) { for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] *= value + tensor.mutableBuffer[tensor.bufferStart + i] *= value } } override fun Tensor.timesAssign(arg: StructureND) { checkShapesCompatible(tensor, arg) for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] *= - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer[tensor.bufferStart + i] *= + arg.tensor.mutableBuffer[tensor.bufferStart + i] } } override fun Double.div(arg: StructureND): DoubleTensor { val resBuffer = DoubleArray(arg.tensor.numElements) { i -> - this / arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + this / arg.tensor.mutableBuffer[arg.tensor.bufferStart + i] } return DoubleTensor(arg.shape, resBuffer) } override fun StructureND.div(arg: Double): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i] / arg + tensor.mutableBuffer[tensor.bufferStart + i] / arg } return DoubleTensor(shape, resBuffer) } @@ -322,29 +322,29 @@ public open class DoubleTensorAlgebra : override fun StructureND.div(arg: StructureND): DoubleTensor { checkShapesCompatible(tensor, arg) val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] / - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + tensor.mutableBuffer[arg.tensor.bufferStart + i] / + arg.tensor.mutableBuffer[arg.tensor.bufferStart + i] } return DoubleTensor(tensor.shape, resBuffer) } override fun Tensor.divAssign(value: Double) { for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] /= value + tensor.mutableBuffer[tensor.bufferStart + i] /= value } } override fun Tensor.divAssign(arg: StructureND) { checkShapesCompatible(tensor, arg) for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] /= - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer[tensor.bufferStart + i] /= + arg.tensor.mutableBuffer[tensor.bufferStart + i] } } override fun StructureND.unaryMinus(): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i].unaryMinus() + tensor.mutableBuffer[tensor.bufferStart + i].unaryMinus() } return DoubleTensor(tensor.shape, resBuffer) } @@ -367,8 +367,8 @@ public open class DoubleTensorAlgebra : newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } val linearIndex = resTensor.indices.offset(newMultiIndex) - resTensor.mutableBuffer.array()[linearIndex] = - tensor.mutableBuffer.array()[tensor.bufferStart + offset] + resTensor.mutableBuffer[linearIndex] = + tensor.mutableBuffer[tensor.bufferStart + offset] } return resTensor } @@ -958,18 +958,21 @@ public open class DoubleTensorAlgebra : var eigenvalueStart = 0 var eigenvectorStart = 0 + val eigenvaluesBuffer = eigenvalues.mutableBuffer + val eigenvectorsBuffer = eigenvectors.mutableBuffer + for (matrix in tensor.matrixSequence()) { val matrix2D = matrix.as2D() val (d, v) = matrix2D.jacobiHelper(maxIteration, epsilon) for (i in 0 until matrix2D.rowNum) { for (j in 0 until matrix2D.colNum) { - eigenvectors.mutableBuffer.array()[eigenvectorStart + i * matrix2D.rowNum + j] = v[i, j] + eigenvectorsBuffer[eigenvectorStart + i * matrix2D.rowNum + j] = v[i, j] } } for (i in 0 until matrix2D.rowNum) { - eigenvalues.mutableBuffer.array()[eigenvalueStart + i] = d[i] + eigenvaluesBuffer[eigenvalueStart + i] = d[i] } eigenvalueStart += this.shape.last() @@ -992,11 +995,11 @@ public open class DoubleTensorAlgebra : // assume that buffered tensor is square matrix operator fun BufferedTensor.get(i: Int, j: Int): Double { - return this.mutableBuffer.array()[bufferStart + i * this.shape[0] + j] + return this.mutableBuffer[bufferStart + i * this.shape[0] + j] } operator fun BufferedTensor.set(i: Int, j: Int, value: Double) { - this.mutableBuffer.array()[bufferStart + i * this.shape[0] + j] = value + this.mutableBuffer[bufferStart + i * this.shape[0] + j] = value } fun maxOffDiagonal(matrix: BufferedTensor): Double { diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 6c502eed1..87050c405 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -156,9 +156,12 @@ internal class TestDoubleLinearOpsTensorAlgebra { val res = svd1d(tensor2) + val resBuffer = res.mutableBuffer + val resStart = res.bufferStart + assertTrue(res.shape contentEquals intArrayOf(2)) - 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 } + assertTrue { abs(abs(resBuffer[resStart]) - 0.386) < 0.01 } + assertTrue { abs(abs(resBuffer[resStart + 1]) - 0.922) < 0.01 } } @Test