v0.3.0-dev-18 #459

Merged
altavir merged 64 commits from dev into master 2022-02-13 17:50:34 +03:00
29 changed files with 221 additions and 178 deletions
Showing only changes of commit 0f5f59e175 - Show all commits

View File

@ -19,24 +19,24 @@ fun main() {
measureTimeMillis { measureTimeMillis {
var res = 0.0 var res = 0.0
strides.indices().forEach { res = structure[it] } strides.asSequence().forEach { res = structure[it] }
} // warmup } // warmup
val time1 = measureTimeMillis { val time1 = measureTimeMillis {
var res = 0.0 var res = 0.0
strides.indices().forEach { res = structure[it] } strides.asSequence().forEach { res = structure[it] }
} }
println("Structure reading finished in $time1 millis") println("Structure reading finished in $time1 millis")
val time2 = measureTimeMillis { val time2 = measureTimeMillis {
var res = 0.0 var res = 0.0
strides.indices().forEach { res = buffer[strides.offset(it)] } strides.asSequence().forEach { res = buffer[strides.offset(it)] }
} }
println("Buffer reading finished in $time2 millis") println("Buffer reading finished in $time2 millis")
val time3 = measureTimeMillis { val time3 = measureTimeMillis {
var res = 0.0 var res = 0.0
strides.indices().forEach { res = array[strides.offset(it)] } strides.asSequence().forEach { res = array[strides.offset(it)] }
} }
println("Array reading finished in $time3 millis") println("Array reading finished in $time3 millis")
} }

View File

@ -166,8 +166,8 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
override operator fun Quaternion.plus(other: Number): Quaternion = Quaternion(w + other.toDouble(), x, y, z) override operator fun Quaternion.plus(other: Number): Quaternion = Quaternion(w + other.toDouble(), x, y, z)
override operator fun Quaternion.minus(other: Number): Quaternion = Quaternion(w - other.toDouble(), x, y, z) override operator fun Quaternion.minus(other: Number): Quaternion = Quaternion(w - other.toDouble(), x, y, z)
override operator fun Number.times(other: Quaternion): Quaternion = override operator fun Number.times(arg: Quaternion): Quaternion =
Quaternion(toDouble() * other.w, toDouble() * other.x, toDouble() * other.y, toDouble() * other.z) Quaternion(toDouble() * arg.w, toDouble() * arg.x, toDouble() * arg.y, toDouble() * arg.z)
override fun Quaternion.unaryMinus(): Quaternion = Quaternion(-w, -x, -y, -z) override fun Quaternion.unaryMinus(): Quaternion = Quaternion(-w, -x, -y, -z)
override fun norm(arg: Quaternion): Quaternion = sqrt(arg.conjugate * arg) override fun norm(arg: Quaternion): Quaternion = sqrt(arg.conjugate * arg)

View File

@ -38,8 +38,8 @@ public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
override operator fun MST.unaryMinus(): MST.Unary = override operator fun MST.unaryMinus(): MST.Unary =
unaryOperationFunction(GroupOps.MINUS_OPERATION)(this) unaryOperationFunction(GroupOps.MINUS_OPERATION)(this)
override operator fun MST.minus(other: MST): MST.Binary = override operator fun MST.minus(arg: MST): MST.Binary =
binaryOperationFunction(GroupOps.MINUS_OPERATION)(this, other) binaryOperationFunction(GroupOps.MINUS_OPERATION)(this, arg)
override fun scale(a: MST, value: Double): MST.Binary = override fun scale(a: MST, value: Double): MST.Binary =
binaryOperationFunction(RingOps.TIMES_OPERATION)(a, number(value)) binaryOperationFunction(RingOps.TIMES_OPERATION)(a, number(value))
@ -72,7 +72,7 @@ public object MstRing : Ring<MST>, NumbersAddOps<MST>, ScaleOperations<MST> {
override operator fun MST.unaryPlus(): MST.Unary = MstGroup { +this@unaryPlus } override operator fun MST.unaryPlus(): MST.Unary = MstGroup { +this@unaryPlus }
override operator fun MST.unaryMinus(): MST.Unary = MstGroup { -this@unaryMinus } override operator fun MST.unaryMinus(): MST.Unary = MstGroup { -this@unaryMinus }
override operator fun MST.minus(other: MST): MST.Binary = MstGroup { this@minus - other } override operator fun MST.minus(arg: MST): MST.Binary = MstGroup { this@minus - arg }
override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
MstGroup.binaryOperationFunction(operation) MstGroup.binaryOperationFunction(operation)
@ -103,7 +103,7 @@ public object MstField : Field<MST>, NumbersAddOps<MST>, ScaleOperations<MST> {
override operator fun MST.unaryPlus(): MST.Unary = MstRing { +this@unaryPlus } override operator fun MST.unaryPlus(): MST.Unary = MstRing { +this@unaryPlus }
override operator fun MST.unaryMinus(): MST.Unary = MstRing { -this@unaryMinus } override operator fun MST.unaryMinus(): MST.Unary = MstRing { -this@unaryMinus }
override operator fun MST.minus(other: MST): MST.Binary = MstRing { this@minus - other } override operator fun MST.minus(arg: MST): MST.Binary = MstRing { this@minus - arg }
override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
MstRing.binaryOperationFunction(operation) MstRing.binaryOperationFunction(operation)
@ -144,7 +144,7 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
override fun divide(left: MST, right: MST): MST.Binary = MstField.divide(left, right) override fun divide(left: MST, right: MST): MST.Binary = MstField.divide(left, right)
override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus } override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus }
override operator fun MST.unaryMinus(): MST.Unary = MstField { -this@unaryMinus } override operator fun MST.unaryMinus(): MST.Unary = MstField { -this@unaryMinus }
override operator fun MST.minus(other: MST): MST.Binary = MstField { this@minus - other } override operator fun MST.minus(arg: MST): MST.Binary = MstField { this@minus - arg }
override fun power(arg: MST, pow: Number): MST.Binary = override fun power(arg: MST, pow: Number): MST.Binary =
binaryOperationFunction(PowerOperations.POW_OPERATION)(arg, number(pow)) binaryOperationFunction(PowerOperations.POW_OPERATION)(arg, number(pow))

View File

@ -29,6 +29,7 @@ public class BufferedLinearSpace<T, out A : Ring<T>>(
override fun buildVector(size: Int, initializer: A.(Int) -> T): Point<T> = override fun buildVector(size: Int, initializer: A.(Int) -> T): Point<T> =
bufferAlgebra.buffer(size) { elementAlgebra.initializer(it) } bufferAlgebra.buffer(size) { elementAlgebra.initializer(it) }
@OptIn(PerformancePitfall::class)
override fun Matrix<T>.unaryMinus(): Matrix<T> = ndAlgebra { override fun Matrix<T>.unaryMinus(): Matrix<T> = ndAlgebra {
asND().map { -it }.as2D() asND().map { -it }.as2D()
} }
@ -83,6 +84,7 @@ public class BufferedLinearSpace<T, out A : Ring<T>>(
} }
} }
@OptIn(PerformancePitfall::class)
override fun Matrix<T>.times(value: T): Matrix<T> = ndAlgebra { override fun Matrix<T>.times(value: T): Matrix<T> = ndAlgebra {
asND().map { it * value }.as2D() asND().map { it * value }.as2D()
} }

View File

