From 499cf85ff08ac65e7343e33af2f4f65cd9967b3f Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Thu, 6 May 2021 12:30:13 +0300 Subject: [PATCH] refactor BT + docs --- .../kmath/tensors/core/BufferedTensor.kt | 112 ++++-------------- .../kmath/tensors/core/DoubleTensor.kt | 19 +++ .../kscience/kmath/tensors/core/IntTensor.kt | 17 +++ .../kmath/tensors/core/tensorCasts.kt | 36 ++++++ .../kmath/tensors/core/tensorCastsUtils.kt | 42 +++++++ 5 files changed, 136 insertions(+), 90 deletions(-) create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 22a1ef1bf..e4ffccd96 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,116 +1,48 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure - -public open class BufferedTensor( +/** + * [Tensor] implementation provided with [MutableBuffer] + */ +public open class BufferedTensor internal constructor( override val shape: IntArray, internal val mutableBuffer: MutableBuffer, internal val bufferStart: Int ) : Tensor { + + /** + * [TensorLinearStructure] with the same shape + */ public val linearStructure: TensorLinearStructure get() = TensorLinearStructure(shape) + /** + * Number of elements in tensor + */ public val numElements: Int get() = linearStructure.linearSize + /** + * @param index [IntArray] with size equal to tensor dimension + * @return the element by multidimensional index + */ override fun get(index: IntArray): T = mutableBuffer[bufferStart + linearStructure.offset(index)] + /** + * @param index the [IntArray] with size equal to tensor dimension + * @param value the value to set + */ override fun set(index: IntArray, value: T) { mutableBuffer[bufferStart + linearStructure.offset(index)] = value } + /** + * @return the sequence of pairs multidimensional indices and values + */ override fun elements(): Sequence> = linearStructure.indices().map { it to this[it] } } - -public class IntTensor internal constructor( - shape: IntArray, - buffer: IntArray, - offset: Int = 0 -) : BufferedTensor(shape, IntBuffer(buffer), offset) - -public class DoubleTensor internal constructor( - shape: IntArray, - buffer: DoubleArray, - offset: Int = 0 -) : BufferedTensor(shape, DoubleBuffer(buffer), offset) { - override fun toString(): String = toPrettyString() -} - -internal fun BufferedTensor.asTensor(): IntTensor = - IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) - -internal fun BufferedTensor.asTensor(): DoubleTensor = - DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) - -internal fun Tensor.copyToBufferedTensor(): BufferedTensor = - BufferedTensor( - this.shape, - TensorLinearStructure(this.shape).indices().map(this::get).toMutableList().asMutableBuffer(), 0 - ) - -internal fun Tensor.toBufferedTensor(): BufferedTensor = when (this) { - is BufferedTensor -> this - is MutableBufferND -> if (this.strides.strides contentEquals TensorLinearStructure(this.shape).strides) - BufferedTensor(this.shape, this.mutableBuffer, 0) else this.copyToBufferedTensor() - else -> this.copyToBufferedTensor() -} - -internal val Tensor.tensor: DoubleTensor - get() = when (this) { - is DoubleTensor -> this - else -> this.toBufferedTensor().asTensor() - } - -internal val Tensor.tensor: IntTensor - get() = when (this) { - is IntTensor -> this - else -> this.toBufferedTensor().asTensor() - } - -public fun Tensor.toDoubleTensor(): DoubleTensor = this.tensor -public fun Tensor.toIntTensor(): IntTensor = this.tensor - -public fun Array.toDoubleTensor(): DoubleTensor { - val n = size - check(n > 0) { "An empty array cannot be casted to tensor" } - val m = first().size - check(m > 0) { "Inner arrays must have at least 1 argument" } - check(all { size == m }) { "Inner arrays must be the same size" } - - val shape = intArrayOf(n, m) - val buffer = this.flatMap { arr -> arr.map { it } }.toDoubleArray() - - return DoubleTensor(shape, buffer, 0) -} - - -public fun Array.toIntTensor(): IntTensor { - val n = size - check(n > 0) { "An empty array cannot be casted to tensor" } - val m = first().size - check(m > 0) { "Inner arrays must have at least 1 argument" } - check(all { size == m }) { "Inner arrays must be the same size" } - - val shape = intArrayOf(n, m) - val buffer = this.flatMap { arr -> arr.map { it } }.toIntArray() - - return IntTensor(shape, buffer, 0) -} - -public fun DoubleTensor.toDoubleArray(): DoubleArray { - return DoubleArray(numElements) { i -> - mutableBuffer[bufferStart + i] - } -} - -public fun IntTensor.toIntArray(): IntArray { - return IntArray(numElements) { i -> - mutableBuffer[bufferStart + i] - } -} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt new file mode 100644 index 000000000..e3143f5a7 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2018-2021 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.tensors.core + +import space.kscience.kmath.structures.DoubleBuffer + +/** + * Default [BufferedTensor] implementation for [Double] values + */ +public class DoubleTensor internal constructor( + shape: IntArray, + buffer: DoubleArray, + offset: Int = 0 +) : BufferedTensor(shape, DoubleBuffer(buffer), offset) { + override fun toString(): String = toPrettyString() +} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt new file mode 100644 index 000000000..ae1e6c8c8 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2018-2021 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.tensors.core + +import space.kscience.kmath.structures.IntBuffer + +/** + * Default [BufferedTensor] implementation for [Int] values + */ +public class IntTensor internal constructor( + shape: IntArray, + buffer: IntArray, + offset: Int = 0 +) : BufferedTensor(shape, IntBuffer(buffer), offset) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt new file mode 100644 index 000000000..6254ce751 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2018-2021 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.tensors.core + +import space.kscience.kmath.tensors.api.Tensor + +/** + * Casts [Tensor] to [DoubleTensor] + */ +public fun Tensor.toDoubleTensor(): DoubleTensor = this.tensor + +/** + * Casts [Tensor] to [IntTensor] + */ +public fun Tensor.toIntTensor(): IntTensor = this.tensor + +/** + * @return [DoubleArray] of tensor elements + */ +public fun DoubleTensor.toDoubleArray(): DoubleArray { + return DoubleArray(numElements) { i -> + mutableBuffer[bufferStart + i] + } +} + +/** + * @return [IntArray] of tensor elements + */ +public fun IntTensor.toIntArray(): IntArray { + return IntArray(numElements) { i -> + mutableBuffer[bufferStart + i] + } +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt new file mode 100644 index 000000000..31de6919f --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2018-2021 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.tensors.core + +import space.kscience.kmath.nd.MutableBufferND +import space.kscience.kmath.structures.asMutableBuffer +import space.kscience.kmath.tensors.api.Tensor +import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure + +internal fun BufferedTensor.asTensor(): IntTensor = + IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) + +internal fun BufferedTensor.asTensor(): DoubleTensor = + DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) + +internal fun Tensor.copyToBufferedTensor(): BufferedTensor = + BufferedTensor( + this.shape, + TensorLinearStructure(this.shape).indices().map(this::get).toMutableList().asMutableBuffer(), 0 + ) + +internal fun Tensor.toBufferedTensor(): BufferedTensor = when (this) { + is BufferedTensor -> this + is MutableBufferND -> if (this.strides.strides contentEquals TensorLinearStructure(this.shape).strides) + BufferedTensor(this.shape, this.mutableBuffer, 0) else this.copyToBufferedTensor() + else -> this.copyToBufferedTensor() +} + +internal val Tensor.tensor: DoubleTensor + get() = when (this) { + is DoubleTensor -> this + else -> this.toBufferedTensor().asTensor() + } + +internal val Tensor.tensor: IntTensor + get() = when (this) { + is IntTensor -> this + else -> this.toBufferedTensor().asTensor() + } \ No newline at end of file