fix sequences + array casting #306

Merged
AndreiKingsley merged 2 commits from andrew into feature/tensor-algebra 2021-05-01 14:33:37 +03:00
3 changed files with 60 additions and 4 deletions

View File

@ -49,6 +49,7 @@ public class DoubleTensor internal constructor(
internal fun BufferedTensor<Int>.asTensor(): IntTensor = internal fun BufferedTensor<Int>.asTensor(): IntTensor =
IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart)
internal fun BufferedTensor<Double>.asTensor(): DoubleTensor = internal fun BufferedTensor<Double>.asTensor(): DoubleTensor =
DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart)
@ -78,4 +79,39 @@ internal val TensorStructure<Int>.tensor: IntTensor
} }
public fun TensorStructure<Double>.toDoubleTensor(): DoubleTensor = this.tensor public fun TensorStructure<Double>.toDoubleTensor(): DoubleTensor = this.tensor
public fun TensorStructure<Int>.toIntTensor(): IntTensor = this.tensor public fun TensorStructure<Int>.toIntTensor(): IntTensor = this.tensor
public fun Array<DoubleArray>.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<IntArray>.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 tensor.mutableBuffer.array().drop(bufferStart).take(numElements).toDoubleArray()
}
public fun IntTensor.toIntArray(): IntArray {
return tensor.mutableBuffer.array().drop(bufferStart).take(numElements).toIntArray()
}

View File

@ -382,7 +382,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
return false return false
} }
for (i in 0 until n) { for (i in 0 until n) {
if (!eqFunction(tensor.mutableBuffer[tensor.bufferStart + i], other.tensor.mutableBuffer[other.tensor.bufferStart + i])) { if (!eqFunction(
tensor.mutableBuffer[tensor.bufferStart + i],
other.tensor.mutableBuffer[other.tensor.bufferStart + i]
)
) {
return false return false
} }
} }
@ -395,4 +399,20 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
public fun TensorStructure<Double>.randNormalLike(seed: Long = 0): DoubleTensor = public fun TensorStructure<Double>.randNormalLike(seed: Long = 0): DoubleTensor =
DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed))
// stack tensors by axis 0
public fun stack(tensors: List<DoubleTensor>): DoubleTensor {
val shape = tensors.firstOrNull()?.shape
check(shape != null) { "Collection must have at least 1 element" }
check(tensors.all { it.shape contentEquals shape }) {"Stacking tensors must have same shapes"}
val resShape = intArrayOf(tensors.size) + shape
val resBuffer = tensors.flatMap {
it.tensor.mutableBuffer.array().drop(it.bufferStart).take(it.numElements)
}.toDoubleArray()
return DoubleTensor(resShape, resBuffer, 0)
}
// build tensor from this rows by given indices
public fun TensorStructure<Double>.rowsByIndices(indices: IntArray): DoubleTensor {
return stack(indices.map { this[it] })
}
} }

View File

@ -18,7 +18,7 @@ internal fun <T> BufferedTensor<T>.vectorSequence(): Sequence<BufferedTensor<T>>
val vectorOffset = shape[n - 1] val vectorOffset = shape[n - 1]
val vectorShape = intArrayOf(shape.last()) val vectorShape = intArrayOf(shape.last())
for (offset in 0 until numElements step vectorOffset) { for (offset in 0 until numElements step vectorOffset) {
val vector = BufferedTensor(vectorShape, mutableBuffer, offset) val vector = BufferedTensor(vectorShape, mutableBuffer, bufferStart + offset)
yield(vector) yield(vector)
} }
} }
@ -29,7 +29,7 @@ internal fun <T> BufferedTensor<T>.matrixSequence(): Sequence<BufferedTensor<T>>
val matrixOffset = shape[n - 1] * shape[n - 2] val matrixOffset = shape[n - 1] * shape[n - 2]
val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) val matrixShape = intArrayOf(shape[n - 2], shape[n - 1])
for (offset in 0 until numElements step matrixOffset) { for (offset in 0 until numElements step matrixOffset) {
val matrix = BufferedTensor(matrixShape, mutableBuffer, offset) val matrix = BufferedTensor(matrixShape, mutableBuffer, bufferStart + offset)
yield(matrix) yield(matrix)
} }
} }