@ -5,6 +5,7 @@
package space.kscience.kmath.nd package space.kscience.kmath.nd
import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -24,6 +25,8 @@ public fun Shape(shapeFirst: Int, vararg shapeRest: Int): Shape = intArrayOf(sha
public interface WithShape { public interface WithShape {
public val shape: Shape public val shape: Shape
public val indices: ShapeIndexer get() = DefaultStrides(shape)
} }
/** /**
@ -46,21 +49,37 @@ public interface AlgebraND<T, out C : Algebra<T>> {
/** /**
* Maps elements from one structure to another one by applying [transform] to them. * Maps elements from one structure to another one by applying [transform] to them.
*/ */
public fun StructureND<T>.map(transform: C.(T) -> T): StructureND<T> @PerformancePitfall("Very slow on remote execution algebras")
public fun StructureND<T>.map(transform: C.(T) -> T): StructureND<T> = structureND(shape) { index ->
elementAlgebra.transform(get(index))
}
/** /**
* Maps elements from one structure to another one by applying [transform] to them alongside with their indices. * Maps elements from one structure to another one by applying [transform] to them alongside with their indices.
*/ */
public fun StructureND<T>.mapIndexed(transform: C.(index: IntArray, T) -> T): StructureND<T> @PerformancePitfall("Very slow on remote execution algebras")
public fun StructureND<T>.mapIndexed(transform: C.(index: IntArray, T) -> T): StructureND<T> =
structureND(shape) { index ->
elementAlgebra.transform(index, get(index))
}
/** /**
* Combines two structures into one. * Combines two structures into one.
*/ */
public fun zip(left: StructureND<T>, right: StructureND<T>, transform: C.(T, T) -> T): StructureND<T> @PerformancePitfall("Very slow on remote execution algebras")
public fun zip(left: StructureND<T>, right: StructureND<T>, transform: C.(T, T) -> T): StructureND<T> {
require(left.shape.contentEquals(right.shape)) {
"Expected left and right of the same shape, but left - ${left.shape} and right - ${right.shape}"
}
return structureND(left.shape) { index ->
elementAlgebra.transform(left[index], right[index])
}
}
/** /**
* Element-wise invocation of function working on [T] on a [StructureND]. * Element-wise invocation of function working on [T] on a [StructureND].
*/ */
@PerformancePitfall
public operator fun Function1<T, T>.invoke(structure: StructureND<T>): StructureND<T> = public operator fun Function1<T, T>.invoke(structure: StructureND<T>): StructureND<T> =
structure.map { value -> this@invoke(value) } structure.map { value -> this@invoke(value) }
@ -104,6 +123,7 @@ public interface GroupOpsND<T, out A : GroupOps<T>> : GroupOps<StructureND<T>>,
* @param right the addend. * @param right the addend.
* @return the sum. * @return the sum.
*/ */
@OptIn(PerformancePitfall::class)
override fun add(left: StructureND<T>, right: StructureND<T>): StructureND<T> = override fun add(left: StructureND<T>, right: StructureND<T>): StructureND<T> =
zip(left, right) { aValue, bValue -> add(aValue, bValue) } zip(left, right) { aValue, bValue -> add(aValue, bValue) }
@ -116,6 +136,7 @@ public interface GroupOpsND<T, out A : GroupOps<T>> : GroupOps<StructureND<T>>,
* @param arg the addend. * @param arg the addend.
* @return the sum. * @return the sum.
*/ */
@OptIn(PerformancePitfall::class)
public operator fun StructureND<T>.plus(arg: T): StructureND<T> = this.map { value -> add(arg, value) } public operator fun StructureND<T>.plus(arg: T): StructureND<T> = this.map { value -> add(arg, value) }
/** /**
@ -125,25 +146,28 @@ public interface GroupOpsND<T, out A : GroupOps<T>> : GroupOps<StructureND<T>>,
* @param arg the divisor. * @param arg the divisor.
* @return the quotient. * @return the quotient.
*/ */
@OptIn(PerformancePitfall::class)
public operator fun StructureND<T>.minus(arg: T): StructureND<T> = this.map { value -> add(arg, -value) } public operator fun StructureND<T>.minus(arg: T): StructureND<T> = this.map { value -> add(arg, -value) }
/** /**
* Adds an element to ND structure of it. * Adds an element to ND structure of it.
* *
* @receiver the augend. * @receiver the augend.
* @param other the addend. * @param arg the addend.
* @return the sum. * @return the sum.
*/ */
public operator fun T.plus(other: StructureND<T>): StructureND<T> = other.map { value -> add(this@plus, value) } @OptIn(PerformancePitfall::class)
public operator fun T.plus(arg: StructureND<T>): StructureND<T> = arg.map { value -> add(this@plus, value) }
/** /**
* Subtracts an ND structure from an element of it. * Subtracts an ND structure from an element of it.
* *
* @receiver the dividend. * @receiver the dividend.
* @param other the divisor. * @param arg the divisor.
* @return the quotient. * @return the quotient.
*/ */
public operator fun T.minus(other: StructureND<T>): StructureND<T> = other.map { value -> add(-this@minus, value) } @OptIn(PerformancePitfall::class)
public operator fun T.minus(arg: StructureND<T>): StructureND<T> = arg.map { value -> add(-this@minus, value) }
public companion object public companion object
} }
@ -166,6 +190,7 @@ public interface RingOpsND<T, out A : RingOps<T>> : RingOps<StructureND<T>>, Gro
* @param right the multiplier. * @param right the multiplier.
* @return the product. * @return the product.
*/ */
@OptIn(PerformancePitfall::class)
override fun multiply(left: StructureND<T>, right: StructureND<T>): StructureND<T> = override fun multiply(left: StructureND<T>, right: StructureND<T>): StructureND<T> =
zip(left, right) { aValue, bValue -> multiply(aValue, bValue) } zip(left, right) { aValue, bValue -> multiply(aValue, bValue) }
@ -178,6 +203,7 @@ public interface RingOpsND<T, out A : RingOps<T>> : RingOps<StructureND<T>>, Gro
* @param arg the multiplier. * @param arg the multiplier.
* @return the product. * @return the product.
*/ */
@OptIn(PerformancePitfall::class)
public operator fun StructureND<T>.times(arg: T): StructureND<T> = this.map { value -> multiply(arg, value) } public operator fun StructureND<T>.times(arg: T): StructureND<T> = this.map { value -> multiply(arg, value) }
/** /**
@ -187,6 +213,7 @@ public interface RingOpsND<T, out A : RingOps<T>> : RingOps<StructureND<T>>, Gro
* @param arg the multiplier. * @param arg the multiplier.
* @return the product. * @return the product.
*/ */
@OptIn(PerformancePitfall::class)
public operator fun T.times(arg: StructureND<T>): StructureND<T> = arg.map { value -> multiply(this@times, value) } public operator fun T.times(arg: StructureND<T>): StructureND<T> = arg.map { value -> multiply(this@times, value) }
public companion object public companion object
@ -214,6 +241,7 @@ public interface FieldOpsND<T, out A : Field<T>> :
* @param right the divisor. * @param right the divisor.
* @return the quotient. * @return the quotient.
*/ */
@OptIn(PerformancePitfall::class)
override fun divide(left: StructureND<T>, right: StructureND<T>): StructureND<T> = override fun divide(left: StructureND<T>, right: StructureND<T>): StructureND<T> =
zip(left, right) { aValue, bValue -> divide(aValue, bValue) } zip(left, right) { aValue, bValue -> divide(aValue, bValue) }
@ -225,6 +253,7 @@ public interface FieldOpsND<T, out A : Field<T>> :
* @param arg the divisor. * @param arg the divisor.
* @return the quotient. * @return the quotient.
*/ */
@OptIn(PerformancePitfall::class)
public operator fun StructureND<T>.div(arg: T): StructureND<T> = this.map { value -> divide(arg, value) } public operator fun StructureND<T>.div(arg: T): StructureND<T> = this.map { value -> divide(arg, value) }
/** /**
@ -234,8 +263,10 @@ public interface FieldOpsND<T, out A : Field<T>> :
* @param arg the divisor. * @param arg the divisor.
* @return the quotient. * @return the quotient.
*/ */
@OptIn(PerformancePitfall::class)
public operator fun T.div(arg: StructureND<T>): StructureND<T> = arg.map { divide(it, this@div) } public operator fun T.div(arg: StructureND<T>): StructureND<T> = arg.map { divide(it, this@div) }
@OptIn(PerformancePitfall::class)
override fun scale(a: StructureND<T>, value: Double): StructureND<T> = a.map { scale(it, value) } override fun scale(a: StructureND<T>, value: Double): StructureND<T> = a.map { scale(it, value) }
} }

View File

@ -7,6 +7,7 @@
package space.kscience.kmath.nd package space.kscience.kmath.nd
import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferFactory
@ -34,11 +35,14 @@ public interface BufferAlgebraND<T, out A : Algebra<T>> : AlgebraND<T, A> {
} }
} }
@PerformancePitfall
override fun StructureND<T>.map(transform: A.(T) -> T): BufferND<T> = mapInline(toBufferND(), transform) override fun StructureND<T>.map(transform: A.(T) -> T): BufferND<T> = mapInline(toBufferND(), transform)
@PerformancePitfall
override fun StructureND<T>.mapIndexed(transform: A.(index: IntArray, T) -> T): BufferND<T> = override fun StructureND<T>.mapIndexed(transform: A.(index: IntArray, T) -> T): BufferND<T> =
mapIndexedInline(toBufferND(), transform) mapIndexedInline(toBufferND(), transform)
@PerformancePitfall
override fun zip(left: StructureND<T>, right: StructureND<T>, transform: A.(T, T) -> T): BufferND<T> = override fun zip(left: StructureND<T>, right: StructureND<T>, transform: A.(T, T) -> T): BufferND<T> =
zipInline(left.toBufferND(), right.toBufferND(), transform) zipInline(left.toBufferND(), right.toBufferND(), transform)
@ -78,6 +82,7 @@ internal inline fun <T, A : Algebra<T>> BufferAlgebraND<T, A>.zipInline(
return BufferND(indexes, bufferAlgebra.zipInline(l.buffer, r.buffer, block)) return BufferND(indexes, bufferAlgebra.zipInline(l.buffer, r.buffer, block))
} }
@OptIn(PerformancePitfall::class)
public open class BufferedGroupNDOps<T, out A : Group<T>>( public open class BufferedGroupNDOps<T, out A : Group<T>>(
override val bufferAlgebra: BufferAlgebra<T, A>, override val bufferAlgebra: BufferAlgebra<T, A>,
override val indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder override val indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder
@ -101,6 +106,7 @@ public open class BufferedFieldOpsND<T, out A : Field<T>>(
indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder
) : this(BufferFieldOps(elementAlgebra, bufferFactory), indexerBuilder) ) : this(BufferFieldOps(elementAlgebra, bufferFactory), indexerBuilder)
@OptIn(PerformancePitfall::class)
override fun scale(a: StructureND<T>, value: Double): StructureND<T> = a.map { it * value } override fun scale(a: StructureND<T>, value: Double): StructureND<T> = a.map { it * value }
} }

View File

@ -19,7 +19,7 @@ import space.kscience.kmath.structures.MutableBufferFactory
* @param buffer The underlying buffer. * @param buffer The underlying buffer.
*/ */
public open class BufferND<out T>( public open class BufferND<out T>(
public val indices: ShapeIndexer, override val indices: ShapeIndexer,
public open val buffer: Buffer<T>, public open val buffer: Buffer<T>,
) : StructureND<T> { ) : StructureND<T> {
@ -28,7 +28,7 @@ public open class BufferND<out T>(
override val shape: IntArray get() = indices.shape override val shape: IntArray get() = indices.shape
@PerformancePitfall @PerformancePitfall
override fun elements(): Sequence<Pair<IntArray, T>> = indices.indices().map { override fun elements(): Sequence<Pair<IntArray, T>> = indices.asSequence().map {
it to this[it] it to this[it]
} }

View File

@ -5,6 +5,7 @@
package space.kscience.kmath.nd package space.kscience.kmath.nd
import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.DoubleBuffer
@ -50,10 +51,12 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND<Double, DoubleField>(D
return DoubleBufferND(indexes, DoubleBuffer(indexes.linearSize) { block(lArray[it], rArray[it]) }) return DoubleBufferND(indexes, DoubleBuffer(indexes.linearSize) { block(lArray[it], rArray[it]) })
} }
@OptIn(PerformancePitfall::class)
override fun StructureND<Double>.map(transform: DoubleField.(Double) -> Double): BufferND<Double> = override fun StructureND<Double>.map(transform: DoubleField.(Double) -> Double): BufferND<Double> =
mapInline(toBufferND()) { DoubleField.transform(it) } mapInline(toBufferND()) { DoubleField.transform(it) }
@OptIn(PerformancePitfall::class)
override fun zip( override fun zip(
left: StructureND<Double>, left: StructureND<Double>,
right: StructureND<Double>, right: StructureND<Double>,
@ -92,11 +95,11 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND<Double, DoubleField>(D
override fun StructureND<Double>.unaryPlus(): DoubleBufferND = toBufferND() override fun StructureND<Double>.unaryPlus(): DoubleBufferND = toBufferND()
override fun StructureND<Double>.plus(other: StructureND<Double>): DoubleBufferND = override fun StructureND<Double>.plus(arg: StructureND<Double>): DoubleBufferND =
zipInline(toBufferND(), other.toBufferND()) { l: Double, r: Double -> l + r } zipInline(toBufferND(), arg.toBufferND()) { l: Double, r: Double -> l + r }
override fun StructureND<Double>.minus(other: StructureND<Double>): DoubleBufferND = override fun StructureND<Double>.minus(arg: StructureND<Double>): DoubleBufferND =
zipInline(toBufferND(), other.toBufferND()) { l: Double, r: Double -> l - r } zipInline(toBufferND(), arg.toBufferND()) { l: Double, r: Double -> l - r }
override fun StructureND<Double>.times(other: StructureND<Double>): DoubleBufferND = override fun StructureND<Double>.times(other: StructureND<Double>): DoubleBufferND =
zipInline(toBufferND(), other.toBufferND()) { l: Double, r: Double -> l * r } zipInline(toBufferND(), other.toBufferND()) { l: Double, r: Double -> l * r }
@ -107,7 +110,7 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND<Double, DoubleField>(D
override fun StructureND<Double>.div(k: Number): DoubleBufferND = override fun StructureND<Double>.div(k: Number): DoubleBufferND =
mapInline(toBufferND()) { it / k.toDouble() } mapInline(toBufferND()) { it / k.toDouble() }
override fun Number.times(other: StructureND<Double>): DoubleBufferND = other * this override fun Number.times(arg: StructureND<Double>): DoubleBufferND = arg * this
override fun StructureND<Double>.plus(arg: Double): DoubleBufferND = mapInline(toBufferND()) { it + arg } override fun StructureND<Double>.plus(arg: Double): DoubleBufferND = mapInline(toBufferND()) { it + arg }

View File

@ -10,7 +10,7 @@ import kotlin.native.concurrent.ThreadLocal
/** /**
* A converter from linear index to multivariate index * A converter from linear index to multivariate index
*/ */
public interface ShapeIndexer{ public interface ShapeIndexer: Iterable<IntArray>{
public val shape: Shape public val shape: Shape
/** /**
@ -33,7 +33,9 @@ public interface ShapeIndexer{
/** /**
* Iterate over ND indices in a natural order * Iterate over ND indices in a natural order
*/ */
public fun indices(): Sequence<IntArray> public fun asSequence(): Sequence<IntArray>
override fun iterator(): Iterator<IntArray> = asSequence().iterator()
override fun equals(other: Any?): Boolean override fun equals(other: Any?): Boolean
override fun hashCode(): Int override fun hashCode(): Int
@ -58,7 +60,7 @@ public abstract class Strides: ShapeIndexer {
/** /**
* Iterate over ND indices in a natural order * Iterate over ND indices in a natural order
*/ */
public override fun indices(): Sequence<IntArray> = (0 until linearSize).asSequence().map(::index) public override fun asSequence(): Sequence<IntArray> = (0 until linearSize).asSequence().map(::index)
} }
/** /**

View File

@ -28,12 +28,12 @@ public interface StructureFeature : Feature<StructureFeature>
* *
* @param T the type of items. * @param T the type of items.
*/ */
public interface StructureND<out T> : Featured<StructureFeature> { public interface StructureND<out T> : Featured<StructureFeature>, WithShape {
/** /**
* The shape of structure i.e., non-empty sequence of non-negative integers that specify sizes of dimensions of * The shape of structure i.e., non-empty sequence of non-negative integers that specify sizes of dimensions of
* this structure. * this structure.
*/ */
public val shape: Shape override val shape: Shape
/** /**
* The count of dimensions in this structure. It should be equal to size of [shape]. * The count of dimensions in this structure. It should be equal to size of [shape].
@ -54,7 +54,7 @@ public interface StructureND<out T> : Featured<StructureFeature> {
* @return the lazy sequence of pairs of indices to values. * @return the lazy sequence of pairs of indices to values.
*/ */
@PerformancePitfall @PerformancePitfall
public fun elements(): Sequence<Pair<IntArray, T>> public fun elements(): Sequence<Pair<IntArray, T>> = indices.asSequence().map { it to get(it) }
/** /**
* Feature is some additional structure information that allows to access it special properties or hints. * Feature is some additional structure information that allows to access it special properties or hints.

View File

@ -149,19 +149,19 @@ public interface GroupOps<T> : Algebra<T> {
* Addition of two elements. * Addition of two elements.
* *
* @receiver the augend. * @receiver the augend.
* @param other the addend. * @param arg the addend.
* @return the sum. * @return the sum.
*/ */
public operator fun T.plus(other: T): T = add(this, other) public operator fun T.plus(arg: T): T = add(this, arg)
/** /**
* Subtraction of two elements. * Subtraction of two elements.
* *
* @receiver the minuend. * @receiver the minuend.
* @param other the subtrahend. * @param arg the subtrahend.
* @return the difference. * @return the difference.
*/ */
public operator fun T.minus(other: T): T = add(this, -other) public operator fun T.minus(arg: T): T = add(this, -arg)
// Dynamic dispatch of operations // Dynamic dispatch of operations
override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) { override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) {
PLUS_OPERATION -> { arg -> +arg } PLUS_OPERATION -> { arg -> +arg }
@ -219,9 +219,9 @@ public interface RingOps<T> : GroupOps<T> {
* Multiplies this element by scalar. * Multiplies this element by scalar.
* *
* @receiver the multiplier. * @receiver the multiplier.
* @param other the multiplicand. * @param arg the multiplicand.
*/ */
public operator fun T.times(other: T): T = multiply(this, other) public operator fun T.times(arg: T): T = multiply(this, arg)
override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = when (operation) { override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = when (operation) {
TIMES_OPERATION -> ::multiply TIMES_OPERATION -> ::multiply

View File

@ -139,10 +139,10 @@ public interface ScaleOperations<T> : Algebra<T> {
* Multiplication of this number by element. * Multiplication of this number by element.
* *
* @receiver the multiplier. * @receiver the multiplier.
* @param other the multiplicand. * @param arg the multiplicand.
* @return the product. * @return the product.
*/ */
public operator fun Number.times(other: T): T = other * this public operator fun Number.times(arg: T): T = arg * this
} }
/** /**

View File

@ -228,8 +228,8 @@ public object ByteRing : Ring<Byte>, Norm<Byte, Byte>, NumericAlgebra<Byte> {
override fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte() override fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte()
override inline fun Byte.unaryMinus(): Byte = (-this).toByte() override inline fun Byte.unaryMinus(): Byte = (-this).toByte()
override inline fun Byte.plus(other: Byte): Byte = (this + other).toByte() override inline fun Byte.plus(arg: Byte): Byte = (this + arg).toByte()
override inline fun Byte.minus(other: Byte): Byte = (this - other).toByte() override inline fun Byte.minus(arg: Byte): Byte = (this - arg).toByte()
override inline fun Byte.times(other: Byte): Byte = (this * other).toByte() override inline fun Byte.times(other: Byte): Byte = (this * other).toByte()
} }

View File

@ -19,7 +19,7 @@ public object JBigIntegerField : Ring<BigInteger>, NumericAlgebra<BigInteger> {
override fun number(value: Number): BigInteger = BigInteger.valueOf(value.toLong()) override fun number(value: Number): BigInteger = BigInteger.valueOf(value.toLong())
override fun add(left: BigInteger, right: BigInteger): BigInteger = left.add(right) override fun add(left: BigInteger, right: BigInteger): BigInteger = left.add(right)
override operator fun BigInteger.minus(other: BigInteger): BigInteger = subtract(other) override operator fun BigInteger.minus(arg: BigInteger): BigInteger = subtract(arg)
override fun multiply(left: BigInteger, right: BigInteger): BigInteger = left.multiply(right) override fun multiply(left: BigInteger, right: BigInteger): BigInteger = left.multiply(right)
override operator fun BigInteger.unaryMinus(): BigInteger = negate() override operator fun BigInteger.unaryMinus(): BigInteger = negate()
@ -40,7 +40,7 @@ public abstract class JBigDecimalFieldBase internal constructor(
get() = BigDecimal.ONE get() = BigDecimal.ONE
override fun add(left: BigDecimal, right: BigDecimal): BigDecimal = left.add(right) override fun add(left: BigDecimal, right: BigDecimal): BigDecimal = left.add(right)
override operator fun BigDecimal.minus(other: BigDecimal): BigDecimal = subtract(other) override operator fun BigDecimal.minus(arg: BigDecimal): BigDecimal = subtract(arg)
override fun number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble()) override fun number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble())
override fun scale(a: BigDecimal, value: Double): BigDecimal = override fun scale(a: BigDecimal, value: Double): BigDecimal =

View File

@ -28,7 +28,7 @@ public class LazyStructureND<out T>(
@OptIn(PerformancePitfall::class) @OptIn(PerformancePitfall::class)
override fun elements(): Sequence<Pair<IntArray, T>> { override fun elements(): Sequence<Pair<IntArray, T>> {
val strides = DefaultStrides(shape) val strides = DefaultStrides(shape)
val res = runBlocking { strides.indices().toList().map { index -> index to await(index) } } val res = runBlocking { strides.asSequence().toList().map { index -> index to await(index) } }
return res.asSequence() return res.asSequence()
} }
} }

View File

@ -38,7 +38,7 @@ public class IndexedHistogram<T : Comparable<T>, V : Any>(
override val dimension: Int get() = context.shape.size override val dimension: Int get() = context.shape.size
override val bins: Iterable<Bin<T>> override val bins: Iterable<Bin<T>>
get() = DefaultStrides(context.shape).indices().map { get() = DefaultStrides(context.shape).asSequence().map {
context.produceBin(it, values[it]) context.produceBin(it, values[it])
}.asIterable() }.asIterable()

View File

@ -70,7 +70,7 @@ internal class MultivariateHistogramTest {
} }
val res = histogram1 - histogram2 val res = histogram1 - histogram2
assertTrue { assertTrue {
DefaultStrides(shape).indices().all { index -> DefaultStrides(shape).asSequence().all { index ->
res.values[index] <= histogram1.values[index] res.values[index] <= histogram1.values[index]
} }
} }

View File

@ -57,8 +57,8 @@ public object JafamaDoubleField : ExtendedField<Double>, Norm<Double, Double>, S
override inline fun norm(arg: Double): Double = FastMath.abs(arg) override inline fun norm(arg: Double): Double = FastMath.abs(arg)
override inline fun Double.unaryMinus(): Double = -this override inline fun Double.unaryMinus(): Double = -this
override inline fun Double.plus(other: Double): Double = this + other override inline fun Double.plus(arg: Double): Double = this + arg
override inline fun Double.minus(other: Double): Double = this - other override inline fun Double.minus(arg: Double): Double = this - arg
override inline fun Double.times(other: Double): Double = this * other override inline fun Double.times(other: Double): Double = this * other
override inline fun Double.div(other: Double): Double = this / other override inline fun Double.div(other: Double): Double = this / other
} }

View File

@ -59,7 +59,7 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): MultikTensor<T> { override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): MultikTensor<T> {
val strides = DefaultStrides(shape) val strides = DefaultStrides(shape)
val memoryView = initMemoryView<T>(strides.linearSize, type) val memoryView = initMemoryView<T>(strides.linearSize, type)
strides.indices().forEachIndexed { linearIndex, tensorIndex -> strides.asSequence().forEachIndexed { linearIndex, tensorIndex ->
memoryView[linearIndex] = elementAlgebra.initializer(tensorIndex) memoryView[linearIndex] = elementAlgebra.initializer(tensorIndex)
} }
return MultikTensor(NDArray(memoryView, shape = shape, dim = DN(shape.size))) return MultikTensor(NDArray(memoryView, shape = shape, dim = DN(shape.size)))
@ -131,14 +131,14 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
get(intArrayOf(0)) get(intArrayOf(0))
} else null } else null
override fun T.plus(other: StructureND<T>): MultikTensor<T> = override fun T.plus(arg: StructureND<T>): MultikTensor<T> =
other.plus(this) arg.plus(this)
override fun StructureND<T>.plus(arg: T): MultikTensor<T> = override fun StructureND<T>.plus(arg: T): MultikTensor<T> =
asMultik().array.deepCopy().apply { plusAssign(arg) }.wrap() asMultik().array.deepCopy().apply { plusAssign(arg) }.wrap()
override fun StructureND<T>.plus(other: StructureND<T>): MultikTensor<T> = override fun StructureND<T>.plus(arg: StructureND<T>): MultikTensor<T> =
asMultik().array.plus(other.asMultik().array).wrap() asMultik().array.plus(arg.asMultik().array).wrap()
override fun Tensor<T>.plusAssign(value: T) { override fun Tensor<T>.plusAssign(value: T) {
if (this is MultikTensor) { if (this is MultikTensor) {
@ -148,21 +148,21 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
} }
} }
override fun Tensor<T>.plusAssign(other: StructureND<T>) { override fun Tensor<T>.plusAssign(arg: StructureND<T>) {
if (this is MultikTensor) { if (this is MultikTensor) {
array.plusAssign(other.asMultik().array) array.plusAssign(arg.asMultik().array)
} else { } else {
mapInPlace { index, t -> elementAlgebra.add(t, other[index]) } mapInPlace { index, t -> elementAlgebra.add(t, arg[index]) }
} }
} }
override fun T.minus(other: StructureND<T>): MultikTensor<T> = (-(other.asMultik().array - this)).wrap() override fun T.minus(arg: StructureND<T>): MultikTensor<T> = (-(arg.asMultik().array - this)).wrap()
override fun StructureND<T>.minus(arg: T): MultikTensor<T> = override fun StructureND<T>.minus(arg: T): MultikTensor<T> =
asMultik().array.deepCopy().apply { minusAssign(arg) }.wrap() asMultik().array.deepCopy().apply { minusAssign(arg) }.wrap()
override fun StructureND<T>.minus(other: StructureND<T>): MultikTensor<T> = override fun StructureND<T>.minus(arg: StructureND<T>): MultikTensor<T> =
asMultik().array.minus(other.asMultik().array).wrap() asMultik().array.minus(arg.asMultik().array).wrap()
override fun Tensor<T>.minusAssign(value: T) { override fun Tensor<T>.minusAssign(value: T) {
if (this is MultikTensor) { if (this is MultikTensor) {
@ -172,11 +172,11 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
} }
} }
override fun Tensor<T>.minusAssign(other: StructureND<T>) { override fun Tensor<T>.minusAssign(arg: StructureND<T>) {
if (this is MultikTensor) { if (this is MultikTensor) {
array.minusAssign(other.asMultik().array) array.minusAssign(arg.asMultik().array)
} else { } else {
mapInPlace { index, t -> elementAlgebra.run { t - other[index] } } mapInPlace { index, t -> elementAlgebra.run { t - arg[index] } }
} }
} }
@ -186,8 +186,8 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
override fun StructureND<T>.times(arg: T): Tensor<T> = override fun StructureND<T>.times(arg: T): Tensor<T> =
asMultik().array.deepCopy().apply { timesAssign(arg) }.wrap() asMultik().array.deepCopy().apply { timesAssign(arg) }.wrap()
override fun StructureND<T>.times(other: StructureND<T>): MultikTensor<T> = override fun StructureND<T>.times(arg: StructureND<T>): MultikTensor<T> =
asMultik().array.times(other.asMultik().array).wrap() asMultik().array.times(arg.asMultik().array).wrap()
override fun Tensor<T>.timesAssign(value: T) { override fun Tensor<T>.timesAssign(value: T) {
if (this is MultikTensor) { if (this is MultikTensor) {
@ -197,11 +197,11 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
} }
} }
override fun Tensor<T>.timesAssign(other: StructureND<T>) { override fun Tensor<T>.timesAssign(arg: StructureND<T>) {
if (this is MultikTensor) { if (this is MultikTensor) {
array.timesAssign(other.asMultik().array) array.timesAssign(arg.asMultik().array)
} else { } else {
mapInPlace { index, t -> elementAlgebra.multiply(t, other[index]) } mapInPlace { index, t -> elementAlgebra.multiply(t, arg[index]) }
} }
} }
@ -212,7 +212,7 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
override fun StructureND<T>.transpose(i: Int, j: Int): MultikTensor<T> = asMultik().array.transpose(i, j).wrap() override fun StructureND<T>.transpose(i: Int, j: Int): MultikTensor<T> = asMultik().array.transpose(i, j).wrap()
override fun StructureND<T>.view(shape: IntArray): MultikTensor<T> { override fun Tensor<T>.view(shape: IntArray): MultikTensor<T> {
require(shape.all { it > 0 }) require(shape.all { it > 0 })
require(shape.fold(1, Int::times) == this.shape.size) { require(shape.fold(1, Int::times) == this.shape.size) {
"Cannot reshape array of size ${this.shape.size} into a new shape ${ "Cannot reshape array of size ${this.shape.size} into a new shape ${
@ -231,7 +231,7 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
}.wrap() }.wrap()
} }
override fun StructureND<T>.viewAs(other: StructureND<T>): MultikTensor<T> = view(other.shape) override fun Tensor<T>.viewAs(other: StructureND<T>): MultikTensor<T> = view(other.shape)
override fun StructureND<T>.dot(other: StructureND<T>): MultikTensor<T> = override fun StructureND<T>.dot(other: StructureND<T>): MultikTensor<T> =
if (this.shape.size == 1 && other.shape.size == 1) { if (this.shape.size == 1 && other.shape.size == 1) {
@ -283,8 +283,8 @@ public abstract class MultikDivisionTensorAlgebra<T, A : Field<T>>
override fun StructureND<T>.div(arg: T): MultikTensor<T> = override fun StructureND<T>.div(arg: T): MultikTensor<T> =
asMultik().array.deepCopy().apply { divAssign(arg) }.wrap() asMultik().array.deepCopy().apply { divAssign(arg) }.wrap()
override fun StructureND<T>.div(other: StructureND<T>): MultikTensor<T> = override fun StructureND<T>.div(arg: StructureND<T>): MultikTensor<T> =
asMultik().array.div(other.asMultik().array).wrap() asMultik().array.div(arg.asMultik().array).wrap()
override fun Tensor<T>.divAssign(value: T) { override fun Tensor<T>.divAssign(value: T) {
if (this is MultikTensor) { if (this is MultikTensor) {

View File

@ -76,8 +76,8 @@ public sealed interface Nd4jArrayGroupOps<T, out S : Ring<T>> : GroupOpsND<T, S>
override fun add(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> = override fun add(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> =
left.ndArray.add(right.ndArray).wrap() left.ndArray.add(right.ndArray).wrap()
override operator fun StructureND<T>.minus(other: StructureND<T>): Nd4jArrayStructure<T> = override operator fun StructureND<T>.minus(arg: StructureND<T>): Nd4jArrayStructure<T> =
ndArray.sub(other.ndArray).wrap() ndArray.sub(arg.ndArray).wrap()
override operator fun StructureND<T>.unaryMinus(): Nd4jArrayStructure<T> = override operator fun StructureND<T>.unaryMinus(): Nd4jArrayStructure<T> =
ndArray.neg().wrap() ndArray.neg().wrap()

View File

@ -51,29 +51,29 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
return structureND(left.shape) { index -> elementAlgebra.transform(left[index], right[index]) } return structureND(left.shape) { index -> elementAlgebra.transform(left[index], right[index]) }
} }
override fun T.plus(other: StructureND<T>): Nd4jArrayStructure<T> = other.ndArray.add(this).wrap() override fun T.plus(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.add(this).wrap()
override fun StructureND<T>.plus(arg: T): Nd4jArrayStructure<T> = ndArray.add(arg).wrap() override fun StructureND<T>.plus(arg: T): Nd4jArrayStructure<T> = ndArray.add(arg).wrap()
override fun StructureND<T>.plus(other: StructureND<T>): Nd4jArrayStructure<T> = ndArray.add(other.ndArray).wrap() override fun StructureND<T>.plus(arg: StructureND<T>): Nd4jArrayStructure<T> = ndArray.add(arg.ndArray).wrap()
override fun Tensor<T>.plusAssign(value: T) { override fun Tensor<T>.plusAssign(value: T) {
ndArray.addi(value) ndArray.addi(value)
} }
override fun Tensor<T>.plusAssign(other: StructureND<T>) { override fun Tensor<T>.plusAssign(arg: StructureND<T>) {
ndArray.addi(other.ndArray) ndArray.addi(arg.ndArray)
} }
override fun T.minus(other: StructureND<T>): Nd4jArrayStructure<T> = other.ndArray.rsub(this).wrap() override fun T.minus(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.rsub(this).wrap()
override fun StructureND<T>.minus(arg: T): Nd4jArrayStructure<T> = ndArray.sub(arg).wrap() override fun StructureND<T>.minus(arg: T): Nd4jArrayStructure<T> = ndArray.sub(arg).wrap()
override fun StructureND<T>.minus(other: StructureND<T>): Nd4jArrayStructure<T> = ndArray.sub(other.ndArray).wrap() override fun StructureND<T>.minus(arg: StructureND<T>): Nd4jArrayStructure<T> = ndArray.sub(arg.ndArray).wrap()
override fun Tensor<T>.minusAssign(value: T) { override fun Tensor<T>.minusAssign(value: T) {
ndArray.rsubi(value) ndArray.rsubi(value)
} }
override fun Tensor<T>.minusAssign(other: StructureND<T>) { override fun Tensor<T>.minusAssign(arg: StructureND<T>) {
ndArray.subi(other.ndArray) ndArray.subi(arg.ndArray)
} }
override fun T.times(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.mul(this).wrap() override fun T.times(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.mul(this).wrap()
@ -81,14 +81,14 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
override fun StructureND<T>.times(arg: T): Nd4jArrayStructure<T> = override fun StructureND<T>.times(arg: T): Nd4jArrayStructure<T> =
ndArray.mul(arg).wrap() ndArray.mul(arg).wrap()
override fun StructureND<T>.times(other: StructureND<T>): Nd4jArrayStructure<T> = ndArray.mul(other.ndArray).wrap() override fun StructureND<T>.times(arg: StructureND<T>): Nd4jArrayStructure<T> = ndArray.mul(arg.ndArray).wrap()
override fun Tensor<T>.timesAssign(value: T) { override fun Tensor<T>.timesAssign(value: T) {
ndArray.muli(value) ndArray.muli(value)
} }
override fun Tensor<T>.timesAssign(other: StructureND<T>) { override fun Tensor<T>.timesAssign(arg: StructureND<T>) {
ndArray.mmuli(other.ndArray) ndArray.mmuli(arg.ndArray)
} }
override fun StructureND<T>.unaryMinus(): Nd4jArrayStructure<T> = ndArray.neg().wrap() override fun StructureND<T>.unaryMinus(): Nd4jArrayStructure<T> = ndArray.neg().wrap()
@ -105,8 +105,8 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
override fun StructureND<T>.max(dim: Int, keepDim: Boolean): Nd4jArrayStructure<T> = override fun StructureND<T>.max(dim: Int, keepDim: Boolean): Nd4jArrayStructure<T> =
ndArray.max(keepDim, dim).wrap() ndArray.max(keepDim, dim).wrap()
override fun StructureND<T>.view(shape: IntArray): Nd4jArrayStructure<T> = ndArray.reshape(shape).wrap() override fun Tensor<T>.view(shape: IntArray): Nd4jArrayStructure<T> = ndArray.reshape(shape).wrap()
override fun StructureND<T>.viewAs(other: StructureND<T>): Nd4jArrayStructure<T> = view(other.shape) override fun Tensor<T>.viewAs(other: StructureND<T>): Nd4jArrayStructure<T> = view(other.shape)
override fun StructureND<T>.argMax(dim: Int, keepDim: Boolean): Nd4jArrayStructure<T> = override fun StructureND<T>.argMax(dim: Int, keepDim: Boolean): Nd4jArrayStructure<T> =
ndBase.get().argmax(ndArray, keepDim, dim).wrap() ndBase.get().argmax(ndArray, keepDim, dim).wrap()
@ -142,7 +142,7 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
override fun T.div(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.rdiv(this).wrap() override fun T.div(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.rdiv(this).wrap()
override fun StructureND<T>.div(arg: T): Nd4jArrayStructure<T> = ndArray.div(arg).wrap() override fun StructureND<T>.div(arg: T): Nd4jArrayStructure<T> = ndArray.div(arg).wrap()
override fun StructureND<T>.div(other: StructureND<T>): Nd4jArrayStructure<T> = ndArray.div(other.ndArray).wrap() override fun StructureND<T>.div(arg: StructureND<T>): Nd4jArrayStructure<T> = ndArray.div(arg.ndArray).wrap()
override fun Tensor<T>.divAssign(value: T) { override fun Tensor<T>.divAssign(value: T) {
ndArray.divi(value) ndArray.divi(value)
@ -172,7 +172,7 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra<Double, DoubleField> {
override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): Nd4jArrayStructure<Double> { override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): Nd4jArrayStructure<Double> {
val array: INDArray = Nd4j.zeros(*shape) val array: INDArray = Nd4j.zeros(*shape)
val indices = DefaultStrides(shape) val indices = DefaultStrides(shape)
indices.indices().forEach { index -> indices.asSequence().forEach { index ->
array.putScalar(index, elementAlgebra.initializer(index)) array.putScalar(index, elementAlgebra.initializer(index))
} }
return array.wrap() return array.wrap()

View File

@ -32,13 +32,13 @@ public interface TensorAlgebra<T, A : Ring<T>> : RingOpsND<T, A> {
valueOrNull() ?: throw IllegalArgumentException("Inconsistent value for tensor of with $shape shape") valueOrNull() ?: throw IllegalArgumentException("Inconsistent value for tensor of with $shape shape")
/** /**
* Each element of the tensor [other] is added to this value. * Each element of the tensor [arg] is added to this value.
* The resulting tensor is returned. * The resulting tensor is returned.
* *
* @param other tensor to be added. * @param arg tensor to be added.
* @return the sum of this value and tensor [other]. * @return the sum of this value and tensor [arg].
*/ */
override operator fun T.plus(other: StructureND<T>): Tensor<T> override operator fun T.plus(arg: StructureND<T>): Tensor<T>
/** /**
* Adds the scalar [arg] to each element of this tensor and returns a new resulting tensor. * Adds the scalar [arg] to each element of this tensor and returns a new resulting tensor.
@ -49,13 +49,13 @@ public interface TensorAlgebra<T, A : Ring<T>> : RingOpsND<T, A> {
override operator fun StructureND<T>.plus(arg: T): Tensor<T> override operator fun StructureND<T>.plus(arg: T): Tensor<T>
/** /**
* Each element of the tensor [other] is added to each element of this tensor. * Each element of the tensor [arg] is added to each element of this tensor.
* The resulting tensor is returned. * The resulting tensor is returned.
* *
* @param other tensor to be added. * @param arg tensor to be added.
* @return the sum of this tensor and [other]. * @return the sum of this tensor and [arg].
*/ */
override operator fun StructureND<T>.plus(other: StructureND<T>): Tensor<T> override operator fun StructureND<T>.plus(arg: StructureND<T>): Tensor<T>
/** /**
* Adds the scalar [value] to each element of this tensor. * Adds the scalar [value] to each element of this tensor.
@ -65,20 +65,20 @@ public interface TensorAlgebra<T, A : Ring<T>> : RingOpsND<T, A> {
public operator fun Tensor<T>.plusAssign(value: T) public operator fun Tensor<T>.plusAssign(value: T)
/** /**
* Each element of the tensor [other] is added to each element of this tensor. * Each element of the tensor [arg] is added to each element of this tensor.
* *
* @param other tensor to be added. * @param arg tensor to be added.
*/ */
public operator fun Tensor<T>.plusAssign(other: StructureND<T>) public operator fun Tensor<T>.plusAssign(arg: StructureND<T>)
/** /**
* Each element of the tensor [other] is subtracted from this value. * Each element of the tensor [arg] is subtracted from this value.
* The resulting tensor is returned. * The resulting tensor is returned.
* *
* @param other tensor to be subtracted. * @param arg tensor to be subtracted.
* @return the difference between this value and tensor [other]. * @return the difference between this value and tensor [arg].
*/ */
override operator fun T.minus(other: StructureND<T>): Tensor<T> override operator fun T.minus(arg: StructureND<T>): Tensor<T>
/** /**
* Subtracts the scalar [arg] from each element of this tensor and returns a new resulting tensor. * Subtracts the scalar [arg] from each element of this tensor and returns a new resulting tensor.
@ -89,13 +89,13 @@ public interface TensorAlgebra<T, A : Ring<T>> : RingOpsND<T, A> {
override operator fun StructureND<T>.minus(arg: T): Tensor<T> override operator fun StructureND<T>.minus(arg: T): Tensor<T>
/** /**
* Each element of the tensor [other] is subtracted from each element of this tensor. * Each element of the tensor [arg] is subtracted from each element of this tensor.
* The resulting tensor is returned. * The resulting tensor is returned.
* *
* @param other tensor to be subtracted. * @param arg tensor to be subtracted.
* @return the difference between this tensor and [other]. * @return the difference between this tensor and [arg].
*/ */
override operator fun StructureND<T>.minus(other: StructureND<T>): Tensor<T> override operator fun StructureND<T>.minus(arg: StructureND<T>): Tensor<T>
/** /**
* Subtracts the scalar [value] from each element of this tensor. * Subtracts the scalar [value] from each element of this tensor.
@ -105,11 +105,11 @@ public interface TensorAlgebra<T, A : Ring<T>> : RingOpsND<T, A> {
public operator fun Tensor<T>.minusAssign(value: T) public operator fun Tensor<T>.minusAssign(value: T)
/** /**
* Each element of the tensor [other] is subtracted from each element of this tensor. * Each element of the tensor [arg] is subtracted from each element of this tensor.
* *
* @param other tensor to be subtracted. * @param arg tensor to be subtracted.
*/ */
public operator fun Tensor<T>.minusAssign(other: StructureND<T>) public operator fun Tensor<T>.minusAssign(arg: StructureND<T>)
/** /**
@ -130,13 +130,13 @@ public interface TensorAlgebra<T, A : Ring<T>> : RingOpsND<T, A> {
override operator fun StructureND<T>.times(arg: T): Tensor<T> override operator fun StructureND<T>.times(arg: T): Tensor<T>
/** /**
* Each element of the tensor [other] is multiplied by each element of this tensor. * Each element of the tensor [arg] is multiplied by each element of this tensor.
* The resulting tensor is returned. * The resulting tensor is returned.
* *
* @param other tensor to be multiplied. * @param arg tensor to be multiplied.
* @return the product of this tensor and [other]. * @return the product of this tensor and [arg].
*/ */
override operator fun StructureND<T>.times(other: StructureND<T>): Tensor<T> override operator fun StructureND<T>.times(arg: StructureND<T>): Tensor<T>
/** /**
* Multiplies the scalar [value] by each element of this tensor. * Multiplies the scalar [value] by each element of this tensor.
@ -146,11 +146,11 @@ public interface TensorAlgebra<T, A : Ring<T>> : RingOpsND<T, A> {
public operator fun Tensor<T>.timesAssign(value: T) public operator fun Tensor<T>.timesAssign(value: T)
/** /**
* Each element of the tensor [other] is multiplied by each element of this tensor. * Each element of the tensor [arg] is multiplied by each element of this tensor.
* *
* @param other tensor to be multiplied. * @param arg tensor to be multiplied.
*/ */
public operator fun Tensor<T>.timesAssign(other: StructureND<T>) public operator fun Tensor<T>.timesAssign(arg: StructureND<T>)
/** /**
* Numerical negative, element-wise. * Numerical negative, element-wise.
@ -186,7 +186,7 @@ public interface TensorAlgebra<T, A : Ring<T>> : RingOpsND<T, A> {
* @param shape the desired size * @param shape the desired size
* @return tensor with new shape * @return tensor with new shape
*/ */
public fun StructureND<T>.view(shape: IntArray): Tensor<T> public fun Tensor<T>.view(shape: IntArray): Tensor<T>
/** /**
* View this tensor as the same size as [other]. * View this tensor as the same size as [other].
@ -196,7 +196,7 @@ public interface TensorAlgebra<T, A : Ring<T>> : RingOpsND<T, A> {
* @param other the result tensor has the same size as other. * @param other the result tensor has the same size as other.
* @return the result tensor with the same size as other. * @return the result tensor with the same size as other.
*/ */
public fun StructureND<T>.viewAs(other: StructureND<T>): Tensor<T> public fun Tensor<T>.viewAs(other: StructureND<T>): Tensor<T>
/** /**
* Matrix product of two tensors. * Matrix product of two tensors.

View File

@ -35,13 +35,13 @@ public interface TensorPartialDivisionAlgebra<T, A : Field<T>> : TensorAlgebra<T
override operator fun StructureND<T>.div(arg: T): Tensor<T> override operator fun StructureND<T>.div(arg: T): Tensor<T>
/** /**
* Each element of the tensor [other] is divided by each element of this tensor. * Each element of the tensor [arg] is divided by each element of this tensor.
* The resulting tensor is returned. * The resulting tensor is returned.
* *
* @param other tensor to be divided by. * @param arg tensor to be divided by.
* @return the division of this tensor by [other]. * @return the division of this tensor by [arg].
*/ */
override operator fun StructureND<T>.div(other: StructureND<T>): Tensor<T> override operator fun StructureND<T>.div(arg: StructureND<T>): Tensor<T>
override fun divide(left: StructureND<T>, right: StructureND<T>): StructureND<T> = left.div(right) override fun divide(left: StructureND<T>, right: StructureND<T>): StructureND<T> = left.div(right)

View File

@ -19,8 +19,8 @@ import space.kscience.kmath.tensors.core.internal.tensor
*/ */
public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
override fun StructureND<Double>.plus(other: StructureND<Double>): DoubleTensor { override fun StructureND<Double>.plus(arg: StructureND<Double>): DoubleTensor {
val broadcast = broadcastTensors(tensor, other.tensor) val broadcast = broadcastTensors(tensor, arg.tensor)
val newThis = broadcast[0] val newThis = broadcast[0]
val newOther = broadcast[1] val newOther = broadcast[1]
val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> val resBuffer = DoubleArray(newThis.indices.linearSize) { i ->
@ -29,16 +29,16 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
return DoubleTensor(newThis.shape, resBuffer) return DoubleTensor(newThis.shape, resBuffer)
} }
override fun Tensor<Double>.plusAssign(other: StructureND<Double>) { override fun Tensor<Double>.plusAssign(arg: StructureND<Double>) {
val newOther = broadcastTo(other.tensor, tensor.shape) val newOther = broadcastTo(arg.tensor, tensor.shape)
for (i in 0 until tensor.indices.linearSize) { for (i in 0 until tensor.indices.linearSize) {
tensor.mutableBuffer.array()[tensor.bufferStart + i] += tensor.mutableBuffer.array()[tensor.bufferStart + i] +=
newOther.mutableBuffer.array()[tensor.bufferStart + i] newOther.mutableBuffer.array()[tensor.bufferStart + i]
} }
} }
override fun StructureND<Double>.minus(other: StructureND<Double>): DoubleTensor { override fun StructureND<Double>.minus(arg: StructureND<Double>): DoubleTensor {
val broadcast = broadcastTensors(tensor, other.tensor) val broadcast = broadcastTensors(tensor, arg.tensor)
val newThis = broadcast[0] val newThis = broadcast[0]
val newOther = broadcast[1] val newOther = broadcast[1]
val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> val resBuffer = DoubleArray(newThis.indices.linearSize) { i ->
@ -47,16 +47,16 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
return DoubleTensor(newThis.shape, resBuffer) return DoubleTensor(newThis.shape, resBuffer)
} }
override fun Tensor<Double>.minusAssign(other: StructureND<Double>) { override fun Tensor<Double>.minusAssign(arg: StructureND<Double>) {
val newOther = broadcastTo(other.tensor, tensor.shape) val newOther = broadcastTo(arg.tensor, tensor.shape)
for (i in 0 until tensor.indices.linearSize) { for (i in 0 until tensor.indices.linearSize) {
tensor.mutableBuffer.array()[tensor.bufferStart + i] -= tensor.mutableBuffer.array()[tensor.bufferStart + i] -=
newOther.mutableBuffer.array()[tensor.bufferStart + i] newOther.mutableBuffer.array()[tensor.bufferStart + i]
} }
} }
override fun StructureND<Double>.times(other: StructureND<Double>): DoubleTensor { override fun StructureND<Double>.times(arg: StructureND<Double>): DoubleTensor {
val broadcast = broadcastTensors(tensor, other.tensor) val broadcast = broadcastTensors(tensor, arg.tensor)
val newThis = broadcast[0] val newThis = broadcast[0]
val newOther = broadcast[1] val newOther = broadcast[1]
val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> val resBuffer = DoubleArray(newThis.indices.linearSize) { i ->
@ -66,8 +66,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
return DoubleTensor(newThis.shape, resBuffer) return DoubleTensor(newThis.shape, resBuffer)
} }
override fun Tensor<Double>.timesAssign(other: StructureND<Double>) { override fun Tensor<Double>.timesAssign(arg: StructureND<Double>) {
val newOther = broadcastTo(other.tensor, tensor.shape) val newOther = broadcastTo(arg.tensor, tensor.shape)
for (i in 0 until tensor.indices.linearSize) { for (i in 0 until tensor.indices.linearSize) {
tensor.mutableBuffer.array()[tensor.bufferStart + i] *= tensor.mutableBuffer.array()[tensor.bufferStart + i] *=
newOther.mutableBuffer.array()[tensor.bufferStart + i] newOther.mutableBuffer.array()[tensor.bufferStart + i]

View File

@ -23,8 +23,7 @@ public open class BufferedTensor<T> internal constructor(
/** /**
* Buffer strides based on [TensorLinearStructure] implementation * Buffer strides based on [TensorLinearStructure] implementation
*/ */
public val indices: Strides override val indices: Strides get() = TensorLinearStructure(shape)
get() = TensorLinearStructure(shape)
/** /**
* Number of elements in tensor * Number of elements in tensor
@ -39,7 +38,7 @@ public open class BufferedTensor<T> internal constructor(
} }
@PerformancePitfall @PerformancePitfall
override fun elements(): Sequence<Pair<IntArray, T>> = indices.indices().map { override fun elements(): Sequence<Pair<IntArray, T>> = indices.asSequence().map {
it to get(it) it to get(it)
} }
} }

View File

@ -112,7 +112,7 @@ public open class DoubleTensorAlgebra :
*/ */
override fun structureND(shape: IntArray, initializer: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray( override fun structureND(shape: IntArray, initializer: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray(
shape, shape,
TensorLinearStructure(shape).indices().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray() TensorLinearStructure(shape).asSequence().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray()
) )
override operator fun StructureND<Double>.get(i: Int): DoubleTensor { override operator fun StructureND<Double>.get(i: Int): DoubleTensor {
@ -201,19 +201,19 @@ public open class DoubleTensorAlgebra :
public fun StructureND<Double>.copy(): DoubleTensor = public fun StructureND<Double>.copy(): DoubleTensor =
DoubleTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart) DoubleTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart)
override fun Double.plus(other: StructureND<Double>): DoubleTensor { override fun Double.plus(arg: StructureND<Double>): DoubleTensor {
val resBuffer = DoubleArray(other.tensor.numElements) { i -> val resBuffer = DoubleArray(arg.tensor.numElements) { i ->
other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] + this arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + this
} }
return DoubleTensor(other.shape, resBuffer) return DoubleTensor(arg.shape, resBuffer)
} }
override fun StructureND<Double>.plus(arg: Double): DoubleTensor = arg + tensor override fun StructureND<Double>.plus(arg: Double): DoubleTensor = arg + tensor
override fun StructureND<Double>.plus(other: StructureND<Double>): DoubleTensor { override fun StructureND<Double>.plus(arg: StructureND<Double>): DoubleTensor {
checkShapesCompatible(tensor, other.tensor) checkShapesCompatible(tensor, arg.tensor)
val resBuffer = DoubleArray(tensor.numElements) { i -> val resBuffer = DoubleArray(tensor.numElements) { i ->
tensor.mutableBuffer.array()[i] + other.tensor.mutableBuffer.array()[i] tensor.mutableBuffer.array()[i] + arg.tensor.mutableBuffer.array()[i]
} }
return DoubleTensor(tensor.shape, resBuffer) return DoubleTensor(tensor.shape, resBuffer)
} }
@ -224,19 +224,19 @@ public open class DoubleTensorAlgebra :
} }
} }
override fun Tensor<Double>.plusAssign(other: StructureND<Double>) { override fun Tensor<Double>.plusAssign(arg: StructureND<Double>) {
checkShapesCompatible(tensor, other.tensor) checkShapesCompatible(tensor, arg.tensor)
for (i in 0 until tensor.numElements) { for (i in 0 until tensor.numElements) {
tensor.mutableBuffer.array()[tensor.bufferStart + i] += tensor.mutableBuffer.array()[tensor.bufferStart + i] +=
other.tensor.mutableBuffer.array()[tensor.bufferStart + i] arg.tensor.mutableBuffer.array()[tensor.bufferStart + i]
} }
} }
override fun Double.minus(other: StructureND<Double>): DoubleTensor { override fun Double.minus(arg: StructureND<Double>): DoubleTensor {
val resBuffer = DoubleArray(other.tensor.numElements) { i -> val resBuffer = DoubleArray(arg.tensor.numElements) { i ->
this - other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] this - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i]
} }
return DoubleTensor(other.shape, resBuffer) return DoubleTensor(arg.shape, resBuffer)
} }
override fun StructureND<Double>.minus(arg: Double): DoubleTensor { override fun StructureND<Double>.minus(arg: Double): DoubleTensor {
@ -246,10 +246,10 @@ public open class DoubleTensorAlgebra :
return DoubleTensor(tensor.shape, resBuffer) return DoubleTensor(tensor.shape, resBuffer)
} }
override fun StructureND<Double>.minus(other: StructureND<Double>): DoubleTensor { override fun StructureND<Double>.minus(arg: StructureND<Double>): DoubleTensor {
checkShapesCompatible(tensor, other) checkShapesCompatible(tensor, arg)
val resBuffer = DoubleArray(tensor.numElements) { i -> val resBuffer = DoubleArray(tensor.numElements) { i ->
tensor.mutableBuffer.array()[i] - other.tensor.mutableBuffer.array()[i] tensor.mutableBuffer.array()[i] - arg.tensor.mutableBuffer.array()[i]
} }
return DoubleTensor(tensor.shape, resBuffer) return DoubleTensor(tensor.shape, resBuffer)
} }
@ -260,11 +260,11 @@ public open class DoubleTensorAlgebra :
} }
} }
override fun Tensor<Double>.minusAssign(other: StructureND<Double>) { override fun Tensor<Double>.minusAssign(arg: StructureND<Double>) {
checkShapesCompatible(tensor, other) checkShapesCompatible(tensor, arg)
for (i in 0 until tensor.numElements) { for (i in 0 until tensor.numElements) {
tensor.mutableBuffer.array()[tensor.bufferStart + i] -= tensor.mutableBuffer.array()[tensor.bufferStart + i] -=
other.tensor.mutableBuffer.array()[tensor.bufferStart + i] arg.tensor.mutableBuffer.array()[tensor.bufferStart + i]
} }
} }
@ -277,11 +277,11 @@ public open class DoubleTensorAlgebra :
override fun StructureND<Double>.times(arg: Double): DoubleTensor = arg * tensor override fun StructureND<Double>.times(arg: Double): DoubleTensor = arg * tensor
override fun StructureND<Double>.times(other: StructureND<Double>): DoubleTensor { override fun StructureND<Double>.times(arg: StructureND<Double>): DoubleTensor {
checkShapesCompatible(tensor, other) checkShapesCompatible(tensor, arg)
val resBuffer = DoubleArray(tensor.numElements) { i -> val resBuffer = DoubleArray(tensor.numElements) { i ->
tensor.mutableBuffer.array()[tensor.bufferStart + i] * tensor.mutableBuffer.array()[tensor.bufferStart + i] *
other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i]
} }
return DoubleTensor(tensor.shape, resBuffer) return DoubleTensor(tensor.shape, resBuffer)
} }
@ -292,11 +292,11 @@ public open class DoubleTensorAlgebra :
} }
} }
override fun Tensor<Double>.timesAssign(other: StructureND<Double>) { override fun Tensor<Double>.timesAssign(arg: StructureND<Double>) {
checkShapesCompatible(tensor, other) checkShapesCompatible(tensor, arg)
for (i in 0 until tensor.numElements) { for (i in 0 until tensor.numElements) {
tensor.mutableBuffer.array()[tensor.bufferStart + i] *= tensor.mutableBuffer.array()[tensor.bufferStart + i] *=
other.tensor.mutableBuffer.array()[tensor.bufferStart + i] arg.tensor.mutableBuffer.array()[tensor.bufferStart + i]
} }
} }
@ -368,12 +368,12 @@ public open class DoubleTensorAlgebra :
return resTensor return resTensor
} }
override fun StructureND<Double>.view(shape: IntArray): DoubleTensor { override fun Tensor<Double>.view(shape: IntArray): DoubleTensor {
checkView(tensor, shape) checkView(tensor, shape)
return DoubleTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart) return DoubleTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart)
} }
override fun StructureND<Double>.viewAs(other: StructureND<Double>): DoubleTensor = override fun Tensor<Double>.viewAs(other: StructureND<Double>): DoubleTensor =
tensor.view(other.shape) tensor.view(other.shape)
override infix fun StructureND<Double>.dot(other: StructureND<Double>): DoubleTensor { override infix fun StructureND<Double>.dot(other: StructureND<Double>): DoubleTensor {
@ -584,7 +584,7 @@ public open class DoubleTensorAlgebra :
} }
val resNumElements = resShape.reduce(Int::times) val resNumElements = resShape.reduce(Int::times)
val resTensor = DoubleTensor(resShape, DoubleArray(resNumElements) { 0.0 }, 0) val resTensor = DoubleTensor(resShape, DoubleArray(resNumElements) { 0.0 }, 0)
for (index in resTensor.indices.indices()) { for (index in resTensor.indices.asSequence()) {
val prefix = index.take(dim).toIntArray() val prefix = index.take(dim).toIntArray()
val suffix = index.takeLast(dimension - dim - 1).toIntArray() val suffix = index.takeLast(dimension - dim - 1).toIntArray()
resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i -> resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i ->

View File

@ -22,7 +22,7 @@ internal fun BufferedTensor<Double>.asTensor(): DoubleTensor =
internal fun <T> StructureND<T>.copyToBufferedTensor(): BufferedTensor<T> = internal fun <T> StructureND<T>.copyToBufferedTensor(): BufferedTensor<T> =
BufferedTensor( BufferedTensor(
this.shape, this.shape,
TensorLinearStructure(this.shape).indices().map(this::get).toMutableList().asMutableBuffer(), 0 TensorLinearStructure(this.shape).asSequence().map(this::get).toMutableList().asMutableBuffer(), 0
) )
internal fun <T> StructureND<T>.toBufferedTensor(): BufferedTensor<T> = when (this) { internal fun <T> StructureND<T>.toBufferedTensor(): BufferedTensor<T> = when (this) {

View File

@ -28,7 +28,7 @@ public open class ViktorFieldOpsND :
override fun structureND(shape: IntArray, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND = override fun structureND(shape: IntArray, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND =
F64Array(*shape).apply { F64Array(*shape).apply {
DefaultStrides(shape).indices().forEach { index -> DefaultStrides(shape).asSequence().forEach { index ->
set(value = DoubleField.initializer(index), indices = index) set(value = DoubleField.initializer(index), indices = index)
} }
}.asStructure() }.asStructure()
@ -37,7 +37,7 @@ public open class ViktorFieldOpsND :
override fun StructureND<Double>.map(transform: DoubleField.(Double) -> Double): ViktorStructureND = override fun StructureND<Double>.map(transform: DoubleField.(Double) -> Double): ViktorStructureND =
F64Array(*shape).apply { F64Array(*shape).apply {
DefaultStrides(shape).indices().forEach { index -> DefaultStrides(shape).asSequence().forEach { index ->
set(value = DoubleField.transform(this@map[index]), indices = index) set(value = DoubleField.transform(this@map[index]), indices = index)
} }
}.asStructure() }.asStructure()
@ -45,7 +45,7 @@ public open class ViktorFieldOpsND :
override fun StructureND<Double>.mapIndexed( override fun StructureND<Double>.mapIndexed(
transform: DoubleField.(index: IntArray, Double) -> Double, transform: DoubleField.(index: IntArray, Double) -> Double,
): ViktorStructureND = F64Array(*shape).apply { ): ViktorStructureND = F64Array(*shape).apply {
DefaultStrides(shape).indices().forEach { index -> DefaultStrides(shape).asSequence().forEach { index ->
set(value = DoubleField.transform(index, this@mapIndexed[index]), indices = index) set(value = DoubleField.transform(index, this@mapIndexed[index]), indices = index)
} }
}.asStructure() }.asStructure()
@ -57,7 +57,7 @@ public open class ViktorFieldOpsND :
): ViktorStructureND { ): ViktorStructureND {
require(left.shape.contentEquals(right.shape)) require(left.shape.contentEquals(right.shape))
return F64Array(*left.shape).apply { return F64Array(*left.shape).apply {
DefaultStrides(left.shape).indices().forEach { index -> DefaultStrides(left.shape).asSequence().forEach { index ->
set(value = DoubleField.transform(left[index], right[index]), indices = index) set(value = DoubleField.transform(left[index], right[index]), indices = index)
} }
}.asStructure() }.asStructure()
@ -69,11 +69,11 @@ public open class ViktorFieldOpsND :
override fun scale(a: StructureND<Double>, value: Double): ViktorStructureND = override fun scale(a: StructureND<Double>, value: Double): ViktorStructureND =
(a.f64Buffer * value).asStructure() (a.f64Buffer * value).asStructure()
override fun StructureND<Double>.plus(other: StructureND<Double>): ViktorStructureND = override fun StructureND<Double>.plus(arg: StructureND<Double>): ViktorStructureND =
(f64Buffer + other.f64Buffer).asStructure() (f64Buffer + arg.f64Buffer).asStructure()
override fun StructureND<Double>.minus(other: StructureND<Double>): ViktorStructureND = override fun StructureND<Double>.minus(arg: StructureND<Double>): ViktorStructureND =
(f64Buffer - other.f64Buffer).asStructure() (f64Buffer - arg.f64Buffer).asStructure()
override fun StructureND<Double>.times(k: Number): ViktorStructureND = override fun StructureND<Double>.times(k: Number): ViktorStructureND =
(f64Buffer * k.toDouble()).asStructure() (f64Buffer * k.toDouble()).asStructure()

View File

@ -22,7 +22,7 @@ public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructur
@PerformancePitfall @PerformancePitfall
override fun elements(): Sequence<Pair<IntArray, Double>> = override fun elements(): Sequence<Pair<IntArray, Double>> =
DefaultStrides(shape).indices().map { it to get(it) } DefaultStrides(shape).asSequence().map { it to get(it) }
} }
public fun F64Array.asStructure(): ViktorStructureND = ViktorStructureND(this) public fun F64Array.asStructure(): ViktorStructureND = ViktorStructureND(this)