From 835d64d797411141a1b21948566651d6dace882e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sat, 16 Jan 2021 19:29:47 +0000 Subject: [PATCH 001/211] Initial draft for TensorAlgebra --- .gitignore | 1 + .../kmath/structures/TensorAlgebra.kt | 49 +++++++++++++++++++ .../kmath/structures/TensorStructure.kt | 11 +++++ 3 files changed, 61 insertions(+) create mode 100644 kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorStructure.kt diff --git a/.gitignore b/.gitignore index bade7f08c..ea8e65fb4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ build/ out/ .idea/ +.vscode/ # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) !gradle-wrapper.jar diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorAlgebra.kt new file mode 100644 index 000000000..f960742ee --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorAlgebra.kt @@ -0,0 +1,49 @@ +package kscience.kmath.structures + + +import kscience.kmath.operations.* + +public interface TensorAlgebra> : Ring { + + public operator fun T.plus(other: TorchTensorType): TorchTensorType + public operator fun TorchTensorType.plus(value: T): TorchTensorType + public operator fun TorchTensorType.plusAssign(value: T): Unit + public operator fun TorchTensorType.plusAssign(b: TorchTensorType): Unit + + public operator fun T.minus(other: TorchTensorType): TorchTensorType + public operator fun TorchTensorType.minus(value: T): TorchTensorType + public operator fun TorchTensorType.minusAssign(value: T): Unit + public operator fun TorchTensorType.minusAssign(b: TorchTensorType): Unit + + public operator fun T.times(other: TorchTensorType): TorchTensorType + public operator fun TorchTensorType.times(value: T): TorchTensorType + public operator fun TorchTensorType.timesAssign(value: T): Unit + public operator fun TorchTensorType.timesAssign(b: TorchTensorType): Unit + + public infix fun TorchTensorType.dot(b: TorchTensorType): TorchTensorType + + public fun diagonalEmbedding( + diagonalEntries: TorchTensorType, + offset: Int = 0, dim1: Int = -2, dim2: Int = -1 + ): TorchTensorType + + public fun TorchTensorType.transpose(i: Int, j: Int): TorchTensorType + public fun TorchTensorType.view(shape: IntArray): TorchTensorType + + public fun TorchTensorType.abs(): TorchTensorType + public fun TorchTensorType.sum(): TorchTensorType + +} + +public interface TensorFieldAlgebra> : + TensorAlgebra, Field { + + public operator fun TorchTensorType.divAssign(b: TorchTensorType) + + public fun TorchTensorType.exp(): TorchTensorType + public fun TorchTensorType.log(): TorchTensorType + + public fun TorchTensorType.svd(): Triple + public fun TorchTensorType.symEig(eigenvectors: Boolean = true): Pair + +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorStructure.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorStructure.kt new file mode 100644 index 000000000..6e3ac0b7b --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorStructure.kt @@ -0,0 +1,11 @@ +package kscience.kmath.structures + +public abstract class TensorStructure: MutableNDStructure { + + // A tensor can have empty shape, in which case it represents just a value + public abstract fun value(): T + + // Tensors are mutable and might hold shared resources + override fun equals(other: Any?): Boolean = false + override fun hashCode(): Int = 0 +} \ No newline at end of file From ecf813803b04f55b602ad50d23d53d13e0b300cb Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 18 Jan 2021 07:57:13 +0000 Subject: [PATCH 002/211] Correcting terminology and failed connection to Algebra --- .gitignore | 3 + .../kmath/structures/TensorAlgebra.kt | 99 +++++++++++-------- .../kmath/structures/TensorStructure.kt | 11 --- 3 files changed, 62 insertions(+), 51 deletions(-) delete mode 100644 kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorStructure.kt diff --git a/.gitignore b/.gitignore index ea8e65fb4..f32005cd2 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ out/ # Cache of project .gradletasknamecache + +# Generated by javac -h +*.class \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorAlgebra.kt index f960742ee..ca7619429 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorAlgebra.kt @@ -1,49 +1,68 @@ package kscience.kmath.structures - -import kscience.kmath.operations.* - -public interface TensorAlgebra> : Ring { - - public operator fun T.plus(other: TorchTensorType): TorchTensorType - public operator fun TorchTensorType.plus(value: T): TorchTensorType - public operator fun TorchTensorType.plusAssign(value: T): Unit - public operator fun TorchTensorType.plusAssign(b: TorchTensorType): Unit - - public operator fun T.minus(other: TorchTensorType): TorchTensorType - public operator fun TorchTensorType.minus(value: T): TorchTensorType - public operator fun TorchTensorType.minusAssign(value: T): Unit - public operator fun TorchTensorType.minusAssign(b: TorchTensorType): Unit - - public operator fun T.times(other: TorchTensorType): TorchTensorType - public operator fun TorchTensorType.times(value: T): TorchTensorType - public operator fun TorchTensorType.timesAssign(value: T): Unit - public operator fun TorchTensorType.timesAssign(b: TorchTensorType): Unit - - public infix fun TorchTensorType.dot(b: TorchTensorType): TorchTensorType - - public fun diagonalEmbedding( - diagonalEntries: TorchTensorType, - offset: Int = 0, dim1: Int = -2, dim2: Int = -1 - ): TorchTensorType - - public fun TorchTensorType.transpose(i: Int, j: Int): TorchTensorType - public fun TorchTensorType.view(shape: IntArray): TorchTensorType - - public fun TorchTensorType.abs(): TorchTensorType - public fun TorchTensorType.sum(): TorchTensorType - +public interface TensorStructure : MutableNDStructure { + // A tensor can have empty shape, in which case it represents just a value + public abstract fun value(): T } -public interface TensorFieldAlgebra> : - TensorAlgebra, Field { +// https://proofwiki.org/wiki/Definition:Algebra_over_Ring - public operator fun TorchTensorType.divAssign(b: TorchTensorType) +public interface TensorAlgebra> { - public fun TorchTensorType.exp(): TorchTensorType - public fun TorchTensorType.log(): TorchTensorType + public operator fun T.plus(other: TensorType): TensorType + public operator fun TensorType.plus(value: T): TensorType + public operator fun TensorType.plus(other: TensorType): TensorType + public operator fun TensorType.plusAssign(value: T): Unit + public operator fun TensorType.plusAssign(other: TensorType): Unit - public fun TorchTensorType.svd(): Triple - public fun TorchTensorType.symEig(eigenvectors: Boolean = true): Pair + public operator fun T.minus(other: TensorType): TensorType + public operator fun TensorType.minus(value: T): TensorType + public operator fun TensorType.minus(other: TensorType): TensorType + public operator fun TensorType.minusAssign(value: T): Unit + public operator fun TensorType.minusAssign(other: TensorType): Unit + + public operator fun T.times(other: TensorType): TensorType + public operator fun TensorType.times(value: T): TensorType + public operator fun TensorType.times(other: TensorType): TensorType + public operator fun TensorType.timesAssign(value: T): Unit + public operator fun TensorType.timesAssign(other: TensorType): Unit + public operator fun TensorType.unaryMinus(): TensorType + + + public infix fun TensorType.dot(other: TensorType): TensorType + public infix fun TensorType.dotAssign(other: TensorType): Unit + public infix fun TensorType.dotRightAssign(other: TensorType): Unit + + public fun diagonalEmbedding( + diagonalEntries: TensorType, + offset: Int = 0, dim1: Int = -2, dim2: Int = -1 + ): TensorType + + public fun TensorType.transpose(i: Int, j: Int): TensorType + public fun TensorType.transposeAssign(i: Int, j: Int): Unit + + public fun TensorType.view(shape: IntArray): TensorType + + public fun TensorType.abs(): TensorType + public fun TensorType.absAssign(): Unit + public fun TensorType.sum(): TensorType + public fun TensorType.sumAssign(): Unit +} + +// https://proofwiki.org/wiki/Definition:Division_Algebra + +public interface TensorPartialDivisionAlgebra> : + TensorAlgebra { + + public operator fun TensorType.div(other: TensorType): TensorType + public operator fun TensorType.divAssign(other: TensorType) + + public fun TensorType.exp(): TensorType + public fun TensorType.expAssign(): Unit + public fun TensorType.log(): TensorType + public fun TensorType.logAssign(): Unit + + public fun TensorType.svd(): Triple + public fun TensorType.symEig(eigenvectors: Boolean = true): Pair } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorStructure.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorStructure.kt deleted file mode 100644 index 6e3ac0b7b..000000000 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorStructure.kt +++ /dev/null @@ -1,11 +0,0 @@ -package kscience.kmath.structures - -public abstract class TensorStructure: MutableNDStructure { - - // A tensor can have empty shape, in which case it represents just a value - public abstract fun value(): T - - // Tensors are mutable and might hold shared resources - override fun equals(other: Any?): Boolean = false - override fun hashCode(): Int = 0 -} \ No newline at end of file From 360e0e17e94d997088915fda214a663a0928bfb9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 19 Jan 2021 22:24:42 +0300 Subject: [PATCH 003/211] Minor optimization for RealNDAlgebra --- .../ast/ExpressionsInterpretersBenchmark.kt | 4 +- .../kscience/kmath/benchmarks/DotBenchmark.kt | 20 ++++----- .../kmath/benchmarks/LargeNDBenchmark.kt | 25 ----------- .../benchmarks/LinearAlgebraBenchmark.kt | 8 +--- .../FunctionalExpressionAlgebra.kt | 5 ++- .../kscience/kmath/linear/LupDecomposition.kt | 1 + .../kscience/kmath/operations/Complex.kt | 2 + .../kscience/kmath/structures/RealNDField.kt | 41 +++++++++---------- .../kscience/kmath/linear/MatrixTest.kt | 1 + .../kmath/structures/NumberNDFieldTest.kt | 1 + .../kscience/dimensions/DMatrixContextTest.kt | 1 + 11 files changed, 42 insertions(+), 67 deletions(-) delete mode 100644 examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LargeNDBenchmark.kt diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt index 6acaca84d..c5edcdedf 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt @@ -28,7 +28,7 @@ internal class ExpressionsInterpretersBenchmark { @Benchmark fun mstExpression() { val expr = algebra.mstInField { - symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) + symbol("x") * 2.0 + 2.0 / symbol("x") - 16.0 } invokeAndSum(expr) @@ -37,7 +37,7 @@ internal class ExpressionsInterpretersBenchmark { @Benchmark fun asmExpression() { val expr = algebra.mstInField { - symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) + symbol("x") * 2.0 + 2.0 / symbol("x") - 16.0 }.compile() invokeAndSum(expr) diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/DotBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/DotBenchmark.kt index 8823e86db..5c59afaee 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/DotBenchmark.kt @@ -2,9 +2,8 @@ package kscience.kmath.benchmarks import kotlinx.benchmark.Benchmark import kscience.kmath.commons.linear.CMMatrixContext -import kscience.kmath.commons.linear.toCM import kscience.kmath.ejml.EjmlMatrixContext -import kscience.kmath.ejml.toEjml + import kscience.kmath.linear.BufferMatrixContext import kscience.kmath.linear.RealMatrixContext import kscience.kmath.linear.real @@ -26,11 +25,11 @@ class DotBenchmark { val matrix1 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } val matrix2 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } - val cmMatrix1 = matrix1.toCM() - val cmMatrix2 = matrix2.toCM() + val cmMatrix1 = CMMatrixContext { matrix1.toCM() } + val cmMatrix2 = CMMatrixContext { matrix2.toCM() } - val ejmlMatrix1 = matrix1.toEjml() - val ejmlMatrix2 = matrix2.toEjml() + val ejmlMatrix1 = EjmlMatrixContext { matrix1.toEjml() } + val ejmlMatrix2 = EjmlMatrixContext { matrix2.toEjml() } } @Benchmark @@ -49,22 +48,23 @@ class DotBenchmark { @Benchmark fun ejmlMultiplicationwithConversion() { - val ejmlMatrix1 = matrix1.toEjml() - val ejmlMatrix2 = matrix2.toEjml() EjmlMatrixContext { + val ejmlMatrix1 = matrix1.toEjml() + val ejmlMatrix2 = matrix2.toEjml() + ejmlMatrix1 dot ejmlMatrix2 } } @Benchmark fun bufferedMultiplication() { - BufferMatrixContext(RealField, Buffer.Companion::real).invoke{ + BufferMatrixContext(RealField, Buffer.Companion::real).invoke { matrix1 dot matrix2 } } @Benchmark - fun realMultiplication(){ + fun realMultiplication() { RealMatrixContext { matrix1 dot matrix2 } diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LargeNDBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LargeNDBenchmark.kt deleted file mode 100644 index 395fde619..000000000 --- a/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LargeNDBenchmark.kt +++ /dev/null @@ -1,25 +0,0 @@ -package kscience.kmath.benchmarks - -import kscience.kmath.structures.NDField -import org.openjdk.jmh.annotations.Benchmark -import org.openjdk.jmh.annotations.Scope -import org.openjdk.jmh.annotations.State -import org.openjdk.jmh.infra.Blackhole -import kotlin.random.Random - -@State(Scope.Benchmark) -class LargeNDBenchmark { - val arraySize = 10000 - val RANDOM = Random(222) - val src1 = DoubleArray(arraySize) { RANDOM.nextDouble() } - val src2 = DoubleArray(arraySize) { RANDOM.nextDouble() } - val field = NDField.real(arraySize) - val kmathArray1 = field.produce { (a) -> src1[a] } - val kmathArray2 = field.produce { (a) -> src2[a] } - - @Benchmark - fun test10000(bh: Blackhole) { - bh.consume(field.add(kmathArray1, kmathArray2)) - } - -} \ No newline at end of file diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt index ec8714617..5ff43ef80 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt @@ -5,10 +5,8 @@ import kotlinx.benchmark.Benchmark import kscience.kmath.commons.linear.CMMatrixContext import kscience.kmath.commons.linear.CMMatrixContext.dot import kscience.kmath.commons.linear.inverse -import kscience.kmath.commons.linear.toCM import kscience.kmath.ejml.EjmlMatrixContext import kscience.kmath.ejml.inverse -import kscience.kmath.ejml.toEjml import kscience.kmath.operations.invoke import kscience.kmath.structures.Matrix import org.openjdk.jmh.annotations.Scope @@ -35,16 +33,14 @@ class LinearAlgebraBenchmark { @Benchmark fun cmLUPInversion() { CMMatrixContext { - val cm = matrix.toCM() //avoid overhead on conversion - inverse(cm) + inverse(matrix) } } @Benchmark fun ejmlInverse() { EjmlMatrixContext { - val km = matrix.toEjml() //avoid overhead on conversion - inverse(km) + inverse(matrix) } } } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index 880a4e34c..1a3668855 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -95,8 +95,9 @@ public open class FunctionalExpressionRing>( super.binaryOperationFunction(operation) } -public open class FunctionalExpressionField>(algebra: A) : - FunctionalExpressionRing(algebra), Field> { +public open class FunctionalExpressionField>( + algebra: A, +) : FunctionalExpressionRing(algebra), Field> { /** * Builds an Expression of division an expression by another one. */ diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LupDecomposition.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LupDecomposition.kt index f4f998da2..5cf7c8f70 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LupDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LupDecomposition.kt @@ -224,6 +224,7 @@ public inline fun , F : Field> GenericMatrixContext ): Matrix = solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum), bufferFactory, checkSingular) +@OptIn(UnstableKMathAPI::class) public fun RealMatrixContext.solveWithLUP(a: Matrix, b: Matrix): Matrix { // Use existing decomposition if it is provided by matrix val bufferFactory: MutableBufferFactory = MutableBuffer.Companion::real diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt index 5695e6696..c6409c015 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt @@ -3,6 +3,7 @@ package kscience.kmath.operations import kscience.kmath.memory.MemoryReader import kscience.kmath.memory.MemorySpec import kscience.kmath.memory.MemoryWriter +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.structures.Buffer import kscience.kmath.structures.MemoryBuffer import kscience.kmath.structures.MutableBuffer @@ -41,6 +42,7 @@ private val PI_DIV_2 = Complex(PI / 2, 0) /** * A field of [Complex]. */ +@OptIn(UnstableKMathAPI::class) public object ComplexField : ExtendedField, Norm, RingWithNumbers { override val zero: Complex = 0.0.toComplex() override val one: Complex = 1.0.toComplex() diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealNDField.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealNDField.kt index 3eb1dc4ca..60e6de440 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealNDField.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealNDField.kt @@ -11,7 +11,7 @@ public typealias RealNDElement = BufferedNDFieldElement public class RealNDField(override val shape: IntArray) : BufferedNDField, ExtendedNDField>, - RingWithNumbers>{ + RingWithNumbers> { override val strides: Strides = DefaultStrides(shape) @@ -24,35 +24,31 @@ public class RealNDField(override val shape: IntArray) : return produce { d } } - private inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Double): Buffer = - RealBuffer(DoubleArray(size) { initializer(it) }) - - /** - * Inline transform an NDStructure to - */ - override fun map( + @Suppress("OVERRIDE_BY_INLINE") + override inline fun map( arg: NDBuffer, - transform: RealField.(Double) -> Double + transform: RealField.(Double) -> Double, ): RealNDElement { check(arg) - val array = buildBuffer(arg.strides.linearSize) { offset -> RealField.transform(arg.buffer[offset]) } + val array = RealBuffer(arg.strides.linearSize) { offset -> RealField.transform(arg.buffer[offset]) } return BufferedNDFieldElement(this, array) } - override fun produce(initializer: RealField.(IntArray) -> Double): RealNDElement { - val array = buildBuffer(strides.linearSize) { offset -> elementContext.initializer(strides.index(offset)) } + @Suppress("OVERRIDE_BY_INLINE") + override inline fun produce(initializer: RealField.(IntArray) -> Double): RealNDElement { + val array = RealBuffer(strides.linearSize) { offset -> elementContext.initializer(strides.index(offset)) } return BufferedNDFieldElement(this, array) } - override fun mapIndexed( + @Suppress("OVERRIDE_BY_INLINE") + override inline fun mapIndexed( arg: NDBuffer, - transform: RealField.(index: IntArray, Double) -> Double + transform: RealField.(index: IntArray, Double) -> Double, ): RealNDElement { check(arg) - return BufferedNDFieldElement( this, - buildBuffer(arg.strides.linearSize) { offset -> + RealBuffer(arg.strides.linearSize) { offset -> elementContext.transform( arg.strides.index(offset), arg.buffer[offset] @@ -60,16 +56,17 @@ public class RealNDField(override val shape: IntArray) : }) } - override fun combine( + @Suppress("OVERRIDE_BY_INLINE") + override inline fun combine( a: NDBuffer, b: NDBuffer, - transform: RealField.(Double, Double) -> Double + transform: RealField.(Double, Double) -> Double, ): RealNDElement { check(a, b) - return BufferedNDFieldElement( - this, - buildBuffer(strides.linearSize) { offset -> elementContext.transform(a.buffer[offset], b.buffer[offset]) } - ) + val buffer = RealBuffer(strides.linearSize) { offset -> + elementContext.transform(a.buffer[offset], b.buffer[offset]) + } + return BufferedNDFieldElement(this, buffer) } override fun NDBuffer.toElement(): FieldElement, *, out BufferedNDField> = diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/MatrixTest.kt index 0a582e339..d7755dcb5 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/MatrixTest.kt @@ -7,6 +7,7 @@ import kscience.kmath.structures.as2D import kotlin.test.Test import kotlin.test.assertEquals +@Suppress("UNUSED_VARIABLE") class MatrixTest { @Test fun testTranspose() { diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NumberNDFieldTest.kt index f5e008ef3..22a0d3629 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NumberNDFieldTest.kt @@ -8,6 +8,7 @@ import kotlin.math.pow import kotlin.test.Test import kotlin.test.assertEquals +@Suppress("UNUSED_VARIABLE") class NumberNDFieldTest { val array1: RealNDElement = real2D(3, 3) { i, j -> (i + j).toDouble() } val array2: RealNDElement = real2D(3, 3) { i, j -> (i - j).toDouble() } diff --git a/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt b/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt index 5b330fcce..b9193d4dd 100644 --- a/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt +++ b/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt @@ -6,6 +6,7 @@ import kscience.kmath.dimensions.DMatrixContext import kscience.kmath.dimensions.one import kotlin.test.Test +@Suppress("UNUSED_VARIABLE") internal class DMatrixContextTest { @Test fun testDimensionSafeMatrix() { From a11711c336e7698a7cf418e5e727d3ed338cb45c Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 19 Jan 2021 22:25:04 +0300 Subject: [PATCH 004/211] Tensor algebra refactoring --- .../{structures => tensors}/TensorAlgebra.kt | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) rename kmath-core/src/commonMain/kotlin/kscience/kmath/{structures => tensors}/TensorAlgebra.kt (76%) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/tensors/TensorAlgebra.kt similarity index 76% rename from kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/tensors/TensorAlgebra.kt index ca7619429..c40544579 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/tensors/TensorAlgebra.kt @@ -1,32 +1,36 @@ -package kscience.kmath.structures +package kscience.kmath.tensors -public interface TensorStructure : MutableNDStructure { - // A tensor can have empty shape, in which case it represents just a value - public abstract fun value(): T -} +import kscience.kmath.operations.Ring +import kscience.kmath.structures.MutableNDStructure + +public typealias Tensor = MutableNDStructure + +public val Tensor.value: T + get() { + require(shape.contentEquals(intArrayOf(1))) { "Value available only for a tensor with no dimensions" } + return get(intArrayOf(0)) + } // https://proofwiki.org/wiki/Definition:Algebra_over_Ring - -public interface TensorAlgebra> { +/** + * To be moved to a separate project + */ +public interface TensorAlgebra> : Ring { public operator fun T.plus(other: TensorType): TensorType public operator fun TensorType.plus(value: T): TensorType - public operator fun TensorType.plus(other: TensorType): TensorType public operator fun TensorType.plusAssign(value: T): Unit public operator fun TensorType.plusAssign(other: TensorType): Unit public operator fun T.minus(other: TensorType): TensorType public operator fun TensorType.minus(value: T): TensorType - public operator fun TensorType.minus(other: TensorType): TensorType public operator fun TensorType.minusAssign(value: T): Unit public operator fun TensorType.minusAssign(other: TensorType): Unit public operator fun T.times(other: TensorType): TensorType public operator fun TensorType.times(value: T): TensorType - public operator fun TensorType.times(other: TensorType): TensorType public operator fun TensorType.timesAssign(value: T): Unit public operator fun TensorType.timesAssign(other: TensorType): Unit - public operator fun TensorType.unaryMinus(): TensorType public infix fun TensorType.dot(other: TensorType): TensorType @@ -35,7 +39,7 @@ public interface TensorAlgebra> { public fun diagonalEmbedding( diagonalEntries: TensorType, - offset: Int = 0, dim1: Int = -2, dim2: Int = -1 + offset: Int = 0, dim1: Int = -2, dim2: Int = -1, ): TensorType public fun TensorType.transpose(i: Int, j: Int): TensorType @@ -51,8 +55,7 @@ public interface TensorAlgebra> { // https://proofwiki.org/wiki/Definition:Division_Algebra -public interface TensorPartialDivisionAlgebra> : - TensorAlgebra { +public interface TensorPartialDivisionAlgebra> : TensorAlgebra { public operator fun TensorType.div(other: TensorType): TensorType public operator fun TensorType.divAssign(other: TensorType) From 9011579d2c777b4844e4fbb10da9c077ce027c24 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 20 Jan 2021 11:43:01 +0300 Subject: [PATCH 005/211] [WIP] Tensor algebra design --- build.gradle.kts | 2 +- .../kscience/kmath/tensors/TensorAlgebra.kt | 74 ++++++++++--------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index d171bd608..0572217af 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { id("ru.mipt.npm.project") } -internal val kmathVersion: String by extra("0.2.0-dev-5") +internal val kmathVersion: String by extra("0.2.0-dev-6") internal val bintrayRepo: String by extra("kscience") internal val githubProject: String by extra("kmath") diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/tensors/TensorAlgebra.kt index c40544579..c14f0ee0d 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/tensors/TensorAlgebra.kt @@ -1,10 +1,13 @@ package kscience.kmath.tensors +import kscience.kmath.misc.UnstableKMathAPI +import kscience.kmath.operations.Field import kscience.kmath.operations.Ring import kscience.kmath.structures.MutableNDStructure public typealias Tensor = MutableNDStructure +@UnstableKMathAPI public val Tensor.value: T get() { require(shape.contentEquals(intArrayOf(1))) { "Value available only for a tensor with no dimensions" } @@ -13,59 +16,60 @@ public val Tensor.value: T // https://proofwiki.org/wiki/Definition:Algebra_over_Ring /** - * To be moved to a separate project + * TODO To be moved to a separate project */ -public interface TensorAlgebra> : Ring { +@UnstableKMathAPI +public interface TensorAlgebra> : Ring { - public operator fun T.plus(other: TensorType): TensorType - public operator fun TensorType.plus(value: T): TensorType - public operator fun TensorType.plusAssign(value: T): Unit - public operator fun TensorType.plusAssign(other: TensorType): Unit + public operator fun T.plus(other: TT): TT + public operator fun TT.plus(value: T): TT + public operator fun TT.plusAssign(value: T): Unit + public operator fun TT.plusAssign(other: TT): Unit - public operator fun T.minus(other: TensorType): TensorType - public operator fun TensorType.minus(value: T): TensorType - public operator fun TensorType.minusAssign(value: T): Unit - public operator fun TensorType.minusAssign(other: TensorType): Unit + public operator fun T.minus(other: TT): TT + public operator fun TT.minus(value: T): TT + public operator fun TT.minusAssign(value: T): Unit + public operator fun TT.minusAssign(other: TT): Unit - public operator fun T.times(other: TensorType): TensorType - public operator fun TensorType.times(value: T): TensorType - public operator fun TensorType.timesAssign(value: T): Unit - public operator fun TensorType.timesAssign(other: TensorType): Unit + public operator fun T.times(other: TT): TT + public operator fun TT.times(value: T): TT + public operator fun TT.timesAssign(value: T): Unit + public operator fun TT.timesAssign(other: TT): Unit - public infix fun TensorType.dot(other: TensorType): TensorType - public infix fun TensorType.dotAssign(other: TensorType): Unit - public infix fun TensorType.dotRightAssign(other: TensorType): Unit + public infix fun TT.dot(other: TT): TT + public infix fun TT.dotAssign(other: TT): Unit + public infix fun TT.dotRightAssign(other: TT): Unit public fun diagonalEmbedding( - diagonalEntries: TensorType, + diagonalEntries: TT, offset: Int = 0, dim1: Int = -2, dim2: Int = -1, - ): TensorType + ): TT - public fun TensorType.transpose(i: Int, j: Int): TensorType - public fun TensorType.transposeAssign(i: Int, j: Int): Unit + public fun TT.transpose(i: Int, j: Int): TT + public fun TT.transposeAssign(i: Int, j: Int): Unit - public fun TensorType.view(shape: IntArray): TensorType + public fun TT.view(shape: IntArray): TT - public fun TensorType.abs(): TensorType - public fun TensorType.absAssign(): Unit - public fun TensorType.sum(): TensorType - public fun TensorType.sumAssign(): Unit + public fun abs(tensor: TT): TT + public fun TT.absAssign(): Unit + public fun TT.sum(): TT + public fun TT.sumAssign(): Unit } // https://proofwiki.org/wiki/Definition:Division_Algebra -public interface TensorPartialDivisionAlgebra> : TensorAlgebra { +public interface TensorPartialDivisionAlgebra> : + TensorAlgebra, Field { - public operator fun TensorType.div(other: TensorType): TensorType - public operator fun TensorType.divAssign(other: TensorType) + public operator fun TT.divAssign(other: TT) - public fun TensorType.exp(): TensorType - public fun TensorType.expAssign(): Unit - public fun TensorType.log(): TensorType - public fun TensorType.logAssign(): Unit + public fun exp(tensor: TT): TT + public fun TT.expAssign(): Unit + public fun log(tensor: TT): TT + public fun TT.logAssign(): Unit - public fun TensorType.svd(): Triple - public fun TensorType.symEig(eigenvectors: Boolean = true): Pair + public fun svd(tensor: TT): Triple + public fun symEig(tensor: TT, eigenvectors: Boolean = true): Pair } \ No newline at end of file From f15ac203236355117e72f81159af7a496f5c6706 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 1 Mar 2021 22:52:58 +0000 Subject: [PATCH 006/211] Cannot afford to inherit from RingWithNumbers --- .../kmath/tensors/RealTensorAlgebra.kt | 35 +++++++++---------- .../kscience/kmath/tensors/TensorAlgebra.kt | 9 ++--- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 0a28ace4f..6023d2b72 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -19,25 +19,6 @@ public class RealTensor( public class RealTensorAlgebra : TensorPartialDivisionAlgebra { - override fun add(a: RealTensor, b: RealTensor): RealTensor { - TODO("Not yet implemented") - } - - override fun multiply(a: RealTensor, k: Number): RealTensor { - TODO("Not yet implemented") - } - - override val zero: RealTensor - get() = TODO("Not yet implemented") - - override fun multiply(a: RealTensor, b: RealTensor): RealTensor { - TODO("Not yet implemented") - } - - override val one: RealTensor - get() = TODO("Not yet implemented") - - override fun Double.plus(other: RealTensor): RealTensor { val n = other.buffer.size val arr = other.buffer.array @@ -51,6 +32,10 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra>: RingWithNumbers { +public interface TensorAlgebra>{ public operator fun T.plus(other: TensorType): TensorType public operator fun TensorType.plus(value: T): TensorType + public operator fun TensorType.plus(other: TensorType): TensorType public operator fun TensorType.plusAssign(value: T): Unit public operator fun TensorType.plusAssign(other: TensorType): Unit public operator fun T.minus(other: TensorType): TensorType public operator fun TensorType.minus(value: T): TensorType + public operator fun TensorType.minus(other: TensorType): TensorType public operator fun TensorType.minusAssign(value: T): Unit public operator fun TensorType.minusAssign(other: TensorType): Unit public operator fun T.times(other: TensorType): TensorType public operator fun TensorType.times(value: T): TensorType + public operator fun TensorType.times(other: TensorType): TensorType public operator fun TensorType.timesAssign(value: T): Unit public operator fun TensorType.timesAssign(other: TensorType): Unit + public operator fun TensorType.unaryMinus(): TensorType //https://pytorch.org/docs/stable/generated/torch.matmul.html From 4aa1df0628c5d531b518691eb8ab22b907946eb0 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 2 Mar 2021 09:32:36 +0000 Subject: [PATCH 007/211] Safe item method and view_as added --- .../space/kscience/kmath/tensors/RealTensorAlgebra.kt | 10 +++++++++- .../space/kscience/kmath/tensors/TensorAlgebra.kt | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 6023d2b72..24612a6aa 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -14,9 +14,13 @@ public class RealTensor( TensorStrides(shape), RealBuffer(buffer) ) { - override fun item(): Double = buffer[0] + override fun item(): Double { + check(buffer.size > 0) { "The tensor is empty" } + return buffer[0] + } } + public class RealTensorAlgebra : TensorPartialDivisionAlgebra { override fun Double.plus(other: RealTensor): RealTensor { @@ -116,6 +120,10 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra>{ //https://pytorch.org/docs/stable/tensor_view.html public fun TensorType.view(shape: IntArray): TensorType + public fun TensorType.view_as(other: TensorType): TensorType //https://pytorch.org/docs/stable/generated/torch.abs.html public fun TensorType.abs(): TensorType From ed007589cfc97d4b6c8d01a51719f2511d0ee3b3 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 2 Mar 2021 14:54:07 +0000 Subject: [PATCH 008/211] LU decomposition set up --- .../kscience/kmath/tensors/RealTensorAlgebra.kt | 13 +++++++++++++ .../space/kscience/kmath/tensors/TensorAlgebra.kt | 3 +++ 2 files changed, 16 insertions(+) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 24612a6aa..f234d7d6a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.linear.LupDecompositionFeature import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array @@ -164,7 +165,19 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { + /** + * Main first task for @AndreiKingsley + * Compare with the implementation of [LupDecomposition] + * and provide a common API + */ + TODO("Not yet implemented") + } + override fun RealTensor.svd(): Triple { + /** + * Main first task for @AlyaNovikova + */ TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index cddda7670..03f6f05c2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -66,6 +66,9 @@ public interface TensorPartialDivisionAlgebra public fun TensorType.log(): TensorType public fun TensorType.logAssign(): Unit + //https://pytorch.org/docs/stable/generated/torch.lu.html + public fun TensorType.lu(): Pair + //https://pytorch.org/docs/stable/generated/torch.svd.html public fun TensorType.svd(): Triple From 90f4ff06fd76fb60f4966d8d60fa31c6b4ebf96f Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 4 Mar 2021 13:22:28 +0000 Subject: [PATCH 009/211] Basic tasks for Alya and Andrei --- .../kmath/tensors/RealTensorAlgebra.kt | 58 +++++++++++-------- .../kscience/kmath/tensors/TensorAlgebra.kt | 7 ++- .../kscience/kmath/tensors/TensorStructure.kt | 4 ++ 3 files changed, 44 insertions(+), 25 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index f234d7d6a..cad01c4d0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,6 +1,5 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.linear.LupDecompositionFeature import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array @@ -15,6 +14,9 @@ public class RealTensor( TensorStrides(shape), RealBuffer(buffer) ) { + /* + * TODO: Andrei remove item() + */ override fun item(): Double { check(buffer.size > 0) { "The tensor is empty" } return buffer[0] @@ -24,6 +26,10 @@ public class RealTensor( public class RealTensorAlgebra : TensorPartialDivisionAlgebra { + override fun RealTensor.value(): Double { + TODO("Andrei") + } + override fun Double.plus(other: RealTensor): RealTensor { val n = other.buffer.size val arr = other.buffer.array @@ -34,95 +40,95 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { + TODO("Not yet implemented") + } + override fun RealTensor.svd(): Triple { /** * Main first task for @AlyaNovikova diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 03f6f05c2..b2586e1e9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -1,7 +1,9 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Algebra_over_Ring -public interface TensorAlgebra>{ +public interface TensorAlgebra> { + + public fun TensorType.value(): T public operator fun T.plus(other: TensorType): TensorType public operator fun TensorType.plus(value: T): TensorType @@ -69,6 +71,9 @@ public interface TensorPartialDivisionAlgebra //https://pytorch.org/docs/stable/generated/torch.lu.html public fun TensorType.lu(): Pair + //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html + public fun lu_unpack(A_LU: TensorType, pivots: TensorType): Triple + //https://pytorch.org/docs/stable/generated/torch.svd.html public fun TensorType.svd(): Triple diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt index 6d2d855b6..3775ea2e5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt @@ -3,6 +3,10 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDStructure public interface TensorStructure : MutableNDStructure { + + /* + * TODO: Andrei remove item() and value() + */ public fun item(): T // A tensor can have empty shape, in which case it represents just a value From fe55856a26bd92c7389c57a17df9f908ea2cc343 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 9 Mar 2021 22:18:46 +0300 Subject: [PATCH 010/211] basic implements & refactor tensor structure & and new tensor algebra methods --- .../kmath/tensors/RealTensorAlgebra.kt | 137 ++++++++++++------ .../kscience/kmath/tensors/TensorAlgebra.kt | 14 +- .../kscience/kmath/tensors/TensorStrides.kt | 4 +- .../kscience/kmath/tensors/TensorStructure.kt | 23 +-- 4 files changed, 111 insertions(+), 67 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index cad01c4d0..13c57fc18 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -3,6 +3,8 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array +import kotlin.js.JsName +import kotlin.math.abs public class RealTensor( @@ -13,46 +15,80 @@ public class RealTensor( MutableNDBuffer( TensorStrides(shape), RealBuffer(buffer) - ) { - /* - * TODO: Andrei remove item() - */ - override fun item(): Double { - check(buffer.size > 0) { "The tensor is empty" } - return buffer[0] - } -} - + ) public class RealTensorAlgebra : TensorPartialDivisionAlgebra { + //rename to item? override fun RealTensor.value(): Double { - TODO("Andrei") + check(this.dimension == 0) { + // todo change message + "This tensor has shape ${shape.toList()}" + } + return this.buffer.array[0] + } + + override fun eye(n: Int): RealTensor { + val shape = intArrayOf(n, n) + val buffer = DoubleArray(n * n) { 0.0 } + val res = RealTensor(shape, buffer) + for (i in 0 until n) { + res[intArrayOf(i, i)] = 1.0 + } + return res + } + + override fun zeros(shape: IntArray): RealTensor { + TODO("Not yet implemented") + } + + override fun zeroesLike(other: RealTensor): RealTensor { + TODO("Not yet implemented") + } + + override fun ones(shape: IntArray): RealTensor { + TODO("Not yet implemented") + } + + override fun onesLike(shape: IntArray): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.copy(): RealTensor { + TODO("Not yet implemented") } override fun Double.plus(other: RealTensor): RealTensor { - val n = other.buffer.size - val arr = other.buffer.array - val res = DoubleArray(n) - for (i in 1..n) - res[i - 1] = arr[i - 1] + this - return RealTensor(other.shape, res) + //todo should be change with broadcasting + val resBuffer = DoubleArray(other.buffer.size) { i -> + other.buffer.array[i] + this + } + return RealTensor(other.shape, resBuffer) } - override fun RealTensor.plus(value: Double): RealTensor { - TODO("Andrei") - } + //todo should be change with broadcasting + override fun RealTensor.plus(value: Double): RealTensor = value + this override fun RealTensor.plus(other: RealTensor): RealTensor { - TODO("Andrei") + //todo should be change with broadcasting + val resBuffer = DoubleArray(this.buffer.size) { i -> + this.buffer.array[i] + other.buffer.array[i] + } + return RealTensor(this.shape, resBuffer) } override fun RealTensor.plusAssign(value: Double) { - TODO("Andrei") + //todo should be change with broadcasting + for (i in this.buffer.array.indices) { + this.buffer.array[i] += value + } } override fun RealTensor.plusAssign(other: RealTensor) { - TODO("Andrei") + //todo should be change with broadcasting + for (i in this.buffer.array.indices) { + this.buffer.array[i] += other.buffer.array[i] + } } override fun Double.minus(other: RealTensor): RealTensor { @@ -76,27 +112,43 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra + other.buffer.array[i] * this + } + return RealTensor(other.shape, resBuffer) } - override fun RealTensor.times(value: Double): RealTensor { - TODO("Andrei") - } + //todo should be change with broadcasting + override fun RealTensor.times(value: Double): RealTensor = value * this override fun RealTensor.times(other: RealTensor): RealTensor { - TODO("Andrei") + //todo should be change with broadcasting + val resBuffer = DoubleArray(this.buffer.size) { i -> + this.buffer.array[i] * other.buffer.array[i] + } + return RealTensor(this.shape, resBuffer) } override fun RealTensor.timesAssign(value: Double) { - TODO("Andrei") + //todo should be change with broadcasting + for (i in this.buffer.array.indices) { + this.buffer.array[i] *= value + } } override fun RealTensor.timesAssign(other: RealTensor) { - TODO("Andrei") + //todo should be change with broadcasting + for (i in this.buffer.array.indices) { + this.buffer.array[i] *= other.buffer.array[i] + } } override fun RealTensor.unaryMinus(): RealTensor { - TODO("Andrei") + val resBuffer = DoubleArray(this.buffer.size) { i -> + this.buffer.array[i].unaryMinus() + } + return RealTensor(this.shape, resBuffer) } override fun RealTensor.dot(other: RealTensor): RealTensor { @@ -124,11 +176,11 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { - /** - * Main first task for @AndreiKingsley - * Compare with the implementation of [LupDecomposition] - * and provide a common API - */ - TODO("Not yet implemented") + TODO() } - override fun lu_unpack(A_LU: RealTensor, pivots: RealTensor): Triple { + override fun luUnpack(A_LU: RealTensor, pivots: RealTensor): Triple { TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index b2586e1e9..6f42623e0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -5,6 +5,14 @@ public interface TensorAlgebra> { public fun TensorType.value(): T + public fun eye(n: Int): TensorType + public fun zeros(shape: IntArray): TensorType + public fun zeroesLike(other: TensorType): TensorType + public fun ones(shape: IntArray): TensorType + public fun onesLike(shape: IntArray): TensorType + + public fun TensorType.copy(): TensorType + public operator fun T.plus(other: TensorType): TensorType public operator fun TensorType.plus(value: T): TensorType public operator fun TensorType.plus(other: TensorType): TensorType @@ -42,7 +50,7 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/tensor_view.html public fun TensorType.view(shape: IntArray): TensorType - public fun TensorType.view_as(other: TensorType): TensorType + public fun TensorType.viewAs(other: TensorType): TensorType //https://pytorch.org/docs/stable/generated/torch.abs.html public fun TensorType.abs(): TensorType @@ -57,7 +65,9 @@ public interface TensorAlgebra> { public interface TensorPartialDivisionAlgebra> : TensorAlgebra { + public operator fun TensorType.div(value: T): TensorType public operator fun TensorType.div(other: TensorType): TensorType + public operator fun TensorType.divAssign(value: T) public operator fun TensorType.divAssign(other: TensorType) //https://pytorch.org/docs/stable/generated/torch.exp.html @@ -72,7 +82,7 @@ public interface TensorPartialDivisionAlgebra public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun lu_unpack(A_LU: TensorType, pivots: TensorType): Triple + public fun luUnpack(A_LU: TensorType, pivots: TensorType): Triple //https://pytorch.org/docs/stable/generated/torch.svd.html public fun TensorType.svd(): Triple diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt index 3ea8f4bf0..dbaefe907 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt @@ -5,7 +5,7 @@ import space.kscience.kmath.nd.offsetFromIndex import kotlin.math.max -inline public fun stridesFromShape(shape: IntArray): IntArray { +public inline fun stridesFromShape(shape: IntArray): IntArray { val nDim = shape.size val res = IntArray(nDim) if (nDim == 0) @@ -22,7 +22,7 @@ inline public fun stridesFromShape(shape: IntArray): IntArray { } -inline public fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { +public inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { val res = IntArray(nDim) var current = offset var strideIndex = 0 diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt index 3775ea2e5..5463877ce 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt @@ -2,26 +2,5 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDStructure -public interface TensorStructure : MutableNDStructure { +public typealias TensorStructure = MutableNDStructure - /* - * TODO: Andrei remove item() and value() - */ - public fun item(): T - - // A tensor can have empty shape, in which case it represents just a value - public fun value(): T { - checkIsValue() - return item() - } -} - -public inline fun TensorStructure.isValue(): Boolean { - return (dimension == 0) -} - -public inline fun TensorStructure.isNotValue(): Boolean = !this.isValue() - -public inline fun TensorStructure.checkIsValue(): Unit = check(this.isValue()) { - "This tensor has shape ${shape.toList()}" -} \ No newline at end of file From 3a37b88b5c4808107e2522d5f33eb07440169fb9 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 9 Mar 2021 21:13:48 +0000 Subject: [PATCH 011/211] Fixed getting value test for tensors --- .../space/kscience/kmath/tensors/RealTensorAlgebra.kt | 8 ++------ .../kotlin/space/kscience/kmath/tensors/TensorStrides.kt | 2 +- .../kotlin/space/kscience/kmath/tensors/TestRealTensor.kt | 4 ++-- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 13c57fc18..366acfb62 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -3,8 +3,6 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array -import kotlin.js.JsName -import kotlin.math.abs public class RealTensor( @@ -19,11 +17,9 @@ public class RealTensor( public class RealTensorAlgebra : TensorPartialDivisionAlgebra { - //rename to item? override fun RealTensor.value(): Double { - check(this.dimension == 0) { - // todo change message - "This tensor has shape ${shape.toList()}" + check(this.shape contentEquals intArrayOf(1)) { + "Inconsistent value for tensor of shape ${shape.toList()}" } return this.buffer.array[0] } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt index dbaefe907..0c10203f0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt @@ -48,5 +48,5 @@ public class TensorStrides(override val shape: IntArray): Strides indexFromOffset(offset, strides, shape.size) override val linearSize: Int - get() = shape.fold(1) { acc, i -> acc * i } + get() = shape.reduce(Int::times) } \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt index 7938eb864..d96b00baf 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt @@ -9,9 +9,9 @@ import kotlin.test.assertTrue class TestRealTensor { @Test - fun valueTest(){ + fun valueTest() = RealTensorAlgebra { val value = 12.5 - val tensor = RealTensor(IntArray(0), doubleArrayOf(value)) + val tensor = RealTensor(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } From 723e0e458e7be15e3388e4bef6654db487d2cf03 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 11 Mar 2021 23:04:42 +0300 Subject: [PATCH 012/211] add functions transpose and transposeAssign --- .../space/kscience/kmath/nd/NDStructure.kt | 9 ++++ .../kmath/tensors/RealTensorAlgebra.kt | 26 +++++++++- .../kscience/kmath/tensors/TensorStrides.kt | 20 ++++++++ .../kmath/tensors/TestRealTensorAlgebra.kt | 51 +++++++++++++++++++ 4 files changed, 104 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt index 54e410ade..e458d0606 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt @@ -174,6 +174,11 @@ public interface Strides { */ public fun index(offset: Int): IntArray + /** + * Get next multidimensional index from the current multidimensional index + */ + public fun nextIndex(index: IntArray): IntArray + /** * The size of linear buffer to accommodate all elements of ND-structure corresponding to strides */ @@ -232,6 +237,10 @@ public class DefaultStrides private constructor(override val shape: IntArray) : return res } + override fun nextIndex(index: IntArray): IntArray { + TODO("Not yet implemented") + } + override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is DefaultStrides) return false diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 366acfb62..a5c00e8ec 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -164,11 +164,33 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra= shape[current]) { + carry = 1 + res[current] = 0 + } + current-- + } while(carry != 0 && current >= 0) + + return res +} + public class TensorStrides(override val shape: IntArray): Strides @@ -47,6 +64,9 @@ public class TensorStrides(override val shape: IntArray): Strides override fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) + override fun nextIndex(index: IntArray): IntArray = + nextIndex(index, shape, shape.size) + override val linearSize: Int get() = shape.reduce(Int::times) } \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index 86caa0338..8e95922b8 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -13,4 +13,55 @@ class TestRealTensorAlgebra { assertTrue(res.buffer.array contentEquals doubleArrayOf(11.0,12.0)) } + @Test + fun transpose1x1() = RealTensorAlgebra { + val tensor = RealTensor(intArrayOf(1), doubleArrayOf(0.0)) + val res = tensor.transpose(0, 0) + + assertTrue(res.buffer.array contentEquals doubleArrayOf(0.0)) + assertTrue(res.shape contentEquals intArrayOf(1)) + } + + @Test + fun transpose3x2() = RealTensorAlgebra { + val tensor = RealTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val res = tensor.transpose(1, 0) + + assertTrue(res.buffer.array contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) + assertTrue(res.shape contentEquals intArrayOf(2, 3)) + } + + @Test + fun transpose1x2x3() = RealTensorAlgebra { + val tensor = RealTensor(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val res01 = tensor.transpose(0, 1) + val res02 = tensor.transpose(0, 2) + val res12 = tensor.transpose(1, 2) + + assertTrue(res01.shape contentEquals intArrayOf(2, 1, 3)) + assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) + assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2)) + + assertTrue(res01.buffer.array contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res02.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res12.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + } + + @Test + fun transposeAssign1x2() = RealTensorAlgebra { + val tensor = RealTensor(intArrayOf(1,2), doubleArrayOf(1.0, 2.0)) + tensor.transposeAssign(0, 1) + + assertTrue(tensor.buffer.array contentEquals doubleArrayOf(1.0, 2.0)) + assertTrue(tensor.shape contentEquals intArrayOf(2, 1)) + } + + @Test + fun transposeAssign2x3() = RealTensorAlgebra { + val tensor = RealTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + tensor.transposeAssign(1, 0) + + assertTrue(tensor.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(tensor.shape contentEquals intArrayOf(3, 2)) + } } \ No newline at end of file From bb4894b87ea5d4ed64b290ae0ddcd35c9ebe6d1a Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 11 Mar 2021 21:46:35 +0000 Subject: [PATCH 013/211] removing assignement for non operator members --- .../kmath/tensors/RealTensorAlgebra.kt | 31 +------------------ .../kscience/kmath/tensors/TensorAlgebra.kt | 7 ----- .../kmath/tensors/TestRealTensorAlgebra.kt | 18 ----------- 3 files changed, 1 insertion(+), 55 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index a5c00e8ec..16f90341b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -151,14 +151,6 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { TODO() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 6f42623e0..f1d401f6e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -35,8 +35,6 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.matmul.html public infix fun TensorType.dot(other: TensorType): TensorType - public infix fun TensorType.dotAssign(other: TensorType): Unit - public infix fun TensorType.dotRightAssign(other: TensorType): Unit //https://pytorch.org/docs/stable/generated/torch.diag_embed.html public fun diagonalEmbedding( @@ -46,7 +44,6 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.transpose.html public fun TensorType.transpose(i: Int, j: Int): TensorType - public fun TensorType.transposeAssign(i: Int, j: Int): Unit //https://pytorch.org/docs/stable/tensor_view.html public fun TensorType.view(shape: IntArray): TensorType @@ -54,11 +51,9 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.abs.html public fun TensorType.abs(): TensorType - public fun TensorType.absAssign(): Unit //https://pytorch.org/docs/stable/generated/torch.sum.html public fun TensorType.sum(): TensorType - public fun TensorType.sumAssign(): Unit } // https://proofwiki.org/wiki/Definition:Division_Algebra @@ -72,11 +67,9 @@ public interface TensorPartialDivisionAlgebra //https://pytorch.org/docs/stable/generated/torch.exp.html public fun TensorType.exp(): TensorType - public fun TensorType.expAssign(): Unit //https://pytorch.org/docs/stable/generated/torch.log.html public fun TensorType.log(): TensorType - public fun TensorType.logAssign(): Unit //https://pytorch.org/docs/stable/generated/torch.lu.html public fun TensorType.lu(): Pair diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index 8e95922b8..19f0c0ef0 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -46,22 +46,4 @@ class TestRealTensorAlgebra { assertTrue(res02.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) assertTrue(res12.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) } - - @Test - fun transposeAssign1x2() = RealTensorAlgebra { - val tensor = RealTensor(intArrayOf(1,2), doubleArrayOf(1.0, 2.0)) - tensor.transposeAssign(0, 1) - - assertTrue(tensor.buffer.array contentEquals doubleArrayOf(1.0, 2.0)) - assertTrue(tensor.shape contentEquals intArrayOf(2, 1)) - } - - @Test - fun transposeAssign2x3() = RealTensorAlgebra { - val tensor = RealTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - tensor.transposeAssign(1, 0) - - assertTrue(tensor.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) - assertTrue(tensor.shape contentEquals intArrayOf(3, 2)) - } } \ No newline at end of file From f9500f44ec6fc811a17e76104a9bea7ed6f790cc Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 12 Mar 2021 13:50:06 +0300 Subject: [PATCH 014/211] new tensor def --- .../kscience/kmath/tensors/BufferTensor.kt | 28 +++++++++++++++++++ .../kmath/tensors/RealTensorAlgebra.kt | 14 +++++----- 2 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt new file mode 100644 index 000000000..4d8aea32c --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt @@ -0,0 +1,28 @@ +package space.kscience.kmath.tensors + +import space.kscience.kmath.linear.BufferMatrix +import space.kscience.kmath.linear.RealMatrixContext.toBufferMatrix +import space.kscience.kmath.nd.MutableNDBuffer +import space.kscience.kmath.nd.as2D +import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.toList + +public open class BufferTensor( + override val shape: IntArray, + buffer: MutableBuffer +) : + TensorStructure, + MutableNDBuffer( + TensorStrides(shape), + buffer + ) + + +public fun BufferTensor.toBufferMatrix(): BufferMatrix { + return BufferMatrix(shape[0], shape[1], this.buffer) +} + +public fun BufferMatrix.BufferTensor(): BufferTensor { + return BufferTensor(intArrayOf(rowNum, colNum), buffer) +} + diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index a5c00e8ec..e38056097 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,19 +1,19 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.linear.BufferMatrix +import space.kscience.kmath.linear.RealMatrixContext.toBufferMatrix import space.kscience.kmath.nd.MutableNDBuffer +import space.kscience.kmath.nd.as2D +import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array +import space.kscience.kmath.structures.toList public class RealTensor( - override val shape: IntArray, + shape: IntArray, buffer: DoubleArray -) : - TensorStructure, - MutableNDBuffer( - TensorStrides(shape), - RealBuffer(buffer) - ) +) : BufferTensor(shape, RealBuffer(buffer)) public class RealTensorAlgebra : TensorPartialDivisionAlgebra { From 95b814e1637c281b6cc771b0c89e3475a27323c9 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 12 Mar 2021 14:29:51 +0300 Subject: [PATCH 015/211] add fromMatrix --- .../kotlin/space/kscience/kmath/tensors/BufferTensor.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt index 4d8aea32c..817c51f11 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt @@ -2,8 +2,12 @@ package space.kscience.kmath.tensors import space.kscience.kmath.linear.BufferMatrix import space.kscience.kmath.linear.RealMatrixContext.toBufferMatrix +import space.kscience.kmath.nd.Matrix import space.kscience.kmath.nd.MutableNDBuffer +import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferAccessor2D import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.toList @@ -22,7 +26,8 @@ public fun BufferTensor.toBufferMatrix(): BufferMatrix { return BufferMatrix(shape[0], shape[1], this.buffer) } -public fun BufferMatrix.BufferTensor(): BufferTensor { - return BufferTensor(intArrayOf(rowNum, colNum), buffer) +// T??? +public fun BufferMatrix.BufferTensor(): BufferTensor { + return BufferTensor(intArrayOf(rowNum, colNum), BufferAccessor2D(rowNum, colNum, Buffer.Companion::real).create(this)) } From 454d574ccd8876982753e8e09782ff1f4fb0c564 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Fri, 12 Mar 2021 15:20:46 +0300 Subject: [PATCH 016/211] add broadcast and functions plus and minus --- .../kmath/tensors/RealTensorAlgebra.kt | 96 ++++++++++++++++--- .../kscience/kmath/tensors/TensorAlgebra.kt | 3 + .../kmath/tensors/TestRealTensorAlgebra.kt | 47 +++++++++ 3 files changed, 135 insertions(+), 11 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index a5c00e8ec..a4ad54bfc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -2,7 +2,9 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.structures.ValueFlag import space.kscience.kmath.structures.array +import kotlin.math.max public class RealTensor( @@ -54,27 +56,85 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { + val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) + val n = totalShape.reduce{ acc, i -> acc * i } + + val res = ArrayList(0) + for (tensor in tensors) { + val resTensor = RealTensor(totalShape, DoubleArray(n)) + + for (linearIndex in 0 until n) { + val totalMultiIndex = resTensor.strides.index(linearIndex) + val curMultiIndex = tensor.shape.copyOf() + + val offset = totalMultiIndex.size - curMultiIndex.size + + for (i in curMultiIndex.indices) { + if (curMultiIndex[i] != 1) { + curMultiIndex[i] = totalMultiIndex[i + offset] + } else { + curMultiIndex[i] = 0 + } + } + + val curLinearIndex = tensor.strides.offset(curMultiIndex) + resTensor.buffer.array[linearIndex] = tensor.buffer.array[curLinearIndex] + } + res.add(resTensor) + } + + return res + } + override fun Double.plus(other: RealTensor): RealTensor { - //todo should be change with broadcasting val resBuffer = DoubleArray(other.buffer.size) { i -> other.buffer.array[i] + this } return RealTensor(other.shape, resBuffer) } - //todo should be change with broadcasting override fun RealTensor.plus(value: Double): RealTensor = value + this override fun RealTensor.plus(other: RealTensor): RealTensor { - //todo should be change with broadcasting - val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.array[i] + other.buffer.array[i] + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.buffer.size) { i -> + newThis.buffer.array[i] + newOther.buffer.array[i] } - return RealTensor(this.shape, resBuffer) + return RealTensor(newThis.shape, resBuffer) } override fun RealTensor.plusAssign(value: Double) { - //todo should be change with broadcasting for (i in this.buffer.array.indices) { this.buffer.array[i] += value } @@ -88,19 +148,33 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra + this - other.buffer.array[i] + } + return RealTensor(other.shape, resBuffer) } override fun RealTensor.minus(value: Double): RealTensor { - TODO("Alya") + val resBuffer = DoubleArray(this.buffer.size) { i -> + this.buffer.array[i] - value + } + return RealTensor(this.shape, resBuffer) } override fun RealTensor.minus(other: RealTensor): RealTensor { - TODO("Alya") + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.buffer.size) { i -> + newThis.buffer.array[i] - newOther.buffer.array[i] + } + return RealTensor(newThis.shape, resBuffer) } override fun RealTensor.minusAssign(value: Double) { - TODO("Alya") + for (i in this.buffer.array.indices) { + this.buffer.array[i] -= value + } } override fun RealTensor.minusAssign(other: RealTensor) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 6f42623e0..bd47a1b76 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -13,6 +13,9 @@ public interface TensorAlgebra> { public fun TensorType.copy(): TensorType + public fun broadcastShapes(vararg shapes: IntArray): IntArray + public fun broadcastTensors(vararg tensors: RealTensor): List + public operator fun T.plus(other: TensorType): TensorType public operator fun TensorType.plus(value: T): TensorType public operator fun TensorType.plus(other: TensorType): TensorType diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index 8e95922b8..18639bf3c 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -2,6 +2,8 @@ package space.kscience.kmath.tensors import space.kscience.kmath.structures.array import kotlin.test.Test +import kotlin.test.assertFails +import kotlin.test.assertFailsWith import kotlin.test.assertTrue class TestRealTensorAlgebra { @@ -64,4 +66,49 @@ class TestRealTensorAlgebra { assertTrue(tensor.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) assertTrue(tensor.shape contentEquals intArrayOf(3, 2)) } + + @Test + fun broadcastShapes() = RealTensorAlgebra { + assertTrue(this.broadcastShapes( + intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) + ) contentEquals intArrayOf(1, 2, 3)) + + assertTrue(this.broadcastShapes( + intArrayOf(6, 7), intArrayOf(5, 6, 1), intArrayOf(7,), intArrayOf(5, 1, 7) + ) contentEquals intArrayOf(5, 6, 7)) + } + + @Test + fun broadcastTensors() = RealTensorAlgebra { + val tensor1 = RealTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = RealTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + + val res = this.broadcastTensors(tensor1, tensor2, tensor3) + + assertTrue(res[0].shape contentEquals intArrayOf(1, 2, 3)) + assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) + assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) + + assertTrue(res[0].buffer.array contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].buffer.array contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + assertTrue(res[2].buffer.array contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) + } + + @Test + fun minusTensor() = RealTensorAlgebra { + val tensor1 = RealTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = RealTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + + assertTrue((tensor2 - tensor1).shape contentEquals intArrayOf(2, 3)) + assertTrue((tensor2 - tensor1).buffer.array contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) + + assertTrue((tensor3 - tensor1).shape contentEquals intArrayOf(1, 2, 3)) + assertTrue((tensor3 - tensor1).buffer.array + contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0)) + + assertTrue((tensor3 - tensor2).shape contentEquals intArrayOf(1, 1, 3)) + assertTrue((tensor3 - tensor2).buffer.array contentEquals doubleArrayOf(490.0, 480.0, 470.0)) + } } \ No newline at end of file From 70e1861e536febfe9792fcbd3dde3dbd66cb4682 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Fri, 12 Mar 2021 15:25:47 +0300 Subject: [PATCH 017/211] remove extra import --- .../kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index a4ad54bfc..afe78ae08 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -2,7 +2,6 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.RealBuffer -import space.kscience.kmath.structures.ValueFlag import space.kscience.kmath.structures.array import kotlin.math.max From 626d5c98fa843fe6833cf300f8b71871d54474b1 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Fri, 12 Mar 2021 15:43:44 +0300 Subject: [PATCH 018/211] change IllegalArgumentException to RuntimeException --- .../kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index afe78ae08..9e090e376 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -75,7 +75,7 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra Date: Sat, 13 Mar 2021 19:30:58 +0300 Subject: [PATCH 019/211] add buffered tensor + lu --- .../kscience/kmath/tensors/BufferTensor.kt | 33 --------- .../kscience/kmath/tensors/BufferedTensor.kt | 33 +++++++++ .../kmath/tensors/RealTensorAlgebra.kt | 69 +++++++++++++++---- .../kscience/kmath/tensors/TensorAlgebra.kt | 5 +- 4 files changed, 92 insertions(+), 48 deletions(-) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt deleted file mode 100644 index 817c51f11..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt +++ /dev/null @@ -1,33 +0,0 @@ -package space.kscience.kmath.tensors - -import space.kscience.kmath.linear.BufferMatrix -import space.kscience.kmath.linear.RealMatrixContext.toBufferMatrix -import space.kscience.kmath.nd.Matrix -import space.kscience.kmath.nd.MutableNDBuffer -import space.kscience.kmath.nd.Structure2D -import space.kscience.kmath.nd.as2D -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferAccessor2D -import space.kscience.kmath.structures.MutableBuffer -import space.kscience.kmath.structures.toList - -public open class BufferTensor( - override val shape: IntArray, - buffer: MutableBuffer -) : - TensorStructure, - MutableNDBuffer( - TensorStrides(shape), - buffer - ) - - -public fun BufferTensor.toBufferMatrix(): BufferMatrix { - return BufferMatrix(shape[0], shape[1], this.buffer) -} - -// T??? -public fun BufferMatrix.BufferTensor(): BufferTensor { - return BufferTensor(intArrayOf(rowNum, colNum), BufferAccessor2D(rowNum, colNum, Buffer.Companion::real).create(this)) -} - diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt new file mode 100644 index 000000000..9ffe2db61 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -0,0 +1,33 @@ +package space.kscience.kmath.tensors + +import space.kscience.kmath.linear.BufferMatrix +import space.kscience.kmath.nd.MutableNDBuffer +import space.kscience.kmath.structures.* +import space.kscience.kmath.structures.BufferAccessor2D + +public open class BufferedTensor( + override val shape: IntArray, + buffer: MutableBuffer +) : + TensorStructure, + MutableNDBuffer( + TensorStrides(shape), + buffer + ) { + + public operator fun get(i: Int, j: Int): T{ + check(this.dimension == 2) {"Not matrix"} + return this[intArrayOf(i, j)] + } + + public operator fun set(i: Int, j: Int, value: T): Unit{ + check(this.dimension == 2) {"Not matrix"} + this[intArrayOf(i, j)] = value + } + +} + +public class IntTensor( + shape: IntArray, + buffer: IntArray +) : BufferedTensor(shape, IntBuffer(buffer)) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index e38056097..3e21a3a98 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,24 +1,19 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.linear.BufferMatrix -import space.kscience.kmath.linear.RealMatrixContext.toBufferMatrix -import space.kscience.kmath.nd.MutableNDBuffer -import space.kscience.kmath.nd.as2D -import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array -import space.kscience.kmath.structures.toList +import kotlin.math.abs public class RealTensor( shape: IntArray, buffer: DoubleArray -) : BufferTensor(shape, RealBuffer(buffer)) +) : BufferedTensor(shape, RealBuffer(buffer)) public class RealTensorAlgebra : TensorPartialDivisionAlgebra { override fun RealTensor.value(): Double { - check(this.shape contentEquals intArrayOf(1)) { + check(this.shape contentEquals intArrayOf(1)) { "Inconsistent value for tensor of shape ${shape.toList()}" } return this.buffer.array[0] @@ -51,7 +46,8 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { - TODO() + override fun RealTensor.lu(): Pair { + // todo checks + val lu = this.copy() + val m = this.shape[0] + val pivot = IntArray(m) + + + // Initialize permutation array and parity + for (row in 0 until m) pivot[row] = row + var even = true + + for (i in 0 until m) { + var maxA = -1.0 + var iMax = i + + for (k in i until m) { + val absA = abs(lu[k, i]) + if (absA > maxA) { + maxA = absA + iMax = k + } + } + + //todo check singularity + + if (iMax != i) { + + val j = pivot[i] + pivot[i] = pivot[iMax] + pivot[iMax] = j + even != even + + for (k in 0 until m) { + val tmp = lu[i, k] + lu[i, k] = lu[iMax, k] + lu[iMax, k] = tmp + } + + } + + for (j in i + 1 until m) { + lu[j, i] /= lu[i, i] + for (k in i + 1 until m) { + lu[j, k] -= lu[j, i] * lu[i, k] + } + } + } + return Pair(lu, IntTensor(intArrayOf(m), pivot)) } - override fun luUnpack(A_LU: RealTensor, pivots: RealTensor): Triple { - TODO("Not yet implemented") + override fun luUnpack(A_LU: RealTensor, pivots: IntTensor): Triple { + // todo checks + } override fun RealTensor.svd(): Triple { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 6f42623e0..0dbcae044 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -78,11 +78,12 @@ public interface TensorPartialDivisionAlgebra public fun TensorType.log(): TensorType public fun TensorType.logAssign(): Unit + // todo change type of pivots //https://pytorch.org/docs/stable/generated/torch.lu.html - public fun TensorType.lu(): Pair + public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun luUnpack(A_LU: TensorType, pivots: TensorType): Triple + public fun luUnpack(A_LU: TensorType, pivots: IntTensor): Triple //https://pytorch.org/docs/stable/generated/torch.svd.html public fun TensorType.svd(): Triple From 8f88a101d24faee0504228c57642bb980a7d48e4 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sat, 13 Mar 2021 20:51:15 +0300 Subject: [PATCH 020/211] complete lu for matrix --- .../kmath/tensors/RealTensorAlgebra.kt | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 9e040fcd8..f91f44519 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -35,7 +35,10 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { + override fun luUnpack(lu: RealTensor, pivots: IntTensor): Triple { // todo checks + val n = lu.shape[0] + val p = zeroesLike(lu) + pivots.buffer.array.forEachIndexed { i, pivot -> + p[i, pivot] = 1.0 + } + val l = zeroesLike(lu) + val u = zeroesLike(lu) + for (i in 0 until n){ + for (j in 0 until n){ + if (i == j) { + l[i, j] = 1.0 + } + if (j < i) { + l[i, j] = lu[i, j] + } + if (j >= i) { + u[i, j] = lu[i, j] + } + } + } + return Triple(p, l, u) } override fun RealTensor.svd(): Triple { From 384415dc98ae27125f894798057f6052103e2594 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sat, 13 Mar 2021 19:16:13 +0000 Subject: [PATCH 021/211] utils module for tensors --- .../kscience/kmath/tensors/BufferedTensor.kt | 28 ++++-- .../kmath/tensors/RealTensorAlgebra.kt | 63 ------------ .../kscience/kmath/tensors/TensorAlgebra.kt | 46 +-------- .../kscience/kmath/tensors/TensorStrides.kt | 6 +- .../space/kscience/kmath/tensors/utils.kt | 96 +++++++++++++++++++ .../kmath/tensors/TestRealTensorAlgebra.kt | 8 +- 6 files changed, 124 insertions(+), 123 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index 9ffe2db61..29605024d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -1,9 +1,8 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.linear.BufferMatrix import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.* -import space.kscience.kmath.structures.BufferAccessor2D + public open class BufferedTensor( override val shape: IntArray, @@ -15,13 +14,13 @@ public open class BufferedTensor( buffer ) { - public operator fun get(i: Int, j: Int): T{ - check(this.dimension == 2) {"Not matrix"} - return this[intArrayOf(i, j)] + public operator fun get(i: Int, j: Int): T { + check(this.dimension == 2) { "Not matrix" } + return this[intArrayOf(i, j)] } - public operator fun set(i: Int, j: Int, value: T): Unit{ - check(this.dimension == 2) {"Not matrix"} + public operator fun set(i: Int, j: Int, value: T): Unit { + check(this.dimension == 2) { "Not matrix" } this[intArrayOf(i, j)] = value } @@ -31,3 +30,18 @@ public class IntTensor( shape: IntArray, buffer: IntArray ) : BufferedTensor(shape, IntBuffer(buffer)) + +public class LongTensor( + shape: IntArray, + buffer: LongArray +) : BufferedTensor(shape, LongBuffer(buffer)) + +public class FloatTensor( + shape: IntArray, + buffer: FloatArray +) : BufferedTensor(shape, FloatBuffer(buffer)) + +public class RealTensor( + shape: IntArray, + buffer: DoubleArray +) : BufferedTensor(shape, RealBuffer(buffer)) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index f91f44519..b3e54f077 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -6,11 +6,6 @@ import kotlin.math.abs import kotlin.math.max -public class RealTensor( - shape: IntArray, - buffer: DoubleArray -) : BufferedTensor(shape, RealBuffer(buffer)) - public class RealTensorAlgebra : TensorPartialDivisionAlgebra { override fun RealTensor.value(): Double { @@ -54,64 +49,6 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { - val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) - val n = totalShape.reduce{ acc, i -> acc * i } - - val res = ArrayList(0) - for (tensor in tensors) { - val resTensor = RealTensor(totalShape, DoubleArray(n)) - - for (linearIndex in 0 until n) { - val totalMultiIndex = resTensor.strides.index(linearIndex) - val curMultiIndex = tensor.shape.copyOf() - - val offset = totalMultiIndex.size - curMultiIndex.size - - for (i in curMultiIndex.indices) { - if (curMultiIndex[i] != 1) { - curMultiIndex[i] = totalMultiIndex[i + offset] - } else { - curMultiIndex[i] = 0 - } - } - - val curLinearIndex = tensor.strides.offset(curMultiIndex) - resTensor.buffer.array[linearIndex] = tensor.buffer.array[curLinearIndex] - } - res.add(resTensor) - } - - return res - } override fun Double.plus(other: RealTensor): RealTensor { val resBuffer = DoubleArray(other.buffer.size) { i -> diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index ec257e45c..280acf8ea 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -13,9 +13,6 @@ public interface TensorAlgebra> { public fun TensorType.copy(): TensorType - public fun broadcastShapes(vararg shapes: IntArray): IntArray - public fun broadcastTensors(vararg tensors: RealTensor): List - public operator fun T.plus(other: TensorType): TensorType public operator fun TensorType.plus(value: T): TensorType public operator fun TensorType.plus(other: TensorType): TensorType @@ -87,45 +84,4 @@ public interface TensorPartialDivisionAlgebra //https://pytorch.org/docs/stable/generated/torch.symeig.html public fun TensorType.symEig(eigenvectors: Boolean = true): Pair -} - -public inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkShapeCompatible( - a: TensorType, b: TensorType -): Unit = - check(a.shape contentEquals b.shape) { - "Tensors must be of identical shape" - } - -public inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkDot(a: TensorType, b: TensorType): Unit { - val sa = a.shape - val sb = b.shape - val na = sa.size - val nb = sb.size - var status: Boolean - if (nb == 1) { - status = sa.last() == sb[0] - } else { - status = sa.last() == sb[nb - 2] - if ((na > 2) and (nb > 2)) { - status = status and - (sa.take(nb - 2).toIntArray() contentEquals sb.take(nb - 2).toIntArray()) - } - } - check(status) { "Incompatible shapes $sa and $sb for dot product" } -} - -public inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkTranspose(dim: Int, i: Int, j: Int): Unit = - check((i < dim) and (j < dim)) { - "Cannot transpose $i to $j for a tensor of dim $dim" - } - -public inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = - check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt index d6a6f5f16..d1d1204b4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt @@ -5,7 +5,7 @@ import space.kscience.kmath.nd.offsetFromIndex import kotlin.math.max -public inline fun stridesFromShape(shape: IntArray): IntArray { +internal inline fun stridesFromShape(shape: IntArray): IntArray { val nDim = shape.size val res = IntArray(nDim) if (nDim == 0) @@ -22,7 +22,7 @@ public inline fun stridesFromShape(shape: IntArray): IntArray { } -public inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { +internal inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { val res = IntArray(nDim) var current = offset var strideIndex = 0 @@ -35,7 +35,7 @@ public inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): In return res } -public inline fun nextIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { +internal inline fun nextIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { val res = index.copyOf() var current = nDim - 1 var carry = 0 diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt new file mode 100644 index 000000000..65409bb15 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt @@ -0,0 +1,96 @@ +package space.kscience.kmath.tensors + +import space.kscience.kmath.structures.array +import kotlin.math.max + + +internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { + var totalDim = 0 + for (shape in shapes) { + totalDim = max(totalDim, shape.size) + } + + val totalShape = IntArray(totalDim) { 0 } + for (shape in shapes) { + for (i in shape.indices) { + val curDim = shape[i] + val offset = totalDim - shape.size + totalShape[i + offset] = max(totalShape[i + offset], curDim) + } + } + + for (shape in shapes) { + for (i in shape.indices) { + val curDim = shape[i] + val offset = totalDim - shape.size + if (curDim != 1 && totalShape[i + offset] != curDim) { + throw RuntimeException("Shapes are not compatible and cannot be broadcast") + } + } + } + + return totalShape +} + +internal inline fun broadcastTensors(vararg tensors: RealTensor): List { + val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) + val n = totalShape.reduce { acc, i -> acc * i } + + val res = ArrayList(0) + for (tensor in tensors) { + val resTensor = RealTensor(totalShape, DoubleArray(n)) + + for (linearIndex in 0 until n) { + val totalMultiIndex = resTensor.strides.index(linearIndex) + val curMultiIndex = tensor.shape.copyOf() + + val offset = totalMultiIndex.size - curMultiIndex.size + + for (i in curMultiIndex.indices) { + if (curMultiIndex[i] != 1) { + curMultiIndex[i] = totalMultiIndex[i + offset] + } else { + curMultiIndex[i] = 0 + } + } + + val curLinearIndex = tensor.strides.offset(curMultiIndex) + resTensor.buffer.array[linearIndex] = tensor.buffer.array[curLinearIndex] + } + res.add(resTensor) + } + + return res +} + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkDot(a: TensorType, b: TensorType): Unit { + val sa = a.shape + val sb = b.shape + val na = sa.size + val nb = sb.size + var status: Boolean + if (nb == 1) { + status = sa.last() == sb[0] + } else { + status = sa.last() == sb[nb - 2] + if ((na > 2) and (nb > 2)) { + status = status and + (sa.take(nb - 2).toIntArray() contentEquals sb.take(nb - 2).toIntArray()) + } + } + check(status) { "Incompatible shapes $sa and $sb for dot product" } +} + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkTranspose(dim: Int, i: Int, j: Int): Unit = + check((i < dim) and (j < dim)) { + "Cannot transpose $i to $j for a tensor of dim $dim" + } + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = + check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index c9fd6bb3a..7c27f5fa9 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -2,8 +2,6 @@ package space.kscience.kmath.tensors import space.kscience.kmath.structures.array import kotlin.test.Test -import kotlin.test.assertFails -import kotlin.test.assertFailsWith import kotlin.test.assertTrue class TestRealTensorAlgebra { @@ -51,11 +49,11 @@ class TestRealTensorAlgebra { @Test fun broadcastShapes() = RealTensorAlgebra { - assertTrue(this.broadcastShapes( + assertTrue(broadcastShapes( intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) ) contentEquals intArrayOf(1, 2, 3)) - assertTrue(this.broadcastShapes( + assertTrue(broadcastShapes( intArrayOf(6, 7), intArrayOf(5, 6, 1), intArrayOf(7,), intArrayOf(5, 1, 7) ) contentEquals intArrayOf(5, 6, 7)) } @@ -66,7 +64,7 @@ class TestRealTensorAlgebra { val tensor2 = RealTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) - val res = this.broadcastTensors(tensor1, tensor2, tensor3) + val res = broadcastTensors(tensor1, tensor2, tensor3) assertTrue(res[0].shape contentEquals intArrayOf(1, 2, 3)) assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) From c02f71263ded2c41806c821c351c58fd40d868ec Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sun, 14 Mar 2021 21:18:20 +0000 Subject: [PATCH 022/211] Adding the interfaces for AnalyticTensorAlgebra and LinearOpsTensorAlgebra --- .../kmath/tensors/AnalyticTensorAlgebra.kt | 112 +++++++++++ .../kmath/tensors/LinearOpsTensorAlgebra.kt | 43 ++++ .../tensors/RealAnalyticTensorAlgebra.kt | 148 ++++++++++++++ .../tensors/RealLinearOpsTensorAlgebra.kt | 133 +++++++++++++ .../kmath/tensors/RealTensorAlgebra.kt | 185 +++++++----------- .../kscience/kmath/tensors/TensorAlgebra.kt | 93 +++++---- .../tensors/TensorPartialDivisionAlgebra.kt | 27 +++ 7 files changed, 586 insertions(+), 155 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt new file mode 100644 index 000000000..17a25b6b3 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt @@ -0,0 +1,112 @@ +package space.kscience.kmath.tensors + + +public interface AnalyticTensorAlgebra> : + TensorPartialDivisionAlgebra { + + //https://pytorch.org/docs/stable/generated/torch.exp.html + public fun TensorType.exp(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.log.html + public fun TensorType.log(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.sqrt.html + public fun TensorType.sqrt(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.square.html + public fun TensorType.square(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos + public fun TensorType.cos(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.acos + public fun TensorType.acos(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.cosh + public fun TensorType.cosh(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.acosh + public fun TensorType.acosh(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sin + public fun TensorType.sin(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asin + public fun TensorType.asin(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sinh + public fun TensorType.sinh(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asinh + public fun TensorType.asinh(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.tan + public fun TensorType.tan(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.atan + public fun TensorType.atan(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.tanh + public fun TensorType.tanh(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.atanh + public fun TensorType.atanh(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.ceil.html#torch.ceil + public fun TensorType.ceil(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor + public fun TensorType.floor(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.clamp.html#torch.clamp + public fun TensorType.clamp(min: T, max: T): TensorType + + //https://pytorch.org/docs/stable/generated/torch.erf.html#torch.erf + public fun TensorType.erf(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.erfinv.html#torch.erfinv + public fun TensorType.erfinv(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.erfc.html#torch.erfc + public fun TensorType.erfc(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.lerp.html#torch.lerp + public fun TensorType.lerp(end: TensorType, weight: TensorType): TensorType + + //https://pytorch.org/docs/stable/generated/torch.lgamma.html#torch.lgamma + public fun TensorType.lgamma(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.logit.html#torch.logit + public fun TensorType.logit(eps: T): TensorType + + //https://pytorch.org/docs/stable/generated/torch.igamma.html#torch.igamma + public fun TensorType.igamma(other: TensorType): TensorType + + //https://pytorch.org/docs/stable/generated/torch.igammac.html#torch.igammac + public fun TensorType.igammac(other: TensorType): TensorType + + //https://pytorch.org/docs/stable/generated/torch.mvlgamma.html#torch.mvlgamma + public fun TensorType.mvlgamma(dimensions: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.polygamma.html#torch.polygamma + public fun TensorType.polygamma(order: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.pow.html#torch.pow + public fun TensorType.pow(exponent: T): TensorType + + //https://pytorch.org/docs/stable/generated/torch.round.html#torch.round + public fun TensorType.round(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.sigmoid.html#torch.sigmoid + public fun TensorType.sigmoid(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.sinc.html#torch.sinc + public fun TensorType.sinc(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.heaviside.html#torch.heaviside + public fun TensorType.heaviside(values: TensorType): TensorType + + //https://pytorch.org/docs/stable/generated/torch.trapz.html#torch.trapz + public fun TensorType.trapz(xValues: TensorType, dim: Int): TensorType + +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt new file mode 100644 index 000000000..bd9cbfd45 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -0,0 +1,43 @@ +package space.kscience.kmath.tensors + + +public interface LinearOpsTensorAlgebra> : + TensorPartialDivisionAlgebra { + + //https://pytorch.org/docs/stable/generated/torch.eye.html + public fun eye(n: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.matmul.html + public infix fun TensorType.dot(other: TensorType): TensorType + + //https://pytorch.org/docs/stable/generated/torch.diag_embed.html + public fun diagonalEmbedding( + diagonalEntries: TensorType, + offset: Int = 0, dim1: Int = -2, dim2: Int = -1 + ): TensorType + + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det + public fun TensorType.det(): TensorType + + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv + public fun TensorType.inv(): TensorType + + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.cholesky + public fun TensorType.cholesky(): TensorType + + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr + public fun TensorType.qr(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.lu.html + public fun TensorType.lu(): Pair + + //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html + public fun luPivot(aLU: TensorType, pivots: IntTensor): Triple + + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd + public fun TensorType.svd(): Triple + + //https://pytorch.org/docs/stable/generated/torch.symeig.html + public fun TensorType.symEig(eigenvectors: Boolean = true): Pair + +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt new file mode 100644 index 000000000..cfecac0f4 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt @@ -0,0 +1,148 @@ +package space.kscience.kmath.tensors + +public class RealAnalyticTensorAlgebra: + AnalyticTensorAlgebra, + RealTensorAlgebra() +{ + override fun RealTensor.exp(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.log(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.sqrt(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.square(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.cos(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.acos(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.cosh(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.acosh(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.sin(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.asin(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.sinh(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.asinh(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.tan(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.atan(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.tanh(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.atanh(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.ceil(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.floor(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.clamp(min: Double, max: Double): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.erf(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.erfinv(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.erfc(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.lerp(end: RealTensor, weight: RealTensor): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.lgamma(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.logit(eps: Double): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.igamma(other: RealTensor): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.igammac(other: RealTensor): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.mvlgamma(dimensions: Int): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.polygamma(order: Int): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.pow(exponent: Double): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.round(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.sigmoid(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.sinc(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.heaviside(values: RealTensor): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.trapz(xValues: RealTensor, dim: Int): RealTensor { + TODO("Not yet implemented") + } + + +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt new file mode 100644 index 000000000..18c2050c0 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt @@ -0,0 +1,133 @@ +package space.kscience.kmath.tensors + +import space.kscience.kmath.structures.array + +public class RealLinearOpsTensorAlgebra : + LinearOpsTensorAlgebra, + RealTensorAlgebra() +{ + override fun eye(n: Int): RealTensor { + val shape = intArrayOf(n, n) + val buffer = DoubleArray(n * n) { 0.0 } + val res = RealTensor(shape, buffer) + for (i in 0 until n) { + res[intArrayOf(i, i)] = 1.0 + } + return res + } + + + override fun RealTensor.dot(other: RealTensor): RealTensor { + TODO("Alya") + } + + override fun diagonalEmbedding(diagonalEntries: RealTensor, offset: Int, dim1: Int, dim2: Int): RealTensor { + TODO("Alya") + } + + + override fun RealTensor.lu(): Pair { + // todo checks + val lu = this.copy() + val m = this.shape[0] + val pivot = IntArray(m) + + + // Initialize permutation array and parity + for (row in 0 until m) pivot[row] = row + var even = true + + for (i in 0 until m) { + var maxA = -1.0 + var iMax = i + + for (k in i until m) { + val absA = kotlin.math.abs(lu[k, i]) + if (absA > maxA) { + maxA = absA + iMax = k + } + } + + //todo check singularity + + if (iMax != i) { + + val j = pivot[i] + pivot[i] = pivot[iMax] + pivot[iMax] = j + even != even + + for (k in 0 until m) { + val tmp = lu[i, k] + lu[i, k] = lu[iMax, k] + lu[iMax, k] = tmp + } + + } + + for (j in i + 1 until m) { + lu[j, i] /= lu[i, i] + for (k in i + 1 until m) { + lu[j, k] -= lu[j, i] * lu[i, k] + } + } + } + return Pair(lu, IntTensor(intArrayOf(m), pivot)) + } + + override fun luPivot(lu: RealTensor, pivots: IntTensor): Triple { + // todo checks + val n = lu.shape[0] + val p = lu.zeroesLike() + pivots.buffer.array.forEachIndexed { i, pivot -> + p[i, pivot] = 1.0 + } + val l = lu.zeroesLike() + val u = lu.zeroesLike() + + for (i in 0 until n) { + for (j in 0 until n) { + if (i == j) { + l[i, j] = 1.0 + } + if (j < i) { + l[i, j] = lu[i, j] + } + if (j >= i) { + u[i, j] = lu[i, j] + } + } + } + return Triple(p, l, u) + } + + override fun RealTensor.det(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.inv(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.cholesky(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.qr(): RealTensor { + TODO("Not yet implemented") + } + + + override fun RealTensor.svd(): Triple { + TODO("Not yet implemented") + } + + override fun RealTensor.symEig(eigenvectors: Boolean): Pair { + TODO("Not yet implemented") + } + +} + +public inline fun RealLinearOpsTensorAlgebra(block: RealTensorAlgebra.() -> R): R = + RealTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index b3e54f077..05e2b57d2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,12 +1,9 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array -import kotlin.math.abs -import kotlin.math.max -public class RealTensorAlgebra : TensorPartialDivisionAlgebra { +public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { override fun RealTensor.value(): Double { check(this.shape contentEquals intArrayOf(1)) { @@ -15,24 +12,13 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra, dim: Int): RealTensor { TODO("Not yet implemented") } @@ -213,6 +246,10 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { - // todo checks - val lu = this.copy() - val m = this.shape[0] - val pivot = IntArray(m) - - - // Initialize permutation array and parity - for (row in 0 until m) pivot[row] = row - var even = true - - for (i in 0 until m) { - var maxA = -1.0 - var iMax = i - - for (k in i until m) { - val absA = abs(lu[k, i]) - if (absA > maxA) { - maxA = absA - iMax = k - } - } - - //todo check singularity - - if (iMax != i) { - - val j = pivot[i] - pivot[i] = pivot[iMax] - pivot[iMax] = j - even != even - - for (k in 0 until m) { - val tmp = lu[i, k] - lu[i, k] = lu[iMax, k] - lu[iMax, k] = tmp - } - - } - - for (j in i + 1 until m) { - lu[j, i] /= lu[i, i] - for (k in i + 1 until m) { - lu[j, k] -= lu[j, i] * lu[i, k] - } - } - } - return Pair(lu, IntTensor(intArrayOf(m), pivot)) - } - - override fun luUnpack(lu: RealTensor, pivots: IntTensor): Triple { - // todo checks - val n = lu.shape[0] - val p = zeroesLike(lu) - pivots.buffer.array.forEachIndexed { i, pivot -> - p[i, pivot] = 1.0 - } - val l = zeroesLike(lu) - val u = zeroesLike(lu) - - for (i in 0 until n){ - for (j in 0 until n){ - if (i == j) { - l[i, j] = 1.0 - } - if (j < i) { - l[i, j] = lu[i, j] - } - if (j >= i) { - u[i, j] = lu[i, j] - } - } - } - return Triple(p, l, u) - } - - override fun RealTensor.svd(): Triple { - /** - * Main first task for @AlyaNovikova - */ + override fun RealTensor.std(dim: Int, unbiased: Boolean, keepDim: Boolean): RealTensor { TODO("Not yet implemented") } - override fun RealTensor.symEig(eigenvectors: Boolean): Pair { + override fun RealTensor.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.histc(bins: Int, min: Double, max: Double): RealTensor { TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 280acf8ea..a53054e21 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -5,11 +5,17 @@ public interface TensorAlgebra> { public fun TensorType.value(): T - public fun eye(n: Int): TensorType public fun zeros(shape: IntArray): TensorType - public fun zeroesLike(other: TensorType): TensorType + public fun TensorType.zeroesLike(): TensorType public fun ones(shape: IntArray): TensorType - public fun onesLike(shape: IntArray): TensorType + public fun TensorType.onesLike(): TensorType + + + //https://pytorch.org/docs/stable/generated/torch.full.html + public fun full(shape: IntArray, value: T): TensorType + + //https://pytorch.org/docs/stable/generated/torch.full_like.html#torch.full_like + public fun TensorType.fullLike(value: T): TensorType public fun TensorType.copy(): TensorType @@ -33,15 +39,6 @@ public interface TensorAlgebra> { public operator fun TensorType.unaryMinus(): TensorType - //https://pytorch.org/docs/stable/generated/torch.matmul.html - public infix fun TensorType.dot(other: TensorType): TensorType - - //https://pytorch.org/docs/stable/generated/torch.diag_embed.html - public fun diagonalEmbedding( - diagonalEntries: TensorType, - offset: Int = 0, dim1: Int = -2, dim2: Int = -1 - ): TensorType - //https://pytorch.org/docs/stable/generated/torch.transpose.html public fun TensorType.transpose(i: Int, j: Int): TensorType @@ -53,35 +50,45 @@ public interface TensorAlgebra> { public fun TensorType.abs(): TensorType //https://pytorch.org/docs/stable/generated/torch.sum.html - public fun TensorType.sum(): TensorType + public fun TensorType.sum(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cumsum.html#torch.cumsum + public fun TensorType.cumsum(dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.prod.html#torch.prod + public fun TensorType.prod(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cumprod.html#torch.cumprod + public fun TensorType.cumprod(dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.max.html#torch.max + public fun TensorType.max(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cummax.html#torch.cummax + public fun TensorType.cummax(dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.min.html#torch.min + public fun TensorType.min(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cummin.html#torch.cummin + public fun TensorType.cummin(dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.median.html#torch.median + public fun TensorType.median(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.maximum.html#torch.maximum + public fun maximum(lhs: TensorType, rhs: TensorType) + + //https://pytorch.org/docs/stable/generated/torch.minimum.html#torch.minimum + public fun minimum(lhs: TensorType, rhs: TensorType) + + //https://pytorch.org/docs/stable/generated/torch.sort.html#torch.sort + public fun TensorType.sort(dim: Int, keepDim: Boolean, descending: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cat.html#torch.cat + public fun cat(tensors: List, dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.flatten.html#torch.flatten + public fun TensorType.flatten(startDim: Int, endDim: Int): TensorType + } - -// https://proofwiki.org/wiki/Definition:Division_Algebra -public interface TensorPartialDivisionAlgebra> : - TensorAlgebra { - - public operator fun TensorType.div(value: T): TensorType - public operator fun TensorType.div(other: TensorType): TensorType - public operator fun TensorType.divAssign(value: T) - public operator fun TensorType.divAssign(other: TensorType) - - //https://pytorch.org/docs/stable/generated/torch.exp.html - public fun TensorType.exp(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.log.html - public fun TensorType.log(): TensorType - - // todo change type of pivots - //https://pytorch.org/docs/stable/generated/torch.lu.html - public fun TensorType.lu(): Pair - - //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun luUnpack(A_LU: TensorType, pivots: IntTensor): Triple - - //https://pytorch.org/docs/stable/generated/torch.svd.html - public fun TensorType.svd(): Triple - - //https://pytorch.org/docs/stable/generated/torch.symeig.html - public fun TensorType.symEig(eigenvectors: Boolean = true): Pair - -} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt new file mode 100644 index 000000000..2d448fa8c --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -0,0 +1,27 @@ +package space.kscience.kmath.tensors + +// https://proofwiki.org/wiki/Definition:Division_Algebra +public interface TensorPartialDivisionAlgebra> : + TensorAlgebra { + + public operator fun TensorType.div(value: T): TensorType + public operator fun TensorType.div(other: TensorType): TensorType + public operator fun TensorType.divAssign(value: T) + public operator fun TensorType.divAssign(other: TensorType) + + //https://pytorch.org/docs/stable/generated/torch.mean.html#torch.mean + public fun TensorType.mean(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.quantile.html#torch.quantile + public fun TensorType.quantile(q: T, dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.std.html#torch.std + public fun TensorType.std(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var + public fun TensorType.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.histc.html#torch.histc + public fun TensorType.histc(bins: Int, min: T, max: T): TensorType + +} From 39a088912346078f3c3647ac262b2cf8c490aa4a Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 07:50:20 +0000 Subject: [PATCH 023/211] Dev merge assemble fixed, tests still broken --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 2 +- .../tensors/RealAnalyticTensorAlgebra.kt | 4 +- .../tensors/RealLinearOpsTensorAlgebra.kt | 7 +-- .../kmath/tensors/RealTensorAlgebra.kt | 46 +++++++++---------- .../space/kscience/kmath/tensors/utils.kt | 4 +- .../kscience/kmath/tensors/TestRealTensor.kt | 4 +- .../kmath/tensors/TestRealTensorAlgebra.kt | 26 +++++------ 7 files changed, 48 insertions(+), 45 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index bd9cbfd45..db1135a33 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -32,7 +32,7 @@ public interface LinearOpsTensorAlgebra> : public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun luPivot(aLU: TensorType, pivots: IntTensor): Triple + public fun luPivot(lu: TensorType, pivots: IntTensor): Triple //https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd public fun TensorType.svd(): Triple diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt index cfecac0f4..a93ebcb89 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt @@ -144,5 +144,7 @@ public class RealAnalyticTensorAlgebra: TODO("Not yet implemented") } +} -} \ No newline at end of file +public inline fun RealAnalyticTensorAlgebra(block: RealTensorAlgebra.() -> R): R = + RealAnalyticTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt index 18c2050c0..98a5e581f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.array +import space.kscience.kmath.structures.toDoubleArray +import space.kscience.kmath.structures.toIntArray public class RealLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -80,7 +81,7 @@ public class RealLinearOpsTensorAlgebra : // todo checks val n = lu.shape[0] val p = lu.zeroesLike() - pivots.buffer.array.forEachIndexed { i, pivot -> + pivots.buffer.toIntArray().forEachIndexed { i, pivot -> p[i, pivot] = 1.0 } val l = lu.zeroesLike() @@ -130,4 +131,4 @@ public class RealLinearOpsTensorAlgebra : } public inline fun RealLinearOpsTensorAlgebra(block: RealTensorAlgebra.() -> R): R = - RealTensorAlgebra().block() \ No newline at end of file + RealLinearOpsTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 05e2b57d2..10cc0edad 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.array +import space.kscience.kmath.structures.toDoubleArray public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { @@ -9,7 +9,7 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.array[i] + this + other.buffer.toDoubleArray()[i] + this } return RealTensor(other.shape, resBuffer) } @@ -50,34 +50,34 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.array[i] + newOther.buffer.array[i] + newThis.buffer.toDoubleArray()[i] + newOther.buffer.toDoubleArray()[i] } return RealTensor(newThis.shape, resBuffer) } override fun RealTensor.plusAssign(value: Double) { - for (i in this.buffer.array.indices) { - this.buffer.array[i] += value + for (i in this.buffer.toDoubleArray().indices) { + this.buffer.toDoubleArray()[i] += value } } override fun RealTensor.plusAssign(other: RealTensor) { //todo should be change with broadcasting - for (i in this.buffer.array.indices) { - this.buffer.array[i] += other.buffer.array[i] + for (i in this.buffer.toDoubleArray().indices) { + this.buffer.toDoubleArray()[i] += other.buffer.toDoubleArray()[i] } } override fun Double.minus(other: RealTensor): RealTensor { val resBuffer = DoubleArray(other.buffer.size) { i -> - this - other.buffer.array[i] + this - other.buffer.toDoubleArray()[i] } return RealTensor(other.shape, resBuffer) } override fun RealTensor.minus(value: Double): RealTensor { val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.array[i] - value + this.buffer.toDoubleArray()[i] - value } return RealTensor(this.shape, resBuffer) } @@ -87,14 +87,14 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.array[i] - newOther.buffer.array[i] + newThis.buffer.toDoubleArray()[i] - newOther.buffer.toDoubleArray()[i] } return RealTensor(newThis.shape, resBuffer) } override fun RealTensor.minusAssign(value: Double) { - for (i in this.buffer.array.indices) { - this.buffer.array[i] -= value + for (i in this.buffer.toDoubleArray().indices) { + this.buffer.toDoubleArray()[i] -= value } } @@ -105,7 +105,7 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.array[i] * this + other.buffer.toDoubleArray()[i] * this } return RealTensor(other.shape, resBuffer) } @@ -116,28 +116,28 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - this.buffer.array[i] * other.buffer.array[i] + this.buffer.toDoubleArray()[i] * other.buffer.toDoubleArray()[i] } return RealTensor(this.shape, resBuffer) } override fun RealTensor.timesAssign(value: Double) { //todo should be change with broadcasting - for (i in this.buffer.array.indices) { - this.buffer.array[i] *= value + for (i in this.buffer.toDoubleArray().indices) { + this.buffer.toDoubleArray()[i] *= value } } override fun RealTensor.timesAssign(other: RealTensor) { //todo should be change with broadcasting - for (i in this.buffer.array.indices) { - this.buffer.array[i] *= other.buffer.array[i] + for (i in this.buffer.toDoubleArray().indices) { + this.buffer.toDoubleArray()[i] *= other.buffer.toDoubleArray()[i] } } override fun RealTensor.unaryMinus(): RealTensor { val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.array[i].unaryMinus() + this.buffer.toDoubleArray()[i].unaryMinus() } return RealTensor(this.shape, resBuffer) } @@ -158,14 +158,14 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra Date: Mon, 15 Mar 2021 08:31:19 +0000 Subject: [PATCH 024/211] Fixed tests with unsafe accessors --- .../kscience/kmath/structures/FloatBuffer.kt | 8 ++++ .../kscience/kmath/structures/IntBuffer.kt | 8 ++++ .../kscience/kmath/structures/LongBuffer.kt | 8 ++++ .../kscience/kmath/structures/RealBuffer.kt | 8 ++++ .../tensors/RealLinearOpsTensorAlgebra.kt | 5 +- .../kmath/tensors/RealTensorAlgebra.kt | 46 +++++++++---------- .../space/kscience/kmath/tensors/utils.kt | 4 +- 7 files changed, 59 insertions(+), 28 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt index 9fc7d55f3..dbcf35504 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt @@ -43,6 +43,14 @@ public fun Buffer.toFloatArray(): FloatArray = when(this) { else -> FloatArray(size, ::get) } +/** + * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. + */ +public fun Buffer.unsafeToFloatArray(): FloatArray = when(this) { + is FloatBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to FloatArray") +} + /** * Returns [FloatBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt index d3d0f79a5..d58451bc4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt @@ -42,6 +42,14 @@ public fun Buffer.toIntArray(): IntArray = when(this) { else -> IntArray(size, ::get) } +/** + * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. + */ +public fun Buffer.unsafeToIntArray(): IntArray = when(this) { + is IntBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to IntArray") +} + /** * Returns [IntBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt index fec358421..3fa9bf861 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt @@ -42,6 +42,14 @@ public fun Buffer.toLongArray(): LongArray = when(this) { else -> LongArray(size, ::get) } +/** + * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. + */ +public fun Buffer.unsafeToLongArray(): LongArray = when(this) { + is LongBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to LongArray") +} + /** * Returns [LongBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt index 01b533138..69e1ae9cd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt @@ -47,6 +47,14 @@ public fun Buffer.toDoubleArray(): DoubleArray = when(this) { else -> DoubleArray(size, ::get) } +/** + * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. + */ +public fun Buffer.unsafeToDoubleArray(): DoubleArray = when(this) { + is RealBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") +} + /** * Returns [RealBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt index 98a5e581f..f73e4c4cd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt @@ -1,7 +1,6 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.toDoubleArray -import space.kscience.kmath.structures.toIntArray +import space.kscience.kmath.structures.unsafeToIntArray public class RealLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -81,7 +80,7 @@ public class RealLinearOpsTensorAlgebra : // todo checks val n = lu.shape[0] val p = lu.zeroesLike() - pivots.buffer.toIntArray().forEachIndexed { i, pivot -> + pivots.buffer.unsafeToIntArray().forEachIndexed { i, pivot -> p[i, pivot] = 1.0 } val l = lu.zeroesLike() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 10cc0edad..ee0733577 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.toDoubleArray +import space.kscience.kmath.structures.unsafeToDoubleArray public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { @@ -9,7 +9,7 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.toDoubleArray()[i] + this + other.buffer.unsafeToDoubleArray()[i] + this } return RealTensor(other.shape, resBuffer) } @@ -50,34 +50,34 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.toDoubleArray()[i] + newOther.buffer.toDoubleArray()[i] + newThis.buffer.unsafeToDoubleArray()[i] + newOther.buffer.unsafeToDoubleArray()[i] } return RealTensor(newThis.shape, resBuffer) } override fun RealTensor.plusAssign(value: Double) { - for (i in this.buffer.toDoubleArray().indices) { - this.buffer.toDoubleArray()[i] += value + for (i in this.buffer.unsafeToDoubleArray().indices) { + this.buffer.unsafeToDoubleArray()[i] += value } } override fun RealTensor.plusAssign(other: RealTensor) { //todo should be change with broadcasting - for (i in this.buffer.toDoubleArray().indices) { - this.buffer.toDoubleArray()[i] += other.buffer.toDoubleArray()[i] + for (i in this.buffer.unsafeToDoubleArray().indices) { + this.buffer.unsafeToDoubleArray()[i] += other.buffer.unsafeToDoubleArray()[i] } } override fun Double.minus(other: RealTensor): RealTensor { val resBuffer = DoubleArray(other.buffer.size) { i -> - this - other.buffer.toDoubleArray()[i] + this - other.buffer.unsafeToDoubleArray()[i] } return RealTensor(other.shape, resBuffer) } override fun RealTensor.minus(value: Double): RealTensor { val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.toDoubleArray()[i] - value + this.buffer.unsafeToDoubleArray()[i] - value } return RealTensor(this.shape, resBuffer) } @@ -87,14 +87,14 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.toDoubleArray()[i] - newOther.buffer.toDoubleArray()[i] + newThis.buffer.unsafeToDoubleArray()[i] - newOther.buffer.unsafeToDoubleArray()[i] } return RealTensor(newThis.shape, resBuffer) } override fun RealTensor.minusAssign(value: Double) { - for (i in this.buffer.toDoubleArray().indices) { - this.buffer.toDoubleArray()[i] -= value + for (i in this.buffer.unsafeToDoubleArray().indices) { + this.buffer.unsafeToDoubleArray()[i] -= value } } @@ -105,7 +105,7 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.toDoubleArray()[i] * this + other.buffer.unsafeToDoubleArray()[i] * this } return RealTensor(other.shape, resBuffer) } @@ -116,28 +116,28 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - this.buffer.toDoubleArray()[i] * other.buffer.toDoubleArray()[i] + this.buffer.unsafeToDoubleArray()[i] * other.buffer.unsafeToDoubleArray()[i] } return RealTensor(this.shape, resBuffer) } override fun RealTensor.timesAssign(value: Double) { //todo should be change with broadcasting - for (i in this.buffer.toDoubleArray().indices) { - this.buffer.toDoubleArray()[i] *= value + for (i in this.buffer.unsafeToDoubleArray().indices) { + this.buffer.unsafeToDoubleArray()[i] *= value } } override fun RealTensor.timesAssign(other: RealTensor) { //todo should be change with broadcasting - for (i in this.buffer.toDoubleArray().indices) { - this.buffer.toDoubleArray()[i] *= other.buffer.toDoubleArray()[i] + for (i in this.buffer.unsafeToDoubleArray().indices) { + this.buffer.unsafeToDoubleArray()[i] *= other.buffer.unsafeToDoubleArray()[i] } } override fun RealTensor.unaryMinus(): RealTensor { val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.toDoubleArray()[i].unaryMinus() + this.buffer.unsafeToDoubleArray()[i].unaryMinus() } return RealTensor(this.shape, resBuffer) } @@ -158,14 +158,14 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra Date: Mon, 15 Mar 2021 08:48:31 +0000 Subject: [PATCH 025/211] unsafe buffer casts moved to internal utils --- .../kscience/kmath/structures/FloatBuffer.kt | 8 ----- .../kscience/kmath/structures/IntBuffer.kt | 8 ----- .../kscience/kmath/structures/LongBuffer.kt | 8 ----- .../kscience/kmath/structures/RealBuffer.kt | 8 ----- .../tensors/RealLinearOpsTensorAlgebra.kt | 2 -- .../kmath/tensors/RealTensorAlgebra.kt | 2 -- .../space/kscience/kmath/tensors/utils.kt | 36 +++++++++++++++++-- .../kmath/tensors/TestRealTensorAlgebra.kt | 26 +++++++------- 8 files changed, 47 insertions(+), 51 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt index dbcf35504..9fc7d55f3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt @@ -43,14 +43,6 @@ public fun Buffer.toFloatArray(): FloatArray = when(this) { else -> FloatArray(size, ::get) } -/** - * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. - */ -public fun Buffer.unsafeToFloatArray(): FloatArray = when(this) { - is FloatBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to FloatArray") -} - /** * Returns [FloatBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt index d58451bc4..d3d0f79a5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt @@ -42,14 +42,6 @@ public fun Buffer.toIntArray(): IntArray = when(this) { else -> IntArray(size, ::get) } -/** - * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. - */ -public fun Buffer.unsafeToIntArray(): IntArray = when(this) { - is IntBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to IntArray") -} - /** * Returns [IntBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt index 3fa9bf861..fec358421 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt @@ -42,14 +42,6 @@ public fun Buffer.toLongArray(): LongArray = when(this) { else -> LongArray(size, ::get) } -/** - * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. - */ -public fun Buffer.unsafeToLongArray(): LongArray = when(this) { - is LongBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to LongArray") -} - /** * Returns [LongBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt index 69e1ae9cd..01b533138 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt @@ -47,14 +47,6 @@ public fun Buffer.toDoubleArray(): DoubleArray = when(this) { else -> DoubleArray(size, ::get) } -/** - * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. - */ -public fun Buffer.unsafeToDoubleArray(): DoubleArray = when(this) { - is RealBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") -} - /** * Returns [RealBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt index f73e4c4cd..dcd740356 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt @@ -1,7 +1,5 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.unsafeToIntArray - public class RealLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, RealTensorAlgebra() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index ee0733577..83a513a7a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,7 +1,5 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.unsafeToDoubleArray - public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt index 04b4ddcbf..b03fb7dd7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.unsafeToDoubleArray +import space.kscience.kmath.structures.* import kotlin.math.max @@ -93,4 +93,36 @@ internal inline fun , internal inline fun , TorchTensorAlgebraType : TensorAlgebra> TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = - check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) \ No newline at end of file + check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) + +/** + * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.unsafeToIntArray(): IntArray = when(this) { + is IntBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to IntArray") +} + +/** + * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.unsafeToLongArray(): LongArray = when(this) { + is LongBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to LongArray") +} + +/** + * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.unsafeToFloatArray(): FloatArray = when(this) { + is FloatBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to FloatArray") +} + +/** + * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.unsafeToDoubleArray(): DoubleArray = when(this) { + is RealBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") +} diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index 80e3c3eab..72bbf1787 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.toDoubleArray + import kotlin.test.Test import kotlin.test.assertTrue @@ -10,7 +10,7 @@ class TestRealTensorAlgebra { fun doublePlus() = RealTensorAlgebra { val tensor = RealTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor - assertTrue(res.buffer.toDoubleArray() contentEquals doubleArrayOf(11.0,12.0)) + assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(11.0,12.0)) } @Test @@ -18,7 +18,7 @@ class TestRealTensorAlgebra { val tensor = RealTensor(intArrayOf(1), doubleArrayOf(0.0)) val res = tensor.transpose(0, 0) - assertTrue(res.buffer.toDoubleArray() contentEquals doubleArrayOf(0.0)) + assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(0.0)) assertTrue(res.shape contentEquals intArrayOf(1)) } @@ -27,7 +27,7 @@ class TestRealTensorAlgebra { val tensor = RealTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) - assertTrue(res.buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) + assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) assertTrue(res.shape contentEquals intArrayOf(2, 3)) } @@ -42,9 +42,9 @@ class TestRealTensorAlgebra { assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2)) - assertTrue(res01.buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res02.buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) - assertTrue(res12.buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res01.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res02.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res12.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) } @Test @@ -70,9 +70,9 @@ class TestRealTensorAlgebra { assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[0].buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res[1].buffer.toDoubleArray() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) - assertTrue(res[2].buffer.toDoubleArray() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) + assertTrue(res[0].buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + assertTrue(res[2].buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) } @Test @@ -82,14 +82,14 @@ class TestRealTensorAlgebra { val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) assertTrue((tensor2 - tensor1).shape contentEquals intArrayOf(2, 3)) - assertTrue((tensor2 - tensor1).buffer.toDoubleArray() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) + assertTrue((tensor2 - tensor1).buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) assertTrue((tensor3 - tensor1).shape contentEquals intArrayOf(1, 2, 3)) - assertTrue((tensor3 - tensor1).buffer.toDoubleArray() + assertTrue((tensor3 - tensor1).buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0)) assertTrue((tensor3 - tensor2).shape contentEquals intArrayOf(1, 1, 3)) - assertTrue((tensor3 - tensor2).buffer.toDoubleArray() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) + assertTrue((tensor3 - tensor2).buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) } } \ No newline at end of file From 2d2c5aa6840902db6c5688d19e2960b124b5e0d3 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Mon, 15 Mar 2021 15:18:21 +0300 Subject: [PATCH 026/211] matrixhelper --- .../kscience/kmath/tensors/BufferedTensor.kt | 53 ++++++++ .../tensors/RealLinearOpsTensorAlgebra.kt | 116 ++++++++++-------- 2 files changed, 120 insertions(+), 49 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index 29605024d..4d89996a0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -13,6 +13,7 @@ public open class BufferedTensor( TensorStrides(shape), buffer ) { + /* public operator fun get(i: Int, j: Int): T { check(this.dimension == 2) { "Not matrix" } @@ -24,8 +25,60 @@ public open class BufferedTensor( this[intArrayOf(i, j)] = value } + */ } +//todo make generator mb nextMatrixIndex? +public class InnerMatrix(private val tensor: BufferedTensor){ + private var offset: Int = 0 + private val n : Int = tensor.shape.size + //stride? + private val step = tensor.shape[n - 1] * tensor.shape[n - 2] + + public operator fun get(i: Int, j: Int): T { + val index = tensor.strides.index(offset) + index[n - 2] = i + index[n - 1] = j + return tensor[index] + } + + public operator fun set(i: Int, j: Int, value: T): Unit { + val index = tensor.strides.index(offset) + index[n - 2] = i + index[n - 1] = j + tensor[index] = value + } + + public fun makeStep(){ + offset += step + } +} + +public class InnerVector(private val tensor: BufferedTensor){ + private var offset: Int = 0 + private val n : Int = tensor.shape.size + //stride? + private val step = tensor.shape[n - 1] + + public operator fun get(i: Int): T { + val index = tensor.strides.index(offset) + index[n - 1] = i + return tensor[index] + } + + public operator fun set(i: Int, value: T): Unit { + val index = tensor.strides.index(offset) + index[n - 1] = i + tensor[index] = value + } + + public fun makeStep(){ + offset += step + } +} + + +//todo default buffer = arrayOf(0)??? public class IntTensor( shape: IntArray, buffer: IntArray diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt index dcd740356..ab39fc6ac 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt @@ -2,8 +2,7 @@ package space.kscience.kmath.tensors public class RealLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, - RealTensorAlgebra() -{ + RealTensorAlgebra() { override fun eye(n: Int): RealTensor { val shape = intArrayOf(n, n) val buffer = DoubleArray(n * n) { 0.0 } @@ -26,55 +25,71 @@ public class RealLinearOpsTensorAlgebra : override fun RealTensor.lu(): Pair { // todo checks - val lu = this.copy() - val m = this.shape[0] - val pivot = IntArray(m) - - - // Initialize permutation array and parity - for (row in 0 until m) pivot[row] = row - var even = true - - for (i in 0 until m) { - var maxA = -1.0 - var iMax = i - - for (k in i until m) { - val absA = kotlin.math.abs(lu[k, i]) - if (absA > maxA) { - maxA = absA - iMax = k - } - } - - //todo check singularity - - if (iMax != i) { - - val j = pivot[i] - pivot[i] = pivot[iMax] - pivot[iMax] = j - even != even - - for (k in 0 until m) { - val tmp = lu[i, k] - lu[i, k] = lu[iMax, k] - lu[iMax, k] = tmp - } - - } - - for (j in i + 1 until m) { - lu[j, i] /= lu[i, i] - for (k in i + 1 until m) { - lu[j, k] -= lu[j, i] * lu[i, k] - } - } + val luTensor = this.copy() + val lu = InnerMatrix(luTensor) + //stride TODO!!! move to generator? + var matCnt = 1 + for (i in 0 until this.shape.size - 2) { + matCnt *= this.shape[i] } - return Pair(lu, IntTensor(intArrayOf(m), pivot)) + val n = this.shape.size + val m = this.shape[n - 1] + val pivotsShape = IntArray(n - 1) { i -> + this.shape[i] + } + val pivotsTensor = IntTensor( + pivotsShape, + IntArray(matCnt * m) { 0 } + ) + val pivot = InnerVector(pivotsTensor) + for (i in 0 until matCnt) { + for (row in 0 until m) pivot[row] = row + + for (i in 0 until m) { + var maxA = -1.0 + var iMax = i + + for (k in i until m) { + val absA = kotlin.math.abs(lu[k, i]) + if (absA > maxA) { + maxA = absA + iMax = k + } + } + + //todo check singularity + + if (iMax != i) { + + val j = pivot[i] + pivot[i] = pivot[iMax] + pivot[iMax] = j + + for (k in 0 until m) { + val tmp = lu[i, k] + lu[i, k] = lu[iMax, k] + lu[iMax, k] = tmp + } + + } + + for (j in i + 1 until m) { + lu[j, i] /= lu[i, i] + for (k in i + 1 until m) { + lu[j, k] -= lu[j, i] * lu[i, k] + } + } + } + lu.makeStep() + pivot.makeStep() + } + + return Pair(luTensor, pivotsTensor) } override fun luPivot(lu: RealTensor, pivots: IntTensor): Triple { + TODO() + /* // todo checks val n = lu.shape[0] val p = lu.zeroesLike() @@ -97,9 +112,12 @@ public class RealLinearOpsTensorAlgebra : } } } - return Triple(p, l, u) + + return Triple(p, l, u)*/ } + + override fun RealTensor.det(): RealTensor { TODO("Not yet implemented") } @@ -127,5 +145,5 @@ public class RealLinearOpsTensorAlgebra : } -public inline fun RealLinearOpsTensorAlgebra(block: RealTensorAlgebra.() -> R): R = +public inline fun RealLinearOpsTensorAlgebra(block: RealLinearOpsTensorAlgebra.() -> R): R = RealLinearOpsTensorAlgebra().block() \ No newline at end of file From 50ed7ce28bb072f33a3527879fe8d9453cba6ac4 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 12:54:46 +0000 Subject: [PATCH 027/211] ComplexTensorAlgebra interface --- .../kmath/tensors/ComplexTensorAlgebra.kt | 47 +++++++++++++++++++ .../kmath/tensors/ComplexTensorStructure.kt | 14 ++++++ .../tensors/RealAnalyticTensorAlgebra.kt | 2 +- .../tensors/RealLinearOpsTensorAlgebra.kt | 2 +- 4 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt new file mode 100644 index 000000000..3f5b7d667 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt @@ -0,0 +1,47 @@ +package space.kscience.kmath.tensors + +public interface ComplexTensorAlgebra, + ComplexTensorType : ComplexTensorStructure> + : TensorPartialDivisionAlgebra{ + + //https://pytorch.org/docs/stable/generated/torch.view_as_complex.html + public fun RealTensorType.viewAsComplex(): ComplexTensorType + + //https://pytorch.org/docs/stable/generated/torch.angle.html + public fun ComplexTensorType.angle(): RealTensorType + + //https://pytorch.org/docs/stable/generated/torch.stft.html#torch.stft + public fun ComplexTensorType.stft( + nFFT: Int, + hopLength: Int, + winLength: Int, + window: RealTensorType, + normalised: Boolean, + oneSided: Boolean + ) + + //https://pytorch.org/docs/stable/generated/torch.istft.html#torch.istft + public fun ComplexTensorType.istft( + nFFT: Int, + hopLength: Int, + winLength: Int, + window: RealTensorType, + center: Boolean, + normalised: Boolean, + oneSided: Boolean, + length: Int + ) + + //https://pytorch.org/docs/stable/generated/torch.bartlett_window.html#torch.bartlett_window + public fun bartlettWindow(windowLength: Int, periodic: Boolean): RealTensorType + + //https://pytorch.org/docs/stable/generated/torch.blackman_window.html#torch.blackman_window + public fun blackmanWindow(windowLength: Int, periodic: Boolean): RealTensorType + + //https://pytorch.org/docs/stable/generated/torch.hamming_window.html#torch.hamming_window + public fun hammingWindow(windowLength: Int, periodic: Boolean, alpha: T, beta: T): RealTensorType + + //https://pytorch.org/docs/stable/generated/torch.kaiser_window.html#torch.kaiser_window + public fun kaiserWindow(windowLength: Int, periodic: Boolean, beta: T): RealTensorType +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt new file mode 100644 index 000000000..0e0975830 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt @@ -0,0 +1,14 @@ +package space.kscience.kmath.tensors + +public interface ComplexTensorStructure> : TensorStructure { + + //https://pytorch.org/docs/master/generated/torch.view_as_real.html + public fun viewAsReal(): RealTensorType + + //https://pytorch.org/docs/stable/generated/torch.real.html + public fun realPart(): RealTensorType + + //https://pytorch.org/docs/stable/generated/torch.imag.html + public fun imaginaryPart(): RealTensorType + +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt index a93ebcb89..f610361fc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt @@ -146,5 +146,5 @@ public class RealAnalyticTensorAlgebra: } -public inline fun RealAnalyticTensorAlgebra(block: RealTensorAlgebra.() -> R): R = +public inline fun RealAnalyticTensorAlgebra(block: RealAnalyticTensorAlgebra.() -> R): R = RealAnalyticTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt index dcd740356..6b1957b8c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt @@ -127,5 +127,5 @@ public class RealLinearOpsTensorAlgebra : } -public inline fun RealLinearOpsTensorAlgebra(block: RealTensorAlgebra.() -> R): R = +public inline fun RealLinearOpsTensorAlgebra(block: RealLinearOpsTensorAlgebra.() -> R): R = RealLinearOpsTensorAlgebra().block() \ No newline at end of file From a3ca861ebe034fc1a8b08f18c2613df3ef81c785 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 13:05:45 +0000 Subject: [PATCH 028/211] Rename FFTs --- .../space/kscience/kmath/tensors/ComplexTensorAlgebra.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt index 3f5b7d667..8399511a5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt @@ -12,7 +12,7 @@ public interface ComplexTensorAlgebra Date: Mon, 15 Mar 2021 16:59:50 +0000 Subject: [PATCH 029/211] RealTensor to DoubleTensor rename --- .../kscience/kmath/tensors/BufferedTensor.kt | 2 +- .../tensors/DoubleAnalyticTensorAlgebra.kt | 150 ++++++++++++++++++ ...bra.kt => DoubleLinearOpsTensorAlgebra.kt} | 26 +-- ...ensorAlgebra.kt => DoubleTensorAlgebra.kt} | 128 +++++++-------- .../tensors/RealAnalyticTensorAlgebra.kt | 150 ------------------ .../space/kscience/kmath/tensors/utils.kt | 6 +- .../kscience/kmath/tensors/TestRealTensor.kt | 4 +- .../kmath/tensors/TestRealTensorAlgebra.kt | 20 +-- 8 files changed, 243 insertions(+), 243 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{RealLinearOpsTensorAlgebra.kt => DoubleLinearOpsTensorAlgebra.kt} (73%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{RealTensorAlgebra.kt => DoubleTensorAlgebra.kt} (54%) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index 29605024d..066fb8708 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -41,7 +41,7 @@ public class FloatTensor( buffer: FloatArray ) : BufferedTensor(shape, FloatBuffer(buffer)) -public class RealTensor( +public class DoubleTensor( shape: IntArray, buffer: DoubleArray ) : BufferedTensor(shape, RealBuffer(buffer)) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt new file mode 100644 index 000000000..702049a20 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt @@ -0,0 +1,150 @@ +package space.kscience.kmath.tensors + +public class RealAnalyticTensorAlgebra: + AnalyticTensorAlgebra, + RealTensorAlgebra() +{ + override fun DoubleTensor.exp(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.log(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.sqrt(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.square(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.cos(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.acos(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.cosh(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.acosh(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.sin(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.asin(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.sinh(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.asinh(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.tan(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.atan(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.tanh(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.atanh(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.ceil(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.floor(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.clamp(min: Double, max: Double): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.erf(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.erfinv(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.erfc(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.lerp(end: DoubleTensor, weight: DoubleTensor): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.lgamma(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.logit(eps: Double): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.igamma(other: DoubleTensor): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.igammac(other: DoubleTensor): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.mvlgamma(dimensions: Int): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.polygamma(order: Int): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.pow(exponent: Double): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.round(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.sigmoid(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.sinc(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.heaviside(values: DoubleTensor): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.trapz(xValues: DoubleTensor, dim: Int): DoubleTensor { + TODO("Not yet implemented") + } + +} + +public inline fun RealAnalyticTensorAlgebra(block: RealAnalyticTensorAlgebra.() -> R): R = + RealAnalyticTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt similarity index 73% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt index 6b1957b8c..5fd8c4151 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt @@ -1,13 +1,13 @@ package space.kscience.kmath.tensors public class RealLinearOpsTensorAlgebra : - LinearOpsTensorAlgebra, + LinearOpsTensorAlgebra, RealTensorAlgebra() { - override fun eye(n: Int): RealTensor { + override fun eye(n: Int): DoubleTensor { val shape = intArrayOf(n, n) val buffer = DoubleArray(n * n) { 0.0 } - val res = RealTensor(shape, buffer) + val res = DoubleTensor(shape, buffer) for (i in 0 until n) { res[intArrayOf(i, i)] = 1.0 } @@ -15,16 +15,16 @@ public class RealLinearOpsTensorAlgebra : } - override fun RealTensor.dot(other: RealTensor): RealTensor { + override fun DoubleTensor.dot(other: DoubleTensor): DoubleTensor { TODO("Alya") } - override fun diagonalEmbedding(diagonalEntries: RealTensor, offset: Int, dim1: Int, dim2: Int): RealTensor { + override fun diagonalEmbedding(diagonalEntries: DoubleTensor, offset: Int, dim1: Int, dim2: Int): DoubleTensor { TODO("Alya") } - override fun RealTensor.lu(): Pair { + override fun DoubleTensor.lu(): Pair { // todo checks val lu = this.copy() val m = this.shape[0] @@ -74,7 +74,7 @@ public class RealLinearOpsTensorAlgebra : return Pair(lu, IntTensor(intArrayOf(m), pivot)) } - override fun luPivot(lu: RealTensor, pivots: IntTensor): Triple { + override fun luPivot(lu: DoubleTensor, pivots: IntTensor): Triple { // todo checks val n = lu.shape[0] val p = lu.zeroesLike() @@ -100,28 +100,28 @@ public class RealLinearOpsTensorAlgebra : return Triple(p, l, u) } - override fun RealTensor.det(): RealTensor { + override fun DoubleTensor.det(): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.inv(): RealTensor { + override fun DoubleTensor.inv(): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.cholesky(): RealTensor { + override fun DoubleTensor.cholesky(): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.qr(): RealTensor { + override fun DoubleTensor.qr(): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.svd(): Triple { + override fun DoubleTensor.svd(): Triple { TODO("Not yet implemented") } - override fun RealTensor.symEig(eigenvectors: Boolean): Pair { + override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt similarity index 54% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 83a513a7a..dd15a257c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -1,146 +1,146 @@ package space.kscience.kmath.tensors -public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { +public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { - override fun RealTensor.value(): Double { + override fun DoubleTensor.value(): Double { check(this.shape contentEquals intArrayOf(1)) { "Inconsistent value for tensor of shape ${shape.toList()}" } return this.buffer.unsafeToDoubleArray()[0] } - override fun zeros(shape: IntArray): RealTensor { + override fun zeros(shape: IntArray): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.zeroesLike(): RealTensor { + override fun DoubleTensor.zeroesLike(): DoubleTensor { val shape = this.shape val buffer = DoubleArray(this.buffer.size) { 0.0 } - return RealTensor(shape, buffer) + return DoubleTensor(shape, buffer) } - override fun ones(shape: IntArray): RealTensor { + override fun ones(shape: IntArray): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.onesLike(): RealTensor { + override fun DoubleTensor.onesLike(): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.copy(): RealTensor { + override fun DoubleTensor.copy(): DoubleTensor { // should be rework as soon as copy() method for NDBuffer will be available - return RealTensor(this.shape, this.buffer.unsafeToDoubleArray().copyOf()) + return DoubleTensor(this.shape, this.buffer.unsafeToDoubleArray().copyOf()) } - override fun Double.plus(other: RealTensor): RealTensor { + override fun Double.plus(other: DoubleTensor): DoubleTensor { val resBuffer = DoubleArray(other.buffer.size) { i -> other.buffer.unsafeToDoubleArray()[i] + this } - return RealTensor(other.shape, resBuffer) + return DoubleTensor(other.shape, resBuffer) } - override fun RealTensor.plus(value: Double): RealTensor = value + this + override fun DoubleTensor.plus(value: Double): DoubleTensor = value + this - override fun RealTensor.plus(other: RealTensor): RealTensor { + override fun DoubleTensor.plus(other: DoubleTensor): DoubleTensor { val broadcast = broadcastTensors(this, other) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.buffer.size) { i -> newThis.buffer.unsafeToDoubleArray()[i] + newOther.buffer.unsafeToDoubleArray()[i] } - return RealTensor(newThis.shape, resBuffer) + return DoubleTensor(newThis.shape, resBuffer) } - override fun RealTensor.plusAssign(value: Double) { + override fun DoubleTensor.plusAssign(value: Double) { for (i in this.buffer.unsafeToDoubleArray().indices) { this.buffer.unsafeToDoubleArray()[i] += value } } - override fun RealTensor.plusAssign(other: RealTensor) { + override fun DoubleTensor.plusAssign(other: DoubleTensor) { //todo should be change with broadcasting for (i in this.buffer.unsafeToDoubleArray().indices) { this.buffer.unsafeToDoubleArray()[i] += other.buffer.unsafeToDoubleArray()[i] } } - override fun Double.minus(other: RealTensor): RealTensor { + override fun Double.minus(other: DoubleTensor): DoubleTensor { val resBuffer = DoubleArray(other.buffer.size) { i -> this - other.buffer.unsafeToDoubleArray()[i] } - return RealTensor(other.shape, resBuffer) + return DoubleTensor(other.shape, resBuffer) } - override fun RealTensor.minus(value: Double): RealTensor { + override fun DoubleTensor.minus(value: Double): DoubleTensor { val resBuffer = DoubleArray(this.buffer.size) { i -> this.buffer.unsafeToDoubleArray()[i] - value } - return RealTensor(this.shape, resBuffer) + return DoubleTensor(this.shape, resBuffer) } - override fun RealTensor.minus(other: RealTensor): RealTensor { + override fun DoubleTensor.minus(other: DoubleTensor): DoubleTensor { val broadcast = broadcastTensors(this, other) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.buffer.size) { i -> newThis.buffer.unsafeToDoubleArray()[i] - newOther.buffer.unsafeToDoubleArray()[i] } - return RealTensor(newThis.shape, resBuffer) + return DoubleTensor(newThis.shape, resBuffer) } - override fun RealTensor.minusAssign(value: Double) { + override fun DoubleTensor.minusAssign(value: Double) { for (i in this.buffer.unsafeToDoubleArray().indices) { this.buffer.unsafeToDoubleArray()[i] -= value } } - override fun RealTensor.minusAssign(other: RealTensor) { + override fun DoubleTensor.minusAssign(other: DoubleTensor) { TODO("Alya") } - override fun Double.times(other: RealTensor): RealTensor { + override fun Double.times(other: DoubleTensor): DoubleTensor { //todo should be change with broadcasting val resBuffer = DoubleArray(other.buffer.size) { i -> other.buffer.unsafeToDoubleArray()[i] * this } - return RealTensor(other.shape, resBuffer) + return DoubleTensor(other.shape, resBuffer) } //todo should be change with broadcasting - override fun RealTensor.times(value: Double): RealTensor = value * this + override fun DoubleTensor.times(value: Double): DoubleTensor = value * this - override fun RealTensor.times(other: RealTensor): RealTensor { + override fun DoubleTensor.times(other: DoubleTensor): DoubleTensor { //todo should be change with broadcasting val resBuffer = DoubleArray(this.buffer.size) { i -> this.buffer.unsafeToDoubleArray()[i] * other.buffer.unsafeToDoubleArray()[i] } - return RealTensor(this.shape, resBuffer) + return DoubleTensor(this.shape, resBuffer) } - override fun RealTensor.timesAssign(value: Double) { + override fun DoubleTensor.timesAssign(value: Double) { //todo should be change with broadcasting for (i in this.buffer.unsafeToDoubleArray().indices) { this.buffer.unsafeToDoubleArray()[i] *= value } } - override fun RealTensor.timesAssign(other: RealTensor) { + override fun DoubleTensor.timesAssign(other: DoubleTensor) { //todo should be change with broadcasting for (i in this.buffer.unsafeToDoubleArray().indices) { this.buffer.unsafeToDoubleArray()[i] *= other.buffer.unsafeToDoubleArray()[i] } } - override fun RealTensor.unaryMinus(): RealTensor { + override fun DoubleTensor.unaryMinus(): DoubleTensor { val resBuffer = DoubleArray(this.buffer.size) { i -> this.buffer.unsafeToDoubleArray()[i].unaryMinus() } - return RealTensor(this.shape, resBuffer) + return DoubleTensor(this.shape, resBuffer) } - override fun RealTensor.transpose(i: Int, j: Int): RealTensor { + override fun DoubleTensor.transpose(i: Int, j: Int): DoubleTensor { checkTranspose(this.dimension, i, j) val n = this.buffer.size val resBuffer = DoubleArray(n) @@ -148,7 +148,7 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra, dim: Int): RealTensor { + override fun cat(tensors: List, dim: Int): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.div(value: Double): RealTensor { + override fun DoubleTensor.div(value: Double): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.div(other: RealTensor): RealTensor { + override fun DoubleTensor.div(other: DoubleTensor): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.flatten(startDim: Int, endDim: Int): RealTensor { + override fun DoubleTensor.flatten(startDim: Int, endDim: Int): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.divAssign(value: Double) { + override fun DoubleTensor.divAssign(value: Double) { TODO("Not yet implemented") } - override fun RealTensor.divAssign(other: RealTensor) { + override fun DoubleTensor.divAssign(other: DoubleTensor) { TODO("Not yet implemented") } - override fun RealTensor.mean(dim: Int, keepDim: Boolean): RealTensor { + override fun DoubleTensor.mean(dim: Int, keepDim: Boolean): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.quantile(q: Double, dim: Int, keepDim: Boolean): RealTensor { + override fun DoubleTensor.quantile(q: Double, dim: Int, keepDim: Boolean): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.std(dim: Int, unbiased: Boolean, keepDim: Boolean): RealTensor { + override fun DoubleTensor.std(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): RealTensor { + override fun DoubleTensor.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.histc(bins: Int, min: Double, max: Double): RealTensor { + override fun DoubleTensor.histc(bins: Int, min: Double, max: Double): DoubleTensor { TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt deleted file mode 100644 index f610361fc..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt +++ /dev/null @@ -1,150 +0,0 @@ -package space.kscience.kmath.tensors - -public class RealAnalyticTensorAlgebra: - AnalyticTensorAlgebra, - RealTensorAlgebra() -{ - override fun RealTensor.exp(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.log(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.sqrt(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.square(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.cos(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.acos(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.cosh(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.acosh(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.sin(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.asin(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.sinh(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.asinh(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.tan(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.atan(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.tanh(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.atanh(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.ceil(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.floor(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.clamp(min: Double, max: Double): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.erf(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.erfinv(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.erfc(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.lerp(end: RealTensor, weight: RealTensor): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.lgamma(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.logit(eps: Double): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.igamma(other: RealTensor): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.igammac(other: RealTensor): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.mvlgamma(dimensions: Int): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.polygamma(order: Int): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.pow(exponent: Double): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.round(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.sigmoid(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.sinc(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.heaviside(values: RealTensor): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.trapz(xValues: RealTensor, dim: Int): RealTensor { - TODO("Not yet implemented") - } - -} - -public inline fun RealAnalyticTensorAlgebra(block: RealAnalyticTensorAlgebra.() -> R): R = - RealAnalyticTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt index b03fb7dd7..9f7e811db 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt @@ -32,13 +32,13 @@ internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { return totalShape } -internal inline fun broadcastTensors(vararg tensors: RealTensor): List { +internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List { val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) val n = totalShape.reduce { acc, i -> acc * i } - val res = ArrayList(0) + val res = ArrayList(0) for (tensor in tensors) { - val resTensor = RealTensor(totalShape, DoubleArray(n)) + val resTensor = DoubleTensor(totalShape, DoubleArray(n)) for (linearIndex in 0 until n) { val totalMultiIndex = resTensor.strides.index(linearIndex) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt index 473a3da8b..5d42e6d0f 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt @@ -11,13 +11,13 @@ class TestRealTensor { @Test fun valueTest() = RealTensorAlgebra { val value = 12.5 - val tensor = RealTensor(intArrayOf(1), doubleArrayOf(value)) + val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @Test fun stridesTest(){ - val tensor = RealTensor(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) + val tensor = DoubleTensor(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) assertEquals(tensor[intArrayOf(0,1)], 5.8) assertTrue(tensor.elements().map{ it.second }.toList().toDoubleArray() contentEquals tensor.buffer.toDoubleArray()) } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index 72bbf1787..3e27a1cc2 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -8,14 +8,14 @@ class TestRealTensorAlgebra { @Test fun doublePlus() = RealTensorAlgebra { - val tensor = RealTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0)) + val tensor = DoubleTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(11.0,12.0)) } @Test fun transpose1x1() = RealTensorAlgebra { - val tensor = RealTensor(intArrayOf(1), doubleArrayOf(0.0)) + val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(0.0)) val res = tensor.transpose(0, 0) assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(0.0)) @@ -24,7 +24,7 @@ class TestRealTensorAlgebra { @Test fun transpose3x2() = RealTensorAlgebra { - val tensor = RealTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor = DoubleTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) @@ -33,7 +33,7 @@ class TestRealTensorAlgebra { @Test fun transpose1x2x3() = RealTensorAlgebra { - val tensor = RealTensor(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor = DoubleTensor(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transpose(0, 1) val res02 = tensor.transpose(0, 2) val res12 = tensor.transpose(1, 2) @@ -60,9 +60,9 @@ class TestRealTensorAlgebra { @Test fun broadcastTensors() = RealTensorAlgebra { - val tensor1 = RealTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = RealTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) val res = broadcastTensors(tensor1, tensor2, tensor3) @@ -77,9 +77,9 @@ class TestRealTensorAlgebra { @Test fun minusTensor() = RealTensorAlgebra { - val tensor1 = RealTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = RealTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) assertTrue((tensor2 - tensor1).shape contentEquals intArrayOf(2, 3)) assertTrue((tensor2 - tensor1).buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) From b227a82a80d406fa3c4b4e50373a02363f161954 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 19:06:33 +0000 Subject: [PATCH 030/211] OrderedTensorAlgebra --- .../kmath/tensors/ComplexTensorAlgebra.kt | 6 +++ .../tensors/DoubleAnalyticTensorAlgebra.kt | 8 +-- .../tensors/DoubleLinearOpsTensorAlgebra.kt | 32 ++---------- .../tensors/DoubleOrderedTensorAlgebra.kt | 41 +++++++++++++++ .../kmath/tensors/DoubleTensorAlgebra.kt | 51 ++++++++----------- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 15 ------ .../kmath/tensors/OrderedTensorAlgebra.kt | 29 +++++++++++ .../kscience/kmath/tensors/TensorAlgebra.kt | 35 +++++-------- .../kscience/kmath/tensors/TestRealTensor.kt | 2 +- .../kmath/tensors/TestRealTensorAlgebra.kt | 14 ++--- 10 files changed, 125 insertions(+), 108 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt index 8399511a5..e56920916 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt @@ -8,6 +8,12 @@ public interface ComplexTensorAlgebra, - RealTensorAlgebra() + DoubleTensorAlgebra() { override fun DoubleTensor.exp(): DoubleTensor { TODO("Not yet implemented") @@ -146,5 +146,5 @@ public class RealAnalyticTensorAlgebra: } -public inline fun RealAnalyticTensorAlgebra(block: RealAnalyticTensorAlgebra.() -> R): R = - RealAnalyticTensorAlgebra().block() \ No newline at end of file +public inline fun DoubleAnalyticTensorAlgebra(block: DoubleAnalyticTensorAlgebra.() -> R): R = + DoubleAnalyticTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt index ddb3dfa12..1aaf8df9d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt @@ -2,27 +2,12 @@ package space.kscience.kmath.tensors public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, - RealTensorAlgebra() { - override fun eye(n: Int): DoubleTensor { - val shape = intArrayOf(n, n) - val buffer = DoubleArray(n * n) { 0.0 } - val res = DoubleTensor(shape, buffer) - for (i in 0 until n) { - res[intArrayOf(i, i)] = 1.0 - } - return res + DoubleTensorAlgebra() { + + override fun DoubleTensor.inv(): DoubleTensor { + TODO("Not yet implemented") } - - override fun DoubleTensor.dot(other: DoubleTensor): DoubleTensor { - TODO("Alya") - } - - override fun diagonalEmbedding(diagonalEntries: DoubleTensor, offset: Int, dim1: Int, dim2: Int): DoubleTensor { - TODO("Alya") - } - - override fun DoubleTensor.lu(): Pair { // todo checks val luTensor = this.copy() @@ -115,15 +100,6 @@ public class DoubleLinearOpsTensorAlgebra : return Triple(p, l, u) } - override fun DoubleTensor.det(): DoubleTensor { - - TODO("Not yet implemented") - } - - override fun DoubleTensor.inv(): DoubleTensor { - TODO("Not yet implemented") - } - override fun DoubleTensor.cholesky(): DoubleTensor { TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt new file mode 100644 index 000000000..e7ebf6c56 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt @@ -0,0 +1,41 @@ +package space.kscience.kmath.tensors + +public class DoubleOrderedTensorAlgebra: + OrderedTensorAlgebra, + DoubleTensorAlgebra() +{ + override fun DoubleTensor.max(dim: Int, keepDim: Boolean): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.cummax(dim: Int): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.min(dim: Int, keepDim: Boolean): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.cummin(dim: Int): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.median(dim: Int, keepDim: Boolean): DoubleTensor { + TODO("Not yet implemented") + } + + override fun maximum(lhs: DoubleTensor, rhs: DoubleTensor) { + TODO("Not yet implemented") + } + + override fun minimum(lhs: DoubleTensor, rhs: DoubleTensor) { + TODO("Not yet implemented") + } + + override fun DoubleTensor.sort(dim: Int, keepDim: Boolean, descending: Boolean): DoubleTensor { + TODO("Not yet implemented") + } +} + +public inline fun DoubleOrderedTensorAlgebra(block: DoubleOrderedTensorAlgebra.() -> R): R = + DoubleOrderedTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index dd15a257c..8b9701127 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.tensors -public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { +public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun DoubleTensor.value(): Double { check(this.shape contentEquals intArrayOf(1)) { @@ -27,6 +27,15 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra, dim: Int): DoubleTensor { @@ -276,7 +261,11 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra RealTensorAlgebra(block: RealTensorAlgebra.() -> R): R = - RealTensorAlgebra().block() \ No newline at end of file +public inline fun DoubleTensorAlgebra(block: DoubleTensorAlgebra.() -> R): R = + DoubleTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index db1135a33..7450c09c1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -4,21 +4,6 @@ package space.kscience.kmath.tensors public interface LinearOpsTensorAlgebra> : TensorPartialDivisionAlgebra { - //https://pytorch.org/docs/stable/generated/torch.eye.html - public fun eye(n: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.matmul.html - public infix fun TensorType.dot(other: TensorType): TensorType - - //https://pytorch.org/docs/stable/generated/torch.diag_embed.html - public fun diagonalEmbedding( - diagonalEntries: TensorType, - offset: Int = 0, dim1: Int = -2, dim2: Int = -1 - ): TensorType - - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det - public fun TensorType.det(): TensorType - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv public fun TensorType.inv(): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt new file mode 100644 index 000000000..3320c3a1e --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt @@ -0,0 +1,29 @@ +package space.kscience.kmath.tensors + +public interface OrderedTensorAlgebra> : + TensorAlgebra { + + //https://pytorch.org/docs/stable/generated/torch.max.html#torch.max + public fun TensorType.max(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cummax.html#torch.cummax + public fun TensorType.cummax(dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.min.html#torch.min + public fun TensorType.min(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cummin.html#torch.cummin + public fun TensorType.cummin(dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.median.html#torch.median + public fun TensorType.median(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.maximum.html#torch.maximum + public fun maximum(lhs: TensorType, rhs: TensorType) + + //https://pytorch.org/docs/stable/generated/torch.minimum.html#torch.minimum + public fun minimum(lhs: TensorType, rhs: TensorType) + + //https://pytorch.org/docs/stable/generated/torch.sort.html#torch.sort + public fun TensorType.sort(dim: Int, keepDim: Boolean, descending: Boolean): TensorType +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index a53054e21..6f368f332 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -17,6 +17,9 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.full_like.html#torch.full_like public fun TensorType.fullLike(value: T): TensorType + //https://pytorch.org/docs/stable/generated/torch.eye.html + public fun eye(n: Int): TensorType + public fun TensorType.copy(): TensorType public operator fun T.plus(other: TensorType): TensorType @@ -46,6 +49,9 @@ public interface TensorAlgebra> { public fun TensorType.view(shape: IntArray): TensorType public fun TensorType.viewAs(other: TensorType): TensorType + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det + public fun TensorType.det(): TensorType + //https://pytorch.org/docs/stable/generated/torch.abs.html public fun TensorType.abs(): TensorType @@ -61,29 +67,14 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.cumprod.html#torch.cumprod public fun TensorType.cumprod(dim: Int): TensorType - //https://pytorch.org/docs/stable/generated/torch.max.html#torch.max - public fun TensorType.max(dim: Int, keepDim: Boolean): TensorType + //https://pytorch.org/docs/stable/generated/torch.matmul.html + public infix fun TensorType.dot(other: TensorType): TensorType - //https://pytorch.org/docs/stable/generated/torch.cummax.html#torch.cummax - public fun TensorType.cummax(dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.min.html#torch.min - public fun TensorType.min(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.cummin.html#torch.cummin - public fun TensorType.cummin(dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.median.html#torch.median - public fun TensorType.median(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.maximum.html#torch.maximum - public fun maximum(lhs: TensorType, rhs: TensorType) - - //https://pytorch.org/docs/stable/generated/torch.minimum.html#torch.minimum - public fun minimum(lhs: TensorType, rhs: TensorType) - - //https://pytorch.org/docs/stable/generated/torch.sort.html#torch.sort - public fun TensorType.sort(dim: Int, keepDim: Boolean, descending: Boolean): TensorType + //https://pytorch.org/docs/stable/generated/torch.diag_embed.html + public fun diagonalEmbedding( + diagonalEntries: TensorType, + offset: Int = 0, dim1: Int = -2, dim2: Int = -1 + ): TensorType //https://pytorch.org/docs/stable/generated/torch.cat.html#torch.cat public fun cat(tensors: List, dim: Int): TensorType diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt index 5d42e6d0f..72179ecbc 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt @@ -9,7 +9,7 @@ import kotlin.test.assertTrue class TestRealTensor { @Test - fun valueTest() = RealTensorAlgebra { + fun valueTest() = DoubleTensorAlgebra { val value = 12.5 val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index 3e27a1cc2..9dddcf59e 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -7,14 +7,14 @@ import kotlin.test.assertTrue class TestRealTensorAlgebra { @Test - fun doublePlus() = RealTensorAlgebra { + fun doublePlus() = DoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(11.0,12.0)) } @Test - fun transpose1x1() = RealTensorAlgebra { + fun transpose1x1() = DoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(0.0)) val res = tensor.transpose(0, 0) @@ -23,7 +23,7 @@ class TestRealTensorAlgebra { } @Test - fun transpose3x2() = RealTensorAlgebra { + fun transpose3x2() = DoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) @@ -32,7 +32,7 @@ class TestRealTensorAlgebra { } @Test - fun transpose1x2x3() = RealTensorAlgebra { + fun transpose1x2x3() = DoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transpose(0, 1) val res02 = tensor.transpose(0, 2) @@ -48,7 +48,7 @@ class TestRealTensorAlgebra { } @Test - fun broadcastShapes() = RealTensorAlgebra { + fun broadcastShapes() = DoubleTensorAlgebra { assertTrue(broadcastShapes( intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) ) contentEquals intArrayOf(1, 2, 3)) @@ -59,7 +59,7 @@ class TestRealTensorAlgebra { } @Test - fun broadcastTensors() = RealTensorAlgebra { + fun broadcastTensors() = DoubleTensorAlgebra { val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -76,7 +76,7 @@ class TestRealTensorAlgebra { } @Test - fun minusTensor() = RealTensorAlgebra { + fun minusTensor() = DoubleTensorAlgebra { val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) From f8e0d4be17baac7e2f5930083b2bfeb7338f99e8 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 21:18:15 +0000 Subject: [PATCH 031/211] MutableStructure 2D & 1D --- .../space/kscience/kmath/nd/Structure1D.kt | 56 +++++++++++++++++++ .../space/kscience/kmath/nd/Structure2D.kt | 53 +++++++++++++++++- .../space/kscience/kmath/structures/Buffer.kt | 5 ++ .../kscience/kmath/tensors/BufferedTensor.kt | 1 - .../kmath/tensors/DoubleTensorAlgebra.kt | 4 ++ .../kscience/kmath/tensors/TensorAlgebra.kt | 2 + .../kscience/kmath/tensors/TensorStructure.kt | 1 - 7 files changed, 118 insertions(+), 4 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 1335a4933..2926b3d1b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -1,6 +1,8 @@ package space.kscience.kmath.nd import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.asMutableBuffer import space.kscience.kmath.structures.asSequence /** @@ -17,6 +19,16 @@ public interface Structure1D : NDStructure, Buffer { public override operator fun iterator(): Iterator = (0 until size).asSequence().map(::get).iterator() } +/** + * A mutable structure that is guaranteed to be one-dimensional + */ +public interface MutableStructure1D : Structure1D, MutableNDStructure, MutableBuffer { + public override operator fun set(index: IntArray, value: T) { + require(index.size == 1) { "Index dimension mismatch. Expected 1 but found ${index.size}" } + set(index[0], value) + } +} + /** * A 1D wrapper for nd-structure */ @@ -28,6 +40,25 @@ private inline class Structure1DWrapper(val structure: NDStructure) : Stru override fun elements(): Sequence> = structure.elements() } +/** + * A 1D wrapper for a mutable nd-structure + */ +private inline class MutableStructure1DWrapper(val structure: MutableNDStructure) : MutableStructure1D { + override val shape: IntArray get() = structure.shape + override val size: Int get() = structure.shape[0] + override fun elements(): Sequence> { + TODO("Not yet implemented") + } + + override fun get(index: Int): T = structure[index] + override fun set(index: Int, value: T) { + set(index, value) + } + + override fun copy(): MutableBuffer = + structure.elements().map { it.second }.toMutableList().asMutableBuffer() +} + /** * A structure wrapper for buffer @@ -42,6 +73,21 @@ private inline class Buffer1DWrapper(val buffer: Buffer) : Structure1D override operator fun get(index: Int): T = buffer[index] } +private inline class MutableBuffer1DWrapper(val buffer: MutableBuffer) : MutableStructure1D { + override val shape: IntArray get() = intArrayOf(buffer.size) + override val size: Int get() = buffer.size + + override fun elements(): Sequence> = + buffer.asSequence().mapIndexed { index, value -> intArrayOf(index) to value } + + override operator fun get(index: Int): T = buffer[index] + override fun set(index: Int, value: T) { + buffer[index] = value + } + + override fun copy(): MutableBuffer = buffer.copy() +} + /** * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch */ @@ -52,7 +98,17 @@ public fun NDStructure.as1D(): Structure1D = this as? Structure1D ? } } else error("Can't create 1d-structure from ${shape.size}d-structure") +public fun MutableNDStructure.as1D(): MutableStructure1D = + this as? MutableStructure1D ?: if (shape.size == 1) { + when (this) { + is MutableNDBuffer -> MutableBuffer1DWrapper(this.buffer) + else -> MutableStructure1DWrapper(this) + } + } else error("Can't create 1d-structure from ${shape.size}d-structure") + /** * Represent this buffer as 1D structure */ public fun Buffer.asND(): Structure1D = Buffer1DWrapper(this) + +public fun MutableBuffer.asND(): MutableStructure1D = MutableBuffer1DWrapper(this) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index e9f8234e5..2f2fd653e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -57,6 +57,20 @@ public interface Structure2D : NDStructure { public companion object } +/** + * Represents mutable [Structure2D]. + */ +public interface MutableStructure2D : Structure2D, MutableNDStructure { + /** + * Inserts an item at the specified indices. + * + * @param i the first index. + * @param j the second index. + * @param value the value. + */ + public operator fun set(i: Int, j: Int, value: T) +} + /** * A 2D wrapper for nd-structure */ @@ -79,11 +93,46 @@ private class Structure2DWrapper(val structure: NDStructure) : Structure2D } /** - * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch + * A 2D wrapper for a mutable nd-structure + */ +private class MutableStructure2DWrapper(val structure: MutableNDStructure): MutableStructure2D +{ + override val shape: IntArray get() = structure.shape + + override val rowNum: Int get() = shape[0] + override val colNum: Int get() = shape[1] + + override operator fun get(i: Int, j: Int): T = structure[i, j] + + override fun set(index: IntArray, value: T) { + structure[index] = value + } + + override operator fun set(i: Int, j: Int, value: T){ + structure[intArrayOf(i, j)] = value + } + + override fun elements(): Sequence> = structure.elements() + + override fun equals(other: Any?): Boolean = false + + override fun hashCode(): Int = 0 +} + +/** + * Represent a [NDStructure] as [Structure2D]. Throw error in case of dimension mismatch */ public fun NDStructure.as2D(): Structure2D = this as? Structure2D ?: when (shape.size) { 2 -> Structure2DWrapper(this) else -> error("Can't create 2d-structure from ${shape.size}d-structure") } -internal fun Structure2D.unwrap(): NDStructure = if (this is Structure2DWrapper) structure else this \ No newline at end of file +internal fun Structure2D.unwrap(): NDStructure = if (this is Structure2DWrapper) structure else this + +public fun MutableNDStructure.as2D(): MutableStructure2D = this as? MutableStructure2D ?: when (shape.size) { + 2 -> MutableStructure2DWrapper(this) + else -> error("Can't create 2d-structure from ${shape.size}d-structure") +} + +internal fun MutableStructure2D.unwrap(): MutableNDStructure = + if (this is MutableStructure2DWrapper) structure else this diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 2bde18fce..c62fa30ba 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -236,6 +236,11 @@ public inline class MutableListBuffer(public val list: MutableList) : Muta override fun copy(): MutableBuffer = MutableListBuffer(ArrayList(list)) } +/** + * Returns an [MutableListBuffer] that wraps the original list. + */ +public fun MutableList.asMutableBuffer(): MutableListBuffer = MutableListBuffer(this) + /** * [MutableBuffer] implementation over [Array]. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index d5adf380c..68fc0412e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -25,7 +25,6 @@ public open class BufferedTensor( this[intArrayOf(i, j)] = value } - } //todo make generator mb nextMatrixIndex? diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 8b9701127..76a3c4c9c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -10,6 +10,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra> { public operator fun TensorType.timesAssign(other: TensorType): Unit public operator fun TensorType.unaryMinus(): TensorType + //https://pytorch.org/cppdocs/notes/tensor_indexing.html + public fun TensorType.get(i: Int): TensorType //https://pytorch.org/docs/stable/generated/torch.transpose.html public fun TensorType.transpose(i: Int, j: Int): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt index 5463877ce..f5ea39d1b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt @@ -3,4 +3,3 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDStructure public typealias TensorStructure = MutableNDStructure - From 7cb5cd8f71721e5eb5e77e0849311a3fd3c2374f Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 22:11:15 +0000 Subject: [PATCH 032/211] BufferedTensor revisited --- .../kscience/kmath/tensors/BufferedTensor.kt | 54 ++++++++------- .../tensors/DoubleLinearOpsTensorAlgebra.kt | 10 ++- .../kmath/tensors/DoubleTensorAlgebra.kt | 69 ++++++++++--------- .../space/kscience/kmath/tensors/utils.kt | 3 +- ...{TestRealTensor.kt => TestDoubleTensor.kt} | 2 +- ...rAlgebra.kt => TestDoubleTensorAlgebra.kt} | 2 +- 6 files changed, 78 insertions(+), 62 deletions(-) rename kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/{TestRealTensor.kt => TestDoubleTensor.kt} (96%) rename kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/{TestRealTensorAlgebra.kt => TestDoubleTensorAlgebra.kt} (99%) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index 68fc0412e..264692d0c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -1,32 +1,34 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.* public open class BufferedTensor( override val shape: IntArray, - buffer: MutableBuffer -) : - TensorStructure, - MutableNDBuffer( - TensorStrides(shape), - buffer - ) { + public val buffer: MutableBuffer, + internal val bufferStart: Int +) : TensorStructure +{ + public val strides: TensorStrides + get() = TensorStrides(shape) + override fun get(index: IntArray): T = buffer[bufferStart + strides.offset(index)] - public operator fun get(i: Int, j: Int): T { - check(this.dimension == 2) { "Not matrix" } - return this[intArrayOf(i, j)] + override fun set(index: IntArray, value: T) { + buffer[bufferStart + strides.offset(index)] = value } - public operator fun set(i: Int, j: Int, value: T): Unit { - check(this.dimension == 2) { "Not matrix" } - this[intArrayOf(i, j)] = value + override fun elements(): Sequence> = strides.indices().map { + it to this[it] } + override fun equals(other: Any?): Boolean = false + + override fun hashCode(): Int = 0 + } +/* //todo make generator mb nextMatrixIndex? public class InnerMatrix(private val tensor: BufferedTensor){ private var offset: Int = 0 @@ -75,25 +77,29 @@ public class InnerVector(private val tensor: BufferedTensor){ offset += step } } - - //todo default buffer = arrayOf(0)??? + */ + public class IntTensor( shape: IntArray, - buffer: IntArray -) : BufferedTensor(shape, IntBuffer(buffer)) + buffer: IntArray, + offset: Int = 0 +) : BufferedTensor(shape, IntBuffer(buffer), offset) public class LongTensor( shape: IntArray, - buffer: LongArray -) : BufferedTensor(shape, LongBuffer(buffer)) + buffer: LongArray, + offset: Int = 0 +) : BufferedTensor(shape, LongBuffer(buffer), offset) public class FloatTensor( shape: IntArray, - buffer: FloatArray -) : BufferedTensor(shape, FloatBuffer(buffer)) + buffer: FloatArray, + offset: Int = 0 +) : BufferedTensor(shape, FloatBuffer(buffer), offset) public class DoubleTensor( shape: IntArray, - buffer: DoubleArray -) : BufferedTensor(shape, RealBuffer(buffer)) \ No newline at end of file + buffer: DoubleArray, + offset: Int = 0 +) : BufferedTensor(shape, RealBuffer(buffer), offset) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt index 1aaf8df9d..eceb28459 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt @@ -9,6 +9,7 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.lu(): Pair { + /* // todo checks val luTensor = this.copy() val lu = InnerMatrix(luTensor) @@ -69,11 +70,13 @@ public class DoubleLinearOpsTensorAlgebra : pivot.makeStep() } - return Pair(luTensor, pivotsTensor) + return Pair(luTensor, pivotsTensor)*/ + + TODO("Andrei, first we need to view and get(Int)") } override fun luPivot(lu: DoubleTensor, pivots: IntTensor): Triple { - + /* // todo checks val n = lu.shape[0] val p = lu.zeroesLike() @@ -97,7 +100,8 @@ public class DoubleLinearOpsTensorAlgebra : } } - return Triple(p, l, u) + return Triple(p, l, u)*/ + TODO("Andrei, first we need implement get(Int)") } override fun DoubleTensor.cholesky(): DoubleTensor { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 76a3c4c9c..391c2895f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -7,11 +7,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.unsafeToDoubleArray()[i] + this + val resBuffer = DoubleArray(other.strides.linearSize) { i -> + other.buffer.unsafeToDoubleArray()[other.bufferStart + i] + this } return DoubleTensor(other.shape, resBuffer) } @@ -60,35 +60,36 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> newThis.buffer.unsafeToDoubleArray()[i] + newOther.buffer.unsafeToDoubleArray()[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun DoubleTensor.plusAssign(value: Double) { - for (i in this.buffer.unsafeToDoubleArray().indices) { - this.buffer.unsafeToDoubleArray()[i] += value + for (i in 0 until this.strides.linearSize) { + this.buffer.unsafeToDoubleArray()[this.bufferStart + i] += value } } override fun DoubleTensor.plusAssign(other: DoubleTensor) { //todo should be change with broadcasting - for (i in this.buffer.unsafeToDoubleArray().indices) { - this.buffer.unsafeToDoubleArray()[i] += other.buffer.unsafeToDoubleArray()[i] + for (i in 0 until this.strides.linearSize) { + this.buffer.unsafeToDoubleArray()[this.bufferStart + i] += + other.buffer.unsafeToDoubleArray()[this.bufferStart + i] } } override fun Double.minus(other: DoubleTensor): DoubleTensor { - val resBuffer = DoubleArray(other.buffer.size) { i -> - this - other.buffer.unsafeToDoubleArray()[i] + val resBuffer = DoubleArray(other.strides.linearSize) { i -> + this - other.buffer.unsafeToDoubleArray()[other.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } override fun DoubleTensor.minus(value: Double): DoubleTensor { - val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.unsafeToDoubleArray()[i] - value + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.unsafeToDoubleArray()[this.bufferStart + i] - value } return DoubleTensor(this.shape, resBuffer) } @@ -97,15 +98,15 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> newThis.buffer.unsafeToDoubleArray()[i] - newOther.buffer.unsafeToDoubleArray()[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun DoubleTensor.minusAssign(value: Double) { - for (i in this.buffer.unsafeToDoubleArray().indices) { - this.buffer.unsafeToDoubleArray()[i] -= value + for (i in 0 until this.strides.linearSize) { + this.buffer.unsafeToDoubleArray()[this.bufferStart + i] -= value } } @@ -115,8 +116,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.unsafeToDoubleArray()[i] * this + val resBuffer = DoubleArray(other.strides.linearSize) { i -> + other.buffer.unsafeToDoubleArray()[other.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) } @@ -126,36 +127,38 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - this.buffer.unsafeToDoubleArray()[i] * other.buffer.unsafeToDoubleArray()[i] + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.unsafeToDoubleArray()[other.bufferStart + i] * + other.buffer.unsafeToDoubleArray()[other.bufferStart + i] } return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.timesAssign(value: Double) { //todo should be change with broadcasting - for (i in this.buffer.unsafeToDoubleArray().indices) { - this.buffer.unsafeToDoubleArray()[i] *= value + for (i in 0 until this.strides.linearSize) { + this.buffer.unsafeToDoubleArray()[this.bufferStart + i] *= value } } override fun DoubleTensor.timesAssign(other: DoubleTensor) { //todo should be change with broadcasting - for (i in this.buffer.unsafeToDoubleArray().indices) { - this.buffer.unsafeToDoubleArray()[i] *= other.buffer.unsafeToDoubleArray()[i] + for (i in 0 until this.strides.linearSize) { + this.buffer.unsafeToDoubleArray()[this.bufferStart + i] *= + other.buffer.unsafeToDoubleArray()[this.bufferStart + i] } } override fun DoubleTensor.unaryMinus(): DoubleTensor { - val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.unsafeToDoubleArray()[i].unaryMinus() + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.unsafeToDoubleArray()[this.bufferStart + i].unaryMinus() } return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.transpose(i: Int, j: Int): DoubleTensor { checkTranspose(this.dimension, i, j) - val n = this.buffer.size + val n = this.strides.linearSize val resBuffer = DoubleArray(n) val resShape = this.shape.copyOf() @@ -169,14 +172,16 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Date: Mon, 15 Mar 2021 22:39:29 +0000 Subject: [PATCH 033/211] get dim 0 operator for tensors --- .../tensors/DoubleLinearOpsTensorAlgebra.kt | 2 +- .../kmath/tensors/DoubleTensorAlgebra.kt | 49 ++++++++++--------- .../kscience/kmath/tensors/TensorAlgebra.kt | 2 +- .../space/kscience/kmath/tensors/utils.kt | 12 ++--- .../kmath/tensors/TestDoubleTensor.kt | 6 +++ .../kmath/tensors/TestDoubleTensorAlgebra.kt | 24 ++++----- 6 files changed, 52 insertions(+), 43 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt index eceb28459..d6b202556 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt @@ -72,7 +72,7 @@ public class DoubleLinearOpsTensorAlgebra : return Pair(luTensor, pivotsTensor)*/ - TODO("Andrei, first we need to view and get(Int)") + TODO("Andrei, use view, get, as2D, as1D") } override fun luPivot(lu: DoubleTensor, pivots: IntTensor): Triple { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 391c2895f..3b65e89da 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -7,11 +7,14 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.unsafeToDoubleArray()[other.bufferStart + i] + this + other.buffer.array()[other.bufferStart + i] + this } return DoubleTensor(other.shape, resBuffer) } @@ -61,35 +64,35 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.unsafeToDoubleArray()[i] + newOther.buffer.unsafeToDoubleArray()[i] + newThis.buffer.array()[i] + newOther.buffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun DoubleTensor.plusAssign(value: Double) { for (i in 0 until this.strides.linearSize) { - this.buffer.unsafeToDoubleArray()[this.bufferStart + i] += value + this.buffer.array()[this.bufferStart + i] += value } } override fun DoubleTensor.plusAssign(other: DoubleTensor) { //todo should be change with broadcasting for (i in 0 until this.strides.linearSize) { - this.buffer.unsafeToDoubleArray()[this.bufferStart + i] += - other.buffer.unsafeToDoubleArray()[this.bufferStart + i] + this.buffer.array()[this.bufferStart + i] += + other.buffer.array()[this.bufferStart + i] } } override fun Double.minus(other: DoubleTensor): DoubleTensor { val resBuffer = DoubleArray(other.strides.linearSize) { i -> - this - other.buffer.unsafeToDoubleArray()[other.bufferStart + i] + this - other.buffer.array()[other.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } override fun DoubleTensor.minus(value: Double): DoubleTensor { val resBuffer = DoubleArray(this.strides.linearSize) { i -> - this.buffer.unsafeToDoubleArray()[this.bufferStart + i] - value + this.buffer.array()[this.bufferStart + i] - value } return DoubleTensor(this.shape, resBuffer) } @@ -99,14 +102,14 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.unsafeToDoubleArray()[i] - newOther.buffer.unsafeToDoubleArray()[i] + newThis.buffer.array()[i] - newOther.buffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun DoubleTensor.minusAssign(value: Double) { for (i in 0 until this.strides.linearSize) { - this.buffer.unsafeToDoubleArray()[this.bufferStart + i] -= value + this.buffer.array()[this.bufferStart + i] -= value } } @@ -117,7 +120,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.unsafeToDoubleArray()[other.bufferStart + i] * this + other.buffer.array()[other.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) } @@ -128,8 +131,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - this.buffer.unsafeToDoubleArray()[other.bufferStart + i] * - other.buffer.unsafeToDoubleArray()[other.bufferStart + i] + this.buffer.array()[other.bufferStart + i] * + other.buffer.array()[other.bufferStart + i] } return DoubleTensor(this.shape, resBuffer) } @@ -137,21 +140,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - this.buffer.unsafeToDoubleArray()[this.bufferStart + i].unaryMinus() + this.buffer.array()[this.bufferStart + i].unaryMinus() } return DoubleTensor(this.shape, resBuffer) } @@ -172,8 +175,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra> { public operator fun TensorType.unaryMinus(): TensorType //https://pytorch.org/cppdocs/notes/tensor_indexing.html - public fun TensorType.get(i: Int): TensorType + public operator fun TensorType.get(i: Int): TensorType //https://pytorch.org/docs/stable/generated/torch.transpose.html public fun TensorType.transpose(i: Int, j: Int): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt index 74a774f45..3e32e2b72 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt @@ -55,8 +55,8 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List, /** * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. */ -internal fun Buffer.unsafeToIntArray(): IntArray = when(this) { +internal fun Buffer.array(): IntArray = when(this) { is IntBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to IntArray") } @@ -107,7 +107,7 @@ internal fun Buffer.unsafeToIntArray(): IntArray = when(this) { /** * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. */ -internal fun Buffer.unsafeToLongArray(): LongArray = when(this) { +internal fun Buffer.array(): LongArray = when(this) { is LongBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to LongArray") } @@ -115,7 +115,7 @@ internal fun Buffer.unsafeToLongArray(): LongArray = when(this) { /** * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. */ -internal fun Buffer.unsafeToFloatArray(): FloatArray = when(this) { +internal fun Buffer.array(): FloatArray = when(this) { is FloatBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to FloatArray") } @@ -123,7 +123,7 @@ internal fun Buffer.unsafeToFloatArray(): FloatArray = when(this) { /** * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. */ -internal fun Buffer.unsafeToDoubleArray(): DoubleArray = when(this) { +internal fun Buffer.array(): DoubleArray = when(this) { is RealBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt index 31c6ccbbf..b1c8cd6dd 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt @@ -21,4 +21,10 @@ class TestDoubleTensor { assertEquals(tensor[intArrayOf(0,1)], 5.8) assertTrue(tensor.elements().map{ it.second }.toList().toDoubleArray() contentEquals tensor.buffer.toDoubleArray()) } + + @Test + fun getTest() = DoubleTensorAlgebra { + val tensor = DoubleTensor(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) + assertTrue(tensor[0].elements().map{ it.second }.toList().toDoubleArray() contentEquals doubleArrayOf(3.5,5.8)) + } } \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt index 91181484c..226454bf4 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt @@ -10,7 +10,7 @@ class TestDoubleTensorAlgebra { fun doublePlus() = DoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor - assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(11.0,12.0)) + assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0,12.0)) } @Test @@ -18,7 +18,7 @@ class TestDoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(0.0)) val res = tensor.transpose(0, 0) - assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(0.0)) + assertTrue(res.buffer.array() contentEquals doubleArrayOf(0.0)) assertTrue(res.shape contentEquals intArrayOf(1)) } @@ -27,7 +27,7 @@ class TestDoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) - assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) + assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) assertTrue(res.shape contentEquals intArrayOf(2, 3)) } @@ -42,9 +42,9 @@ class TestDoubleTensorAlgebra { assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2)) - assertTrue(res01.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res02.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) - assertTrue(res12.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res01.buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res02.buffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res12.buffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) } @Test @@ -70,9 +70,9 @@ class TestDoubleTensorAlgebra { assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[0].buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res[1].buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) - assertTrue(res[2].buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) + assertTrue(res[0].buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + assertTrue(res[2].buffer.array() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) } @Test @@ -82,14 +82,14 @@ class TestDoubleTensorAlgebra { val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) assertTrue((tensor2 - tensor1).shape contentEquals intArrayOf(2, 3)) - assertTrue((tensor2 - tensor1).buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) + assertTrue((tensor2 - tensor1).buffer.array() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) assertTrue((tensor3 - tensor1).shape contentEquals intArrayOf(1, 2, 3)) - assertTrue((tensor3 - tensor1).buffer.unsafeToDoubleArray() + assertTrue((tensor3 - tensor1).buffer.array() contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0)) assertTrue((tensor3 - tensor2).shape contentEquals intArrayOf(1, 1, 3)) - assertTrue((tensor3 - tensor2).buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) + assertTrue((tensor3 - tensor2).buffer.array() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) } } \ No newline at end of file From f4454a6cf6b8d54b1ecd818e2c39e6287b382189 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 22:45:55 +0000 Subject: [PATCH 034/211] Matrices from tensors test --- .../kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt index b1c8cd6dd..3050f064a 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray import kotlin.test.Test import kotlin.test.assertEquals @@ -24,7 +25,8 @@ class TestDoubleTensor { @Test fun getTest() = DoubleTensorAlgebra { - val tensor = DoubleTensor(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) - assertTrue(tensor[0].elements().map{ it.second }.toList().toDoubleArray() contentEquals doubleArrayOf(3.5,5.8)) + val tensor = DoubleTensor(intArrayOf(1,2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) + val matrix = tensor[0].as2D() + assertEquals(matrix[0,1], 5.8) } } \ No newline at end of file From 0553a28ee89e0d55f498c578882fece47bc620fe Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 16 Mar 2021 07:47:02 +0000 Subject: [PATCH 035/211] ReduceOpsTensorAlgebra --- .../kmath/tensors/AnalyticTensorAlgebra.kt | 15 +++++++++++- .../tensors/DoubleAnalyticTensorAlgebra.kt | 18 ++++++++++++++- .../tensors/DoubleOrderedTensorAlgebra.kt | 2 +- .../tensors/DoubleReduceOpsTensorAlgebra.kt | 16 +++++++++++++ .../kmath/tensors/DoubleTensorAlgebra.kt | 23 ------------------- .../kmath/tensors/ReduceOpsTensorAlgebra.kt | 7 ++++++ .../kscience/kmath/tensors/TensorAlgebra.kt | 1 - .../tensors/TensorPartialDivisionAlgebra.kt | 14 ----------- .../kmath/tensors/TestDoubleTensor.kt | 12 +++++++++- 9 files changed, 66 insertions(+), 42 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ReduceOpsTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt index 17a25b6b3..41772da44 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt @@ -2,7 +2,17 @@ package space.kscience.kmath.tensors public interface AnalyticTensorAlgebra> : - TensorPartialDivisionAlgebra { + TensorPartialDivisionAlgebra, + OrderedTensorAlgebra{ + + //https://pytorch.org/docs/stable/generated/torch.quantile.html#torch.quantile + public fun TensorType.quantile(q: T, dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.std.html#torch.std + public fun TensorType.std(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var + public fun TensorType.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType //https://pytorch.org/docs/stable/generated/torch.exp.html public fun TensorType.exp(): TensorType @@ -109,4 +119,7 @@ public interface AnalyticTensorAlgebra> : //https://pytorch.org/docs/stable/generated/torch.trapz.html#torch.trapz public fun TensorType.trapz(xValues: TensorType, dim: Int): TensorType + //https://pytorch.org/docs/stable/generated/torch.histc.html#torch.histc + public fun TensorType.histc(bins: Int, min: T, max: T): TensorType + } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt index 00e7a7fbd..cccc02789 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.tensors public class DoubleAnalyticTensorAlgebra: AnalyticTensorAlgebra, - DoubleTensorAlgebra() + DoubleOrderedTensorAlgebra() { override fun DoubleTensor.exp(): DoubleTensor { TODO("Not yet implemented") @@ -144,6 +144,22 @@ public class DoubleAnalyticTensorAlgebra: TODO("Not yet implemented") } + override fun DoubleTensor.quantile(q: Double, dim: Int, keepDim: Boolean): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.std(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.histc(bins: Int, min: Double, max: Double): DoubleTensor { + TODO("Not yet implemented") + } + } public inline fun DoubleAnalyticTensorAlgebra(block: DoubleAnalyticTensorAlgebra.() -> R): R = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt index e7ebf6c56..bd6bcfe8f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.tensors -public class DoubleOrderedTensorAlgebra: +public open class DoubleOrderedTensorAlgebra: OrderedTensorAlgebra, DoubleTensorAlgebra() { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt new file mode 100644 index 000000000..00d9b3ff8 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt @@ -0,0 +1,16 @@ +package space.kscience.kmath.tensors + +public class DoubleReduceOpsTensorAlgebra: + DoubleTensorAlgebra(), + ReduceOpsTensorAlgebra { + + override fun DoubleTensor.value(): Double { + check(this.shape contentEquals intArrayOf(1)) { + "Inconsistent value for tensor of shape ${shape.toList()}" + } + return this.buffer.array()[this.bufferStart] + } +} + +public inline fun DoubleReduceOpsTensorAlgebra(block: DoubleReduceOpsTensorAlgebra.() -> R): R = + DoubleReduceOpsTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 3b65e89da..c383387ef 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -3,13 +3,6 @@ package space.kscience.kmath.tensors public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { - override fun DoubleTensor.value(): Double { - check(this.shape contentEquals intArrayOf(1)) { - "Inconsistent value for tensor of shape ${shape.toList()}" - } - return this.buffer.array()[this.bufferStart] - } - override operator fun DoubleTensor.get(i: Int): DoubleTensor { val lastShape = this.shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) @@ -257,22 +250,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra> : + TensorAlgebra { + public fun TensorType.value(): T + +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index e56abfaaa..60f0b3379 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -3,7 +3,6 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { - public fun TensorType.value(): T public fun zeros(shape: IntArray): TensorType public fun TensorType.zeroesLike(): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt index 2d448fa8c..ca3876e2c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -3,7 +3,6 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Division_Algebra public interface TensorPartialDivisionAlgebra> : TensorAlgebra { - public operator fun TensorType.div(value: T): TensorType public operator fun TensorType.div(other: TensorType): TensorType public operator fun TensorType.divAssign(value: T) @@ -11,17 +10,4 @@ public interface TensorPartialDivisionAlgebra //https://pytorch.org/docs/stable/generated/torch.mean.html#torch.mean public fun TensorType.mean(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.quantile.html#torch.quantile - public fun TensorType.quantile(q: T, dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.std.html#torch.std - public fun TensorType.std(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var - public fun TensorType.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.histc.html#torch.histc - public fun TensorType.histc(bins: Int, min: T, max: T): TensorType - } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt index 3050f064a..006b0273a 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray import kotlin.test.Test @@ -10,7 +11,7 @@ import kotlin.test.assertTrue class TestDoubleTensor { @Test - fun valueTest() = DoubleTensorAlgebra { + fun valueTest() = DoubleReduceOpsTensorAlgebra { val value = 12.5 val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) @@ -28,5 +29,14 @@ class TestDoubleTensor { val tensor = DoubleTensor(intArrayOf(1,2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) val matrix = tensor[0].as2D() assertEquals(matrix[0,1], 5.8) + + val vector = tensor[0][1].as1D() + assertEquals(vector[0], 58.4) + + matrix[0,1] = 77.89 + assertEquals(tensor[intArrayOf(0,0,1)], 77.89) + + //vector[0] = 109.56 + //println(tensor[intArrayOf(0,1,0)]) } } \ No newline at end of file From 99ee5aa54a043427d8ade94c82107cdc18e48819 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Tue, 16 Mar 2021 14:57:19 +0300 Subject: [PATCH 036/211] add broadcast to functions --- .../kmath/tensors/DoubleTensorAlgebra.kt | 30 ++++++++------- .../space/kscience/kmath/tensors/utils.kt | 37 +++++++++++++++++++ .../kmath/tensors/TestDoubleTensorAlgebra.kt | 10 +++++ 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index c383387ef..794a06102 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -69,10 +69,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra other.buffer.array()[other.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) } - //todo should be change with broadcasting override fun DoubleTensor.times(value: Double): DoubleTensor = value * this override fun DoubleTensor.times(other: DoubleTensor): DoubleTensor { - //todo should be change with broadcasting - val resBuffer = DoubleArray(this.strides.linearSize) { i -> - this.buffer.array()[other.bufferStart + i] * - other.buffer.array()[other.bufferStart + i] + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + newThis.buffer.array()[newOther.bufferStart + i] * + newOther.buffer.array()[newOther.bufferStart + i] } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(newThis.shape, resBuffer) } override fun DoubleTensor.timesAssign(value: Double) { - //todo should be change with broadcasting for (i in 0 until this.strides.linearSize) { this.buffer.array()[this.bufferStart + i] *= value } } override fun DoubleTensor.timesAssign(other: DoubleTensor) { - //todo should be change with broadcasting + val newOther = broadcastTo(other, this.shape) for (i in 0 until this.strides.linearSize) { this.buffer.array()[this.bufferStart + i] *= - other.buffer.array()[this.bufferStart + i] + newOther.buffer.array()[this.bufferStart + i] } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt index 3e32e2b72..e7e043463 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt @@ -32,6 +32,43 @@ internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { return totalShape } +internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor { + if (tensor.shape.size > newShape.size) { + throw RuntimeException("Tensor is not compatible with the new shape") + } + + val n = newShape.reduce { acc, i -> acc * i } + val resTensor = DoubleTensor(newShape, DoubleArray(n)) + + for (i in tensor.shape.indices) { + val curDim = tensor.shape[i] + val offset = newShape.size - tensor.shape.size + if (curDim != 1 && newShape[i + offset] != curDim) { + throw RuntimeException("Tensor is not compatible with the new shape and cannot be broadcast") + } + } + + for (linearIndex in 0 until n) { + val totalMultiIndex = resTensor.strides.index(linearIndex) + val curMultiIndex = tensor.shape.copyOf() + + val offset = totalMultiIndex.size - curMultiIndex.size + + for (i in curMultiIndex.indices) { + if (curMultiIndex[i] != 1) { + curMultiIndex[i] = totalMultiIndex[i + offset] + } else { + curMultiIndex[i] = 0 + } + } + + val curLinearIndex = tensor.strides.offset(curMultiIndex) + resTensor.buffer.array()[linearIndex] = + tensor.buffer.array()[tensor.bufferStart + curLinearIndex] + } + return resTensor +} + internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List { val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) val n = totalShape.reduce { acc, i -> acc * i } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt index 226454bf4..a060a970f 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt @@ -58,6 +58,16 @@ class TestDoubleTensorAlgebra { ) contentEquals intArrayOf(5, 6, 7)) } + @Test + fun broadcastTo() = DoubleTensorAlgebra { + val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + + val res = broadcastTo(tensor2, tensor1.shape) + assertTrue(res.shape contentEquals intArrayOf(2, 3)) + assertTrue(res.buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + } + @Test fun broadcastTensors() = DoubleTensorAlgebra { val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) From 70bebbe8488840a38e84855ca3d3eea1ddb4eebb Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 16 Mar 2021 12:12:28 +0000 Subject: [PATCH 037/211] 1D mutable structure setter fixed --- .../kotlin/space/kscience/kmath/nd/Structure1D.kt | 2 +- .../space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt | 6 ------ .../kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt | 8 -------- .../space/kscience/kmath/tensors/DoubleTensorAlgebra.kt | 8 ++++++++ .../kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt | 3 +++ .../kmath/tensors/TensorPartialDivisionAlgebra.kt | 3 +++ .../space/kscience/kmath/tensors/TestDoubleTensor.kt | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 2926b3d1b..fd965a668 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -52,7 +52,7 @@ private inline class MutableStructure1DWrapper(val structure: MutableNDStruct override fun get(index: Int): T = structure[index] override fun set(index: Int, value: T) { - set(index, value) + structure[intArrayOf(index)] = value } override fun copy(): MutableBuffer = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt index 41772da44..c3a558298 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt @@ -11,9 +11,6 @@ public interface AnalyticTensorAlgebra> : //https://pytorch.org/docs/stable/generated/torch.std.html#torch.std public fun TensorType.std(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType - //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var - public fun TensorType.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType - //https://pytorch.org/docs/stable/generated/torch.exp.html public fun TensorType.exp(): TensorType @@ -23,9 +20,6 @@ public interface AnalyticTensorAlgebra> : //https://pytorch.org/docs/stable/generated/torch.sqrt.html public fun TensorType.sqrt(): TensorType - //https://pytorch.org/docs/stable/generated/torch.square.html - public fun TensorType.square(): TensorType - //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos public fun TensorType.cos(): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt index cccc02789..5349a9923 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt @@ -16,10 +16,6 @@ public class DoubleAnalyticTensorAlgebra: TODO("Not yet implemented") } - override fun DoubleTensor.square(): DoubleTensor { - TODO("Not yet implemented") - } - override fun DoubleTensor.cos(): DoubleTensor { TODO("Not yet implemented") } @@ -152,10 +148,6 @@ public class DoubleAnalyticTensorAlgebra: TODO("Not yet implemented") } - override fun DoubleTensor.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - override fun DoubleTensor.histc(bins: Int, min: Double, max: Double): DoubleTensor { TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index c383387ef..bafbd9a96 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -254,6 +254,14 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra DoubleTensorAlgebra(block: DoubleTensorAlgebra.() -> R): R = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 60f0b3379..0af757d1a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -40,6 +40,9 @@ public interface TensorAlgebra> { public operator fun TensorType.timesAssign(other: TensorType): Unit public operator fun TensorType.unaryMinus(): TensorType + //https://pytorch.org/docs/stable/generated/torch.square.html + public fun TensorType.square(): TensorType + //https://pytorch.org/cppdocs/notes/tensor_indexing.html public operator fun TensorType.get(i: Int): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt index ca3876e2c..9f70f9621 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -10,4 +10,7 @@ public interface TensorPartialDivisionAlgebra //https://pytorch.org/docs/stable/generated/torch.mean.html#torch.mean public fun TensorType.mean(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var + public fun TensorType.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt index 006b0273a..6b20027c7 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt @@ -36,7 +36,7 @@ class TestDoubleTensor { matrix[0,1] = 77.89 assertEquals(tensor[intArrayOf(0,0,1)], 77.89) - //vector[0] = 109.56 - //println(tensor[intArrayOf(0,1,0)]) + vector[0] = 109.56 + assertEquals(tensor[intArrayOf(0,1,0)], 109.56) } } \ No newline at end of file From bd3425e7a545622c117740bba178ec1b1b531eab Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 16 Mar 2021 14:43:20 +0000 Subject: [PATCH 038/211] IndexTensor type added to LinearOps --- .../kotlin/space/kscience/kmath/tensors/BufferedTensor.kt | 3 +++ .../kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt | 2 +- .../space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index 264692d0c..c9a401ad5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -12,6 +12,9 @@ public open class BufferedTensor( public val strides: TensorStrides get() = TensorStrides(shape) + public val numel: Int + get() = strides.linearSize + override fun get(index: IntArray): T = buffer[bufferStart + strides.offset(index)] override fun set(index: IntArray, value: T) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt index d6b202556..689eda9e0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.tensors public class DoubleLinearOpsTensorAlgebra : - LinearOpsTensorAlgebra, + LinearOpsTensorAlgebra, DoubleTensorAlgebra() { override fun DoubleTensor.inv(): DoubleTensor { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index 7450c09c1..2e1c4a92c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.tensors -public interface LinearOpsTensorAlgebra> : +public interface LinearOpsTensorAlgebra, IndexTensorType: TensorStructure> : TensorPartialDivisionAlgebra { //https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv @@ -14,7 +14,7 @@ public interface LinearOpsTensorAlgebra> : public fun TensorType.qr(): TensorType //https://pytorch.org/docs/stable/generated/torch.lu.html - public fun TensorType.lu(): Pair + public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html public fun luPivot(lu: TensorType, pivots: IntTensor): Triple From efb23591a9efebe3bf86b2757ac482032b5047a7 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 17 Mar 2021 07:36:35 +0000 Subject: [PATCH 039/211] Added squeeze --- .../space/kscience/kmath/tensors/DoubleTensorAlgebra.kt | 4 ++++ .../kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt | 2 ++ 2 files changed, 6 insertions(+) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 888f12923..675be2f33 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -266,6 +266,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra DoubleTensorAlgebra(block: DoubleTensorAlgebra.() -> R): R = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 0af757d1a..b1adf2962 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -86,4 +86,6 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.flatten.html#torch.flatten public fun TensorType.flatten(startDim: Int, endDim: Int): TensorType + //https://pytorch.org/docs/stable/generated/torch.squeeze.html + public fun TensorType.squeeze(dim: Int): TensorType } From 1fa0da2810d69aa6d9dac669b4ebc353dd5265d1 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 17 Mar 2021 17:53:14 +0300 Subject: [PATCH 040/211] complete lu and matrix mapping --- .../kscience/kmath/tensors/BufferedTensor.kt | 95 +++++++++---------- .../tensors/DoubleLinearOpsTensorAlgebra.kt | 83 ++++++++-------- .../kscience/kmath/tensors/TensorAlgebra.kt | 2 +- 3 files changed, 85 insertions(+), 95 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index c9a401ad5..c48e47f4c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.nd.* import space.kscience.kmath.structures.* @@ -29,59 +31,50 @@ public open class BufferedTensor( override fun hashCode(): Int = 0 + // todo rename to vector + public inline fun forEachVector(vectorAction : (MutableStructure1D) -> Unit): Unit { + check(shape.size >= 1) {"todo"} + val vectorOffset = strides.strides[0] + val vectorShape = intArrayOf(shape.last()) + for (offset in 0 until numel step vectorOffset) { + val vector = BufferedTensor(vectorShape, buffer, offset).as1D() + vectorAction(vector) + } + } + + public inline fun forEachMatrix(matrixAction : (MutableStructure2D) -> Unit): Unit { + check(shape.size >= 2) {"todo"} + val matrixOffset = strides.strides[1] + val matrixShape = intArrayOf(shape[shape.size - 2], shape.last()) //todo better way? + for (offset in 0 until numel step matrixOffset) { + val matrix = BufferedTensor(matrixShape, buffer, offset).as2D() + matrixAction(matrix) + } + } + // todo remove code copy-pasting + + public fun vectorSequence(): Sequence> = sequence { + check(shape.size >= 1) {"todo"} + val vectorOffset = strides.strides[0] + val vectorShape = intArrayOf(shape.last()) + for (offset in 0 until numel step vectorOffset) { + val vector = BufferedTensor(vectorShape, buffer, offset).as1D() + yield(vector) + } + } + + public fun matrixSequence(): Sequence> = sequence { + check(shape.size >= 2) {"todo"} + val matrixOffset = strides.strides[1] + val matrixShape = intArrayOf(shape[shape.size - 2], shape.last()) //todo better way? + for (offset in 0 until numel step matrixOffset) { + val matrix = BufferedTensor(matrixShape, buffer, offset).as2D() + yield(matrix) + } + } + } -/* -//todo make generator mb nextMatrixIndex? -public class InnerMatrix(private val tensor: BufferedTensor){ - private var offset: Int = 0 - private val n : Int = tensor.shape.size - //stride? - private val step = tensor.shape[n - 1] * tensor.shape[n - 2] - - public operator fun get(i: Int, j: Int): T { - val index = tensor.strides.index(offset) - index[n - 2] = i - index[n - 1] = j - return tensor[index] - } - - public operator fun set(i: Int, j: Int, value: T): Unit { - val index = tensor.strides.index(offset) - index[n - 2] = i - index[n - 1] = j - tensor[index] = value - } - - public fun makeStep(){ - offset += step - } -} - -public class InnerVector(private val tensor: BufferedTensor){ - private var offset: Int = 0 - private val n : Int = tensor.shape.size - //stride? - private val step = tensor.shape[n - 1] - - public operator fun get(i: Int): T { - val index = tensor.strides.index(offset) - index[n - 1] = i - return tensor[index] - } - - public operator fun set(i: Int, value: T): Unit { - val index = tensor.strides.index(offset) - index[n - 1] = i - tensor[index] = value - } - - public fun makeStep(){ - offset += step - } -} -//todo default buffer = arrayOf(0)??? - */ public class IntTensor( shape: IntArray, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt index 689eda9e0..3f44305b1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt @@ -9,27 +9,21 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.lu(): Pair { - /* + // todo checks + val luTensor = this.copy() - val lu = InnerMatrix(luTensor) - //stride TODO!!! move to generator? - var matCnt = 1 - for (i in 0 until this.shape.size - 2) { - matCnt *= this.shape[i] - } + val n = this.shape.size - val m = this.shape[n - 1] - val pivotsShape = IntArray(n - 1) { i -> - this.shape[i] - } + val m = this.shape.last() + val pivotsShape = IntArray(n - 1) { i -> this.shape[i] } val pivotsTensor = IntTensor( pivotsShape, - IntArray(matCnt * m) { 0 } + IntArray(pivotsShape.reduce(Int::times)) { 0 } //todo default??? ) - val pivot = InnerVector(pivotsTensor) - for (i in 0 until matCnt) { - for (row in 0 until m) pivot[row] = row + + for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())){ + for (row in 0 until m) pivots[row] = row for (i in 0 until m) { var maxA = -1.0 @@ -47,9 +41,9 @@ public class DoubleLinearOpsTensorAlgebra : if (iMax != i) { - val j = pivot[i] - pivot[i] = pivot[iMax] - pivot[iMax] = j + val j = pivots[i] + pivots[i] = pivots[iMax] + pivots[iMax] = j for (k in 0 until m) { val tmp = lu[i, k] @@ -66,42 +60,45 @@ public class DoubleLinearOpsTensorAlgebra : } } } - lu.makeStep() - pivot.makeStep() } - return Pair(luTensor, pivotsTensor)*/ - TODO("Andrei, use view, get, as2D, as1D") + return Pair(luTensor, pivotsTensor) + } - override fun luPivot(lu: DoubleTensor, pivots: IntTensor): Triple { - /* - // todo checks - val n = lu.shape[0] - val p = lu.zeroesLike() - pivots.buffer.unsafeToIntArray().forEachIndexed { i, pivot -> - p[i, pivot] = 1.0 + override fun luPivot(luTensor: DoubleTensor, pivotsTensor: IntTensor): Triple { + //todo checks + val n = luTensor.shape.last() + val pTensor = luTensor.zeroesLike() + for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.vectorSequence())){ + for (i in 0 until n){ + p[i, pivot[i]] = 1.0 + } } - val l = lu.zeroesLike() - val u = lu.zeroesLike() - for (i in 0 until n) { - for (j in 0 until n) { - if (i == j) { - l[i, j] = 1.0 - } - if (j < i) { - l[i, j] = lu[i, j] - } - if (j >= i) { - u[i, j] = lu[i, j] + val lTensor = luTensor.zeroesLike() + val uTensor = luTensor.zeroesLike() + + for ((pairLU, lu) in lTensor.matrixSequence().zip(uTensor.matrixSequence()).zip(luTensor.matrixSequence())){ + val (l, u) = pairLU + for (i in 0 until n) { + for (j in 0 until n) { + if (i == j) { + l[i, j] = 1.0 + } + if (j < i) { + l[i, j] = lu[i, j] + } + if (j >= i) { + u[i, j] = lu[i, j] + } } } } - return Triple(p, l, u)*/ - TODO("Andrei, first we need implement get(Int)") + return Triple(pTensor, lTensor, uTensor) + } override fun DoubleTensor.cholesky(): DoubleTensor { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index b1adf2962..7ec920d88 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -5,7 +5,7 @@ public interface TensorAlgebra> { public fun zeros(shape: IntArray): TensorType - public fun TensorType.zeroesLike(): TensorType + public fun TensorType.zeroesLike(): TensorType // mb it shouldn't be tensor but algebra method (like in numpy/torch) ? public fun ones(shape: IntArray): TensorType public fun TensorType.onesLike(): TensorType From 5e94610e2862fc2ecfe5e4f9e709ecc2ab3f428a Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 19 Mar 2021 17:51:30 +0300 Subject: [PATCH 041/211] imp full and remove copypaste in geners --- .../kscience/kmath/tensors/BufferedTensor.kt | 34 +++++++------------ .../kmath/tensors/DoubleTensorAlgebra.kt | 34 +++++++------------ .../kscience/kmath/tensors/TensorAlgebra.kt | 12 +++---- 3 files changed, 31 insertions(+), 49 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index c48e47f4c..b9ebf578a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -31,28 +31,6 @@ public open class BufferedTensor( override fun hashCode(): Int = 0 - // todo rename to vector - public inline fun forEachVector(vectorAction : (MutableStructure1D) -> Unit): Unit { - check(shape.size >= 1) {"todo"} - val vectorOffset = strides.strides[0] - val vectorShape = intArrayOf(shape.last()) - for (offset in 0 until numel step vectorOffset) { - val vector = BufferedTensor(vectorShape, buffer, offset).as1D() - vectorAction(vector) - } - } - - public inline fun forEachMatrix(matrixAction : (MutableStructure2D) -> Unit): Unit { - check(shape.size >= 2) {"todo"} - val matrixOffset = strides.strides[1] - val matrixShape = intArrayOf(shape[shape.size - 2], shape.last()) //todo better way? - for (offset in 0 until numel step matrixOffset) { - val matrix = BufferedTensor(matrixShape, buffer, offset).as2D() - matrixAction(matrix) - } - } - // todo remove code copy-pasting - public fun vectorSequence(): Sequence> = sequence { check(shape.size >= 1) {"todo"} val vectorOffset = strides.strides[0] @@ -73,6 +51,18 @@ public open class BufferedTensor( } } + public inline fun forEachVector(vectorAction : (MutableStructure1D) -> Unit): Unit { + for (vector in vectorSequence()){ + vectorAction(vector) + } + } + + public inline fun forEachMatrix(matrixAction : (MutableStructure2D) -> Unit): Unit { + for (matrix in matrixSequence()){ + matrixAction(matrix) + } + } + } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 675be2f33..6459f4510 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -10,23 +10,24 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra> { - public fun zeros(shape: IntArray): TensorType - public fun TensorType.zeroesLike(): TensorType // mb it shouldn't be tensor but algebra method (like in numpy/torch) ? - public fun ones(shape: IntArray): TensorType - public fun TensorType.onesLike(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.full.html public fun full(shape: IntArray, value: T): TensorType + public fun ones(shape: IntArray): TensorType + public fun zeros(shape: IntArray): TensorType + //https://pytorch.org/docs/stable/generated/torch.full_like.html#torch.full_like public fun TensorType.fullLike(value: T): TensorType + public fun TensorType.zeroesLike(): TensorType + public fun TensorType.onesLike(): TensorType + //https://pytorch.org/docs/stable/generated/torch.eye.html public fun eye(n: Int): TensorType From 274be613302d8cdef5f8a81fc8aeee5c88bf8ccd Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 19 Mar 2021 19:40:17 +0000 Subject: [PATCH 042/211] Explicit broadcasting enforced --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 2 +- .../BroadcastDoubleTensorAlgebra.kt} | 151 ++++++++++-------- .../tensors/{ => core}/BufferedTensor.kt | 12 +- .../{ => core}/DoubleAnalyticTensorAlgebra.kt | 4 +- .../DoubleLinearOpsTensorAlgebra.kt | 4 +- .../{ => core}/DoubleOrderedTensorAlgebra.kt | 4 +- .../DoubleReduceOpsTensorAlgebra.kt | 6 +- .../tensors/{ => core}/DoubleTensorAlgebra.kt | 107 +++++++------ .../kscience/kmath/tensors/core/checks.kt | 67 ++++++++ .../kscience/kmath/tensors/core/utils.kt | 36 +++++ .../kmath/tensors/TestDoubleTensorAlgebra.kt | 105 ------------ .../kmath/tensors/core/TestBroadcasting.kt | 82 ++++++++++ .../tensors/{ => core}/TestDoubleTensor.kt | 10 +- .../tensors/core/TestDoubleTensorAlgebra.kt | 50 ++++++ 14 files changed, 407 insertions(+), 233 deletions(-) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{utils.kt => core/BroadcastDoubleTensorAlgebra.kt} (50%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => core}/BufferedTensor.kt (88%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => core}/DoubleAnalyticTensorAlgebra.kt (96%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => core}/DoubleLinearOpsTensorAlgebra.kt (96%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => core}/DoubleOrderedTensorAlgebra.kt (89%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => core}/DoubleReduceOpsTensorAlgebra.kt (68%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => core}/DoubleTensorAlgebra.kt (77%) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt delete mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt rename kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/{ => core}/TestDoubleTensor.kt (74%) create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index 2e1c4a92c..94176564c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -17,7 +17,7 @@ public interface LinearOpsTensorAlgebra, Inde public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun luPivot(lu: TensorType, pivots: IntTensor): Triple + public fun luPivot(lu: TensorType, pivots: IndexTensorType): Triple //https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd public fun TensorType.svd(): Triple diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt similarity index 50% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index e7e043463..a4767a612 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -1,10 +1,91 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core -import space.kscience.kmath.structures.* import kotlin.math.max +public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { + + override fun DoubleTensor.plus(other: DoubleTensor): DoubleTensor { + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + newThis.buffer.array()[i] + newOther.buffer.array()[i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun DoubleTensor.plusAssign(other: DoubleTensor) { + val newOther = broadcastTo(other, this.shape) + for (i in 0 until this.strides.linearSize) { + this.buffer.array()[this.bufferStart + i] += + newOther.buffer.array()[this.bufferStart + i] + } + } + + override fun DoubleTensor.minus(other: DoubleTensor): DoubleTensor { + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + newThis.buffer.array()[i] - newOther.buffer.array()[i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun DoubleTensor.minusAssign(other: DoubleTensor) { + val newOther = broadcastTo(other, this.shape) + for (i in 0 until this.strides.linearSize) { + this.buffer.array()[this.bufferStart + i] -= + newOther.buffer.array()[this.bufferStart + i] + } + } + + override fun DoubleTensor.times(other: DoubleTensor): DoubleTensor { + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + newThis.buffer.array()[newOther.bufferStart + i] * + newOther.buffer.array()[newOther.bufferStart + i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun DoubleTensor.timesAssign(other: DoubleTensor) { + val newOther = broadcastTo(other, this.shape) + for (i in 0 until this.strides.linearSize) { + this.buffer.array()[this.bufferStart + i] *= + newOther.buffer.array()[this.bufferStart + i] + } + } + + override fun DoubleTensor.div(other: DoubleTensor): DoubleTensor { + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + newThis.buffer.array()[newOther.bufferStart + i] / + newOther.buffer.array()[newOther.bufferStart + i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun DoubleTensor.divAssign(other: DoubleTensor) { + val newOther = broadcastTo(other, this.shape) + for (i in 0 until this.strides.linearSize) { + this.buffer.array()[this.bufferStart + i] /= + newOther.buffer.array()[this.bufferStart + i] + } + } + +} + +public inline fun broadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorAlgebra.() -> R): R = + BroadcastDoubleTensorAlgebra().block() + internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { + println(shapes) var totalDim = 0 for (shape in shapes) { totalDim = max(totalDim, shape.size) @@ -99,68 +180,4 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List, - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkDot(a: TensorType, b: TensorType): Unit { - val sa = a.shape - val sb = b.shape - val na = sa.size - val nb = sb.size - var status: Boolean - if (nb == 1) { - status = sa.last() == sb[0] - } else { - status = sa.last() == sb[nb - 2] - if ((na > 2) and (nb > 2)) { - status = status and - (sa.take(nb - 2).toIntArray() contentEquals sb.take(nb - 2).toIntArray()) - } - } - check(status) { "Incompatible shapes $sa and $sb for dot product" } -} - -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkTranspose(dim: Int, i: Int, j: Int): Unit = - check((i < dim) and (j < dim)) { - "Cannot transpose $i to $j for a tensor of dim $dim" - } - -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = - check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) - -/** - * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. - */ -internal fun Buffer.array(): IntArray = when(this) { - is IntBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to IntArray") -} - -/** - * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. - */ -internal fun Buffer.array(): LongArray = when(this) { - is LongBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to LongArray") -} - -/** - * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. - */ -internal fun Buffer.array(): FloatArray = when(this) { - is FloatBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to FloatArray") -} - -/** - * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. - */ -internal fun Buffer.array(): DoubleArray = when(this) { - is RealBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") -} +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt similarity index 88% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index c48e47f4c..cbfb15be0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,8 +1,10 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core import space.kscience.kmath.linear.Matrix import space.kscience.kmath.nd.* import space.kscience.kmath.structures.* +import space.kscience.kmath.tensors.TensorStrides +import space.kscience.kmath.tensors.TensorStructure public open class BufferedTensor( @@ -76,25 +78,25 @@ public open class BufferedTensor( } -public class IntTensor( +public class IntTensor internal constructor( shape: IntArray, buffer: IntArray, offset: Int = 0 ) : BufferedTensor(shape, IntBuffer(buffer), offset) -public class LongTensor( +public class LongTensor internal constructor( shape: IntArray, buffer: LongArray, offset: Int = 0 ) : BufferedTensor(shape, LongBuffer(buffer), offset) -public class FloatTensor( +public class FloatTensor internal constructor( shape: IntArray, buffer: FloatArray, offset: Int = 0 ) : BufferedTensor(shape, FloatBuffer(buffer), offset) -public class DoubleTensor( +public class DoubleTensor internal constructor( shape: IntArray, buffer: DoubleArray, offset: Int = 0 diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt similarity index 96% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt index 5349a9923..a34fe4b6c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt @@ -1,4 +1,6 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.tensors.AnalyticTensorAlgebra public class DoubleAnalyticTensorAlgebra: AnalyticTensorAlgebra, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt similarity index 96% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 3f44305b1..8a16dc3ed 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,4 +1,6 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.tensors.LinearOpsTensorAlgebra public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt similarity index 89% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt index bd6bcfe8f..a6bea59f4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt @@ -1,4 +1,6 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.tensors.OrderedTensorAlgebra public open class DoubleOrderedTensorAlgebra: OrderedTensorAlgebra, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt similarity index 68% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt index 00d9b3ff8..9a8aa9ebf 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt @@ -1,8 +1,10 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.tensors.ReduceOpsTensorAlgebra public class DoubleReduceOpsTensorAlgebra: DoubleTensorAlgebra(), - ReduceOpsTensorAlgebra { + ReduceOpsTensorAlgebra { override fun DoubleTensor.value(): Double { check(this.shape contentEquals intArrayOf(1)) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt similarity index 77% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 675be2f33..9decc0e6a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,8 +1,18 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { + public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor { + checkEmptyShape(shape) + checkEmptyDoubleBuffer(buffer) + checkBufferShapeConsistency(shape, buffer) + return DoubleTensor(shape, buffer, 0) + } + + override operator fun DoubleTensor.get(i: Int): DoubleTensor { val lastShape = this.shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) @@ -53,13 +63,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.array()[i] + newOther.buffer.array()[i] + checkShapesCompatible(this, other) + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.array()[i] + other.buffer.array()[i] } - return DoubleTensor(newThis.shape, resBuffer) + return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.plusAssign(value: Double) { @@ -69,10 +77,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.array()[i] - newOther.buffer.array()[i] + checkShapesCompatible(this, other) + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.array()[i] - other.buffer.array()[i] } - return DoubleTensor(newThis.shape, resBuffer) + return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.minusAssign(value: Double) { @@ -107,10 +113,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.array()[newOther.bufferStart + i] * - newOther.buffer.array()[newOther.bufferStart + i] + checkShapesCompatible(this, other) + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.array()[other.bufferStart + i] * + other.buffer.array()[other.bufferStart + i] } - return DoubleTensor(newThis.shape, resBuffer) + return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.timesAssign(value: Double) { @@ -142,10 +145,40 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + this.buffer.array()[this.bufferStart + i] / value + } + return DoubleTensor(this.shape, resBuffer) + } + + override fun DoubleTensor.div(other: DoubleTensor): DoubleTensor { + checkShapesCompatible(this, other) + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.array()[other.bufferStart + i] / + other.buffer.array()[other.bufferStart + i] + } + return DoubleTensor(this.shape, resBuffer) + } + + override fun DoubleTensor.divAssign(value: Double) { + for (i in 0 until this.strides.linearSize) { + this.buffer.array()[this.bufferStart + i] /= value + } + } + + override fun DoubleTensor.divAssign(other: DoubleTensor) { + checkShapesCompatible(this, other) + for (i in 0 until this.strides.linearSize) { + this.buffer.array()[this.bufferStart + i] /= + other.buffer.array()[this.bufferStart + i] } } @@ -229,27 +262,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra DoubleTensorAlgebra(block: DoubleTensorAlgebra.() -> R): R = - DoubleTensorAlgebra().block() \ No newline at end of file + DoubleTensorAlgebra().block() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt new file mode 100644 index 000000000..f1ae89490 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -0,0 +1,67 @@ +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.tensors.TensorAlgebra +import space.kscience.kmath.tensors.TensorStructure + + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkEmptyShape(shape: IntArray): Unit = + check(shape.isNotEmpty()) { + "Illegal empty shape provided" + } + +internal inline fun < TensorType : TensorStructure, + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = + check(buffer.isNotEmpty()) { + "Illegal empty buffer provided" + } + +internal inline fun < TensorType : TensorStructure, + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = + check(buffer.size == shape.reduce(Int::times)) { + "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" + } + + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkShapesCompatible(a: TensorType, b: TensorType): Unit = + check(a.shape contentEquals b.shape) { + "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " + } + + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkDot(a: TensorType, b: TensorType): Unit { + val sa = a.shape + val sb = b.shape + val na = sa.size + val nb = sb.size + var status: Boolean + if (nb == 1) { + status = sa.last() == sb[0] + } else { + status = sa.last() == sb[nb - 2] + if ((na > 2) and (nb > 2)) { + status = status and + (sa.take(nb - 2).toIntArray() contentEquals sb.take(nb - 2).toIntArray()) + } + } + check(status) { "Incompatible shapes ${sa.toList()} and ${sb.toList()} provided for dot product" } +} + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkTranspose(dim: Int, i: Int, j: Int): Unit = + check((i < dim) and (j < dim)) { + "Cannot transpose $i to $j for a tensor of dim $dim" + } + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = + check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt new file mode 100644 index 000000000..69c8afde5 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -0,0 +1,36 @@ +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.structures.* + + +/** + * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.array(): IntArray = when (this) { + is IntBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to IntArray") +} + +/** + * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.array(): LongArray = when (this) { + is LongBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to LongArray") +} + +/** + * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.array(): FloatArray = when (this) { + is FloatBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to FloatArray") +} + +/** + * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.array(): DoubleArray = when (this) { + is RealBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") +} diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt deleted file mode 100644 index a060a970f..000000000 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt +++ /dev/null @@ -1,105 +0,0 @@ -package space.kscience.kmath.tensors - - -import kotlin.test.Test -import kotlin.test.assertTrue - -class TestDoubleTensorAlgebra { - - @Test - fun doublePlus() = DoubleTensorAlgebra { - val tensor = DoubleTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0)) - val res = 10.0 + tensor - assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0,12.0)) - } - - @Test - fun transpose1x1() = DoubleTensorAlgebra { - val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(0.0)) - val res = tensor.transpose(0, 0) - - assertTrue(res.buffer.array() contentEquals doubleArrayOf(0.0)) - assertTrue(res.shape contentEquals intArrayOf(1)) - } - - @Test - fun transpose3x2() = DoubleTensorAlgebra { - val tensor = DoubleTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val res = tensor.transpose(1, 0) - - assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) - assertTrue(res.shape contentEquals intArrayOf(2, 3)) - } - - @Test - fun transpose1x2x3() = DoubleTensorAlgebra { - val tensor = DoubleTensor(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val res01 = tensor.transpose(0, 1) - val res02 = tensor.transpose(0, 2) - val res12 = tensor.transpose(1, 2) - - assertTrue(res01.shape contentEquals intArrayOf(2, 1, 3)) - assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) - assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2)) - - assertTrue(res01.buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res02.buffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) - assertTrue(res12.buffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) - } - - @Test - fun broadcastShapes() = DoubleTensorAlgebra { - assertTrue(broadcastShapes( - intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) - ) contentEquals intArrayOf(1, 2, 3)) - - assertTrue(broadcastShapes( - intArrayOf(6, 7), intArrayOf(5, 6, 1), intArrayOf(7,), intArrayOf(5, 1, 7) - ) contentEquals intArrayOf(5, 6, 7)) - } - - @Test - fun broadcastTo() = DoubleTensorAlgebra { - val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - - val res = broadcastTo(tensor2, tensor1.shape) - assertTrue(res.shape contentEquals intArrayOf(2, 3)) - assertTrue(res.buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) - } - - @Test - fun broadcastTensors() = DoubleTensorAlgebra { - val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) - - val res = broadcastTensors(tensor1, tensor2, tensor3) - - assertTrue(res[0].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) - - assertTrue(res[0].buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res[1].buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) - assertTrue(res[2].buffer.array() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) - } - - @Test - fun minusTensor() = DoubleTensorAlgebra { - val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) - - assertTrue((tensor2 - tensor1).shape contentEquals intArrayOf(2, 3)) - assertTrue((tensor2 - tensor1).buffer.array() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) - - assertTrue((tensor3 - tensor1).shape contentEquals intArrayOf(1, 2, 3)) - assertTrue((tensor3 - tensor1).buffer.array() - contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0)) - - assertTrue((tensor3 - tensor2).shape contentEquals intArrayOf(1, 1, 3)) - assertTrue((tensor3 - tensor2).buffer.array() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) - } - -} \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt new file mode 100644 index 000000000..2633229ea --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -0,0 +1,82 @@ +package space.kscience.kmath.tensors.core + +import kotlin.test.Test +import kotlin.test.assertTrue + +class TestBroadcasting { + + @Test + fun broadcastShapes() = DoubleTensorAlgebra { + assertTrue( + broadcastShapes( + intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) + ) contentEquals intArrayOf(1, 2, 3) + ) + + assertTrue( + broadcastShapes( + intArrayOf(6, 7), intArrayOf(5, 6, 1), intArrayOf(7), intArrayOf(5, 1, 7) + ) contentEquals intArrayOf(5, 6, 7) + ) + } + + @Test + fun broadcastTo() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + + val res = broadcastTo(tensor2, tensor1.shape) + assertTrue(res.shape contentEquals intArrayOf(2, 3)) + assertTrue(res.buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + } + + @Test + fun broadcastTensors() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + + val res = broadcastTensors(tensor1, tensor2, tensor3) + + assertTrue(res[0].shape contentEquals intArrayOf(1, 2, 3)) + assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) + assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) + + assertTrue(res[0].buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + assertTrue(res[2].buffer.array() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) + } + + @Test + fun minusTensor() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + + val tensor21 = broadcastDoubleTensorAlgebra { + tensor2 - tensor1 + } + + val tensor31 = broadcastDoubleTensorAlgebra { + tensor3 - tensor1 + } + + val tensor32 = broadcastDoubleTensorAlgebra { + tensor3 - tensor2 + } + + + assertTrue(tensor21.shape contentEquals intArrayOf(2, 3)) + assertTrue(tensor21.buffer.array() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) + + assertTrue(tensor31.shape contentEquals intArrayOf(1, 2, 3)) + assertTrue( + tensor31.buffer.array() + contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0) + ) + + assertTrue(tensor32.shape contentEquals intArrayOf(1, 1, 3)) + assertTrue(tensor32.buffer.array() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) + } + +} \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt similarity index 74% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt rename to kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 6b20027c7..b12b08b52 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,4 +1,4 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core import space.kscience.kmath.nd.as1D @@ -13,20 +13,20 @@ class TestDoubleTensor { @Test fun valueTest() = DoubleReduceOpsTensorAlgebra { val value = 12.5 - val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(value)) + val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @Test - fun stridesTest(){ - val tensor = DoubleTensor(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) + fun stridesTest() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) assertEquals(tensor[intArrayOf(0,1)], 5.8) assertTrue(tensor.elements().map{ it.second }.toList().toDoubleArray() contentEquals tensor.buffer.toDoubleArray()) } @Test fun getTest() = DoubleTensorAlgebra { - val tensor = DoubleTensor(intArrayOf(1,2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) + val tensor = fromArray(intArrayOf(1,2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) val matrix = tensor[0].as2D() assertEquals(matrix[0,1], 5.8) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt new file mode 100644 index 000000000..8b4d5ca16 --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -0,0 +1,50 @@ +package space.kscience.kmath.tensors.core + + +import kotlin.test.Test +import kotlin.test.assertTrue + +class TestDoubleTensorAlgebra { + + @Test + fun doublePlus() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0)) + val res = 10.0 + tensor + assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0, 12.0)) + } + + @Test + fun transpose1x1() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(1), doubleArrayOf(0.0)) + val res = tensor.transpose(0, 0) + + assertTrue(res.buffer.array() contentEquals doubleArrayOf(0.0)) + assertTrue(res.shape contentEquals intArrayOf(1)) + } + + @Test + fun transpose3x2() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val res = tensor.transpose(1, 0) + + assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) + assertTrue(res.shape contentEquals intArrayOf(2, 3)) + } + + @Test + fun transpose1x2x3() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val res01 = tensor.transpose(0, 1) + val res02 = tensor.transpose(0, 2) + val res12 = tensor.transpose(1, 2) + + assertTrue(res01.shape contentEquals intArrayOf(2, 1, 3)) + assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) + assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2)) + + assertTrue(res01.buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res02.buffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res12.buffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + } + +} \ No newline at end of file From 3535e512483b74f00867858b18e38a2150f3451c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 19 Mar 2021 19:52:58 +0000 Subject: [PATCH 043/211] Broadcasting as its own algebra --- .../core/BroadcastDoubleTensorAlgebra.kt | 2 +- .../kmath/tensors/core/TestBroadcasting.kt | 17 ++++------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index a4767a612..20f64f469 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -80,7 +80,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { } -public inline fun broadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorAlgebra.() -> R): R = +public inline fun BroadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorAlgebra.() -> R): R = BroadcastDoubleTensorAlgebra().block() diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 2633229ea..73e3993a1 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -48,23 +48,14 @@ class TestBroadcasting { } @Test - fun minusTensor() = DoubleTensorAlgebra { + fun minusTensor() = BroadcastDoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) - val tensor21 = broadcastDoubleTensorAlgebra { - tensor2 - tensor1 - } - - val tensor31 = broadcastDoubleTensorAlgebra { - tensor3 - tensor1 - } - - val tensor32 = broadcastDoubleTensorAlgebra { - tensor3 - tensor2 - } - + val tensor21 = tensor2 - tensor1 + val tensor31 = tensor3 - tensor1 + val tensor32 = tensor3 - tensor2 assertTrue(tensor21.shape contentEquals intArrayOf(2, 3)) assertTrue(tensor21.buffer.array() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) From 93d3cb47bed67d95c75d6e9f54283f7428dd150e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 19 Mar 2021 20:10:08 +0000 Subject: [PATCH 044/211] Testing linear structure --- .../kscience/kmath/tensors/TensorAlgebra.kt | 12 +++---- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 35 ++++++++----------- .../tensors/core/TestDoubleTensorAlgebra.kt | 32 +++++++++++++++++ 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 7ec920d88..1673657d3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -3,19 +3,17 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { + //https://pytorch.org/docs/stable/generated/torch.full.html + public fun full(value: T, shape: IntArray): TensorType + + //https://pytorch.org/docs/stable/generated/torch.full_like.html#torch.full_like + public fun TensorType.fullLike(value: T): TensorType public fun zeros(shape: IntArray): TensorType public fun TensorType.zeroesLike(): TensorType // mb it shouldn't be tensor but algebra method (like in numpy/torch) ? public fun ones(shape: IntArray): TensorType public fun TensorType.onesLike(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.full.html - public fun full(shape: IntArray, value: T): TensorType - - //https://pytorch.org/docs/stable/generated/torch.full_like.html#torch.full_like - public fun TensorType.fullLike(value: T): TensorType - //https://pytorch.org/docs/stable/generated/torch.eye.html public fun eye(n: Int): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 9decc0e6a..1c156b4e3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -20,23 +20,25 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Date: Fri, 19 Mar 2021 20:32:57 +0000 Subject: [PATCH 045/211] merge PR --- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 465c2ddc1..875f21687 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -12,7 +12,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra>>>>>> ups/feature/tensor-algebra:kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt override fun DoubleTensor.fullLike(value: Double): DoubleTensor { val shape = this.shape val buffer = DoubleArray(this.strides.linearSize) { value } return DoubleTensor(shape, buffer) } -<<<<<<< HEAD:kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt - override fun DoubleTensor.zeroesLike(): DoubleTensor = this.fullLike(0.0) - -======= override fun zeros(shape: IntArray): DoubleTensor = full(0.0, shape) override fun DoubleTensor.zeroesLike(): DoubleTensor = this.fullLike(0.0) override fun ones(shape: IntArray): DoubleTensor = full(1.0, shape) ->>>>>>> ups/feature/tensor-algebra:kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt override fun DoubleTensor.onesLike(): DoubleTensor = this.fullLike(1.0) override fun eye(n: Int): DoubleTensor { @@ -71,7 +53,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra other.buffer.array()[other.bufferStart + i] + this From b7e1349eadc0cfe9b573006c79e714333655a2d1 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sat, 20 Mar 2021 18:59:54 +0000 Subject: [PATCH 046/211] atanh as example --- .../kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt index a34fe4b6c..8a579b7da 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.AnalyticTensorAlgebra +import kotlin.math.* public class DoubleAnalyticTensorAlgebra: AnalyticTensorAlgebra, @@ -63,7 +64,11 @@ public class DoubleAnalyticTensorAlgebra: } override fun DoubleTensor.atanh(): DoubleTensor { - TODO("Not yet implemented") + return DoubleTensor( + this.shape, + this.buffer.array().map(::atanh).toDoubleArray(), + this.bufferStart + ) } override fun DoubleTensor.ceil(): DoubleTensor { From 94e5ee4a6de020d77c49ce57e7795d3a33abe80e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sun, 21 Mar 2021 08:01:52 +0000 Subject: [PATCH 047/211] TensorLinearStructure introduced --- .../space/kscience/kmath/nd/StructureND.kt | 17 +++---- .../core/BroadcastDoubleTensorAlgebra.kt | 24 +++++----- .../kmath/tensors/core/BufferedTensor.kt | 18 ++++---- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 44 +++++++++---------- .../TensorLinearStructure.kt} | 33 ++++++++------ 5 files changed, 69 insertions(+), 67 deletions(-) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{TensorStrides.kt => core/TensorLinearStructure.kt} (55%) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index 86b867130..f28d29e47 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -177,7 +177,7 @@ public interface Strides { /** * Array strides */ - public val strides: IntArray + public val strides: List /** * Get linear index from multidimensional index @@ -209,12 +209,6 @@ public interface Strides { } } -internal inline fun offsetFromIndex(index: IntArray, shape: IntArray, strides: IntArray): Int = - index.mapIndexed { i, value -> - if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})") - value * strides[i] - }.sum() - /** * Simple implementation of [Strides]. */ @@ -225,7 +219,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) : /** * Strides for memory access */ - override val strides: IntArray by lazy { + override val strides: List by lazy { sequence { var current = 1 yield(1) @@ -234,10 +228,13 @@ public class DefaultStrides private constructor(override val shape: IntArray) : current *= it yield(current) } - }.toList().toIntArray() + }.toList() } - override fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides) + override fun offset(index: IntArray): Int = index.mapIndexed { i, value -> + if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})") + value * strides[i] + }.sum() override fun index(offset: Int): IntArray { val res = IntArray(shape.size) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index 20f64f469..4bfbe5863 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -8,7 +8,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(this, other) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> newThis.buffer.array()[i] + newOther.buffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) @@ -16,7 +16,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun DoubleTensor.plusAssign(other: DoubleTensor) { val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] += newOther.buffer.array()[this.bufferStart + i] } @@ -26,7 +26,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(this, other) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> newThis.buffer.array()[i] - newOther.buffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) @@ -34,7 +34,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun DoubleTensor.minusAssign(other: DoubleTensor) { val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] -= newOther.buffer.array()[this.bufferStart + i] } @@ -44,7 +44,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(this, other) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> newThis.buffer.array()[newOther.bufferStart + i] * newOther.buffer.array()[newOther.bufferStart + i] } @@ -53,7 +53,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun DoubleTensor.timesAssign(other: DoubleTensor) { val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] *= newOther.buffer.array()[this.bufferStart + i] } @@ -63,7 +63,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(this, other) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> newThis.buffer.array()[newOther.bufferStart + i] / newOther.buffer.array()[newOther.bufferStart + i] } @@ -72,7 +72,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun DoubleTensor.divAssign(other: DoubleTensor) { val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] /= newOther.buffer.array()[this.bufferStart + i] } @@ -130,7 +130,7 @@ internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): Doubl } for (linearIndex in 0 until n) { - val totalMultiIndex = resTensor.strides.index(linearIndex) + val totalMultiIndex = resTensor.linearStructure.index(linearIndex) val curMultiIndex = tensor.shape.copyOf() val offset = totalMultiIndex.size - curMultiIndex.size @@ -143,7 +143,7 @@ internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): Doubl } } - val curLinearIndex = tensor.strides.offset(curMultiIndex) + val curLinearIndex = tensor.linearStructure.offset(curMultiIndex) resTensor.buffer.array()[linearIndex] = tensor.buffer.array()[tensor.bufferStart + curLinearIndex] } @@ -159,7 +159,7 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List( internal val bufferStart: Int ) : TensorStructure { - public val strides: TensorStrides - get() = TensorStrides(shape) + public val linearStructure: TensorLinearStructure + get() = TensorLinearStructure(shape) public val numel: Int - get() = strides.linearSize + get() = linearStructure.size - override fun get(index: IntArray): T = buffer[bufferStart + strides.offset(index)] + override fun get(index: IntArray): T = buffer[bufferStart + linearStructure.offset(index)] override fun set(index: IntArray, value: T) { - buffer[bufferStart + strides.offset(index)] = value + buffer[bufferStart + linearStructure.offset(index)] = value } - override fun elements(): Sequence> = strides.indices().map { + override fun elements(): Sequence> = linearStructure.indices().map { it to this[it] } @@ -35,7 +33,7 @@ public open class BufferedTensor( public fun vectorSequence(): Sequence> = sequence { check(shape.size >= 1) {"todo"} - val vectorOffset = strides.strides[0] + val vectorOffset = linearStructure.strides[0] val vectorShape = intArrayOf(shape.last()) for (offset in 0 until numel step vectorOffset) { val vector = BufferedTensor(vectorShape, buffer, offset).as1D() @@ -45,7 +43,7 @@ public open class BufferedTensor( public fun matrixSequence(): Sequence> = sequence { check(shape.size >= 2) {"todo"} - val matrixOffset = strides.strides[1] + val matrixOffset = linearStructure.strides[1] val matrixShape = intArrayOf(shape[shape.size - 2], shape.last()) //todo better way? for (offset in 0 until numel step matrixOffset) { val matrix = BufferedTensor(matrixShape, buffer, offset).as2D() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 875f21687..385118d97 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -27,7 +27,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(other.linearStructure.size) { i -> other.buffer.array()[other.bufferStart + i] + this } return DoubleTensor(other.shape, resBuffer) @@ -64,35 +64,35 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[i] + other.buffer.array()[i] } return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.plusAssign(value: Double) { - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] += value } } override fun DoubleTensor.plusAssign(other: DoubleTensor) { checkShapesCompatible(this, other) - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] += other.buffer.array()[this.bufferStart + i] } } override fun Double.minus(other: DoubleTensor): DoubleTensor { - val resBuffer = DoubleArray(other.strides.linearSize) { i -> + val resBuffer = DoubleArray(other.linearStructure.size) { i -> this - other.buffer.array()[other.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } override fun DoubleTensor.minus(value: Double): DoubleTensor { - val resBuffer = DoubleArray(this.strides.linearSize) { i -> + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[this.bufferStart + i] - value } return DoubleTensor(this.shape, resBuffer) @@ -100,28 +100,28 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[i] - other.buffer.array()[i] } return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.minusAssign(value: Double) { - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] -= value } } override fun DoubleTensor.minusAssign(other: DoubleTensor) { checkShapesCompatible(this, other) - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] -= other.buffer.array()[this.bufferStart + i] } } override fun Double.times(other: DoubleTensor): DoubleTensor { - val resBuffer = DoubleArray(other.strides.linearSize) { i -> + val resBuffer = DoubleArray(other.linearStructure.size) { i -> other.buffer.array()[other.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) @@ -131,7 +131,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[other.bufferStart + i] * other.buffer.array()[other.bufferStart + i] } @@ -139,21 +139,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[this.bufferStart + i] / value } return DoubleTensor(this.shape, resBuffer) @@ -161,7 +161,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[other.bufferStart + i] / other.buffer.array()[other.bufferStart + i] } @@ -169,21 +169,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[this.bufferStart + i].unaryMinus() } return DoubleTensor(this.shape, resBuffer) @@ -191,7 +191,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})") + value * strides[i] + }.sum() + internal inline fun stridesFromShape(shape: IntArray): IntArray { val nDim = shape.size val res = IntArray(nDim) @@ -35,7 +39,7 @@ internal inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): return res } -internal inline fun nextIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { +internal inline fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { val res = index.copyOf() var current = nDim - 1 var carry = 0 @@ -47,26 +51,29 @@ internal inline fun nextIndex(index: IntArray, shape: IntArray, nDim: Int): IntA res[current] = 0 } current-- - } while(carry != 0 && current >= 0) + } while (carry != 0 && current >= 0) return res } - -public class TensorStrides(override val shape: IntArray): Strides +public class TensorLinearStructure(public val shape: IntArray) { - override val strides: IntArray + public val strides: IntArray get() = stridesFromShape(shape) - override fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides) + public fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides) - override fun index(offset: Int): IntArray = + public fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) - override fun nextIndex(index: IntArray): IntArray = - nextIndex(index, shape, shape.size) + public fun stepIndex(index: IntArray): IntArray = + stepIndex(index, shape, shape.size) - override val linearSize: Int + public val size: Int get() = shape.reduce(Int::times) + + public fun indices(): Sequence = (0 until size).asSequence().map { + index(it) + } } \ No newline at end of file From d8ef190ed8912476aaf7901431cc7e24d6449d94 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sun, 21 Mar 2021 08:07:17 +0000 Subject: [PATCH 048/211] UnaryPlus fails API check --- .../kotlin/space/kscience/kmath/nd/StructureND.kt | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index f28d29e47..78eac1809 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -189,11 +189,6 @@ public interface Strides { */ public fun index(offset: Int): IntArray - /** - * Get next multidimensional index from the current multidimensional index - */ - public fun nextIndex(index: IntArray): IntArray - /** * The size of linear buffer to accommodate all elements of ND-structure corresponding to strides */ @@ -232,7 +227,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) : } override fun offset(index: IntArray): Int = index.mapIndexed { i, value -> - if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})") + if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${this.shape[i]})") value * strides[i] }.sum() @@ -250,10 +245,6 @@ public class DefaultStrides private constructor(override val shape: IntArray) : return res } - override fun nextIndex(index: IntArray): IntArray { - TODO("Not yet implemented") - } - override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is DefaultStrides) return false @@ -275,7 +266,6 @@ public class DefaultStrides private constructor(override val shape: IntArray) : } } - public inline fun StructureND.combine( struct: StructureND, crossinline block: (T, T) -> T, From fa78ed1f45f3598e26d74d21d6f79c623c9e8e8e Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sun, 21 Mar 2021 19:05:11 +0300 Subject: [PATCH 049/211] map and analytic funcions --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 4 +- .../kscience/kmath/tensors/TensorAlgebra.kt | 5 ++ .../kmath/tensors/core/BufferedTensor.kt | 1 + .../core/DoubleAnalyticTensorAlgebra.kt | 73 +++++-------------- .../core/DoubleLinearOpsTensorAlgebra.kt | 63 +++++++++++----- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 39 +++++++++- .../kscience/kmath/tensors/core/checks.kt | 14 +++- 7 files changed, 122 insertions(+), 77 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index 94176564c..c4fa3e0a8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -14,10 +14,10 @@ public interface LinearOpsTensorAlgebra, Inde public fun TensorType.qr(): TensorType //https://pytorch.org/docs/stable/generated/torch.lu.html - public fun TensorType.lu(): Pair + public fun TensorType.lu(tol: T): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun luPivot(lu: TensorType, pivots: IndexTensorType): Triple + public fun luPivot(luTensor: TensorType, pivotsTensor: IndexTensorType): Triple //https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd public fun TensorType.svd(): Triple diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index e41b7546c..8be0dc149 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -3,6 +3,11 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { + public fun TensorType.map(transform: (T) -> T): TensorType + + public fun TensorType.eq(other: TensorType, eqFunction: (T, T) -> Boolean): Boolean + public fun TensorType.contentEquals(other: TensorType, eqFunction: (T, T) -> Boolean): Boolean + //https://pytorch.org/docs/stable/generated/torch.full.html public fun full(value: T, shape: IntArray): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 5a0fc6c75..ca9168c91 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -5,6 +5,7 @@ import space.kscience.kmath.nd.* import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.TensorStrides import space.kscience.kmath.tensors.TensorStructure +import kotlin.math.atanh public open class BufferedTensor( diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt index 8a579b7da..1eb4c3b63 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt @@ -7,77 +7,40 @@ public class DoubleAnalyticTensorAlgebra: AnalyticTensorAlgebra, DoubleOrderedTensorAlgebra() { - override fun DoubleTensor.exp(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.exp(): DoubleTensor = this.map(::exp) - override fun DoubleTensor.log(): DoubleTensor { - TODO("Not yet implemented") - } + // todo log with other base???? + override fun DoubleTensor.log(): DoubleTensor = this.map(::ln) - override fun DoubleTensor.sqrt(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.sqrt(): DoubleTensor = this.map(::sqrt) - override fun DoubleTensor.cos(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.cos(): DoubleTensor = this.map(::cos) - override fun DoubleTensor.acos(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.acos(): DoubleTensor = this.map(::acos) - override fun DoubleTensor.cosh(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.cosh(): DoubleTensor = this.map(::cosh) - override fun DoubleTensor.acosh(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.acosh(): DoubleTensor = this.map(::acosh) - override fun DoubleTensor.sin(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.sin(): DoubleTensor = this.map(::sin) - override fun DoubleTensor.asin(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.asin(): DoubleTensor = this.map(::asin) - override fun DoubleTensor.sinh(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.sinh(): DoubleTensor = this.map(::sinh) - override fun DoubleTensor.asinh(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.asinh(): DoubleTensor = this.map(::asinh) - override fun DoubleTensor.tan(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.tan(): DoubleTensor = this.map(::tan) - override fun DoubleTensor.atan(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.atan(): DoubleTensor = this.map(::atan) - override fun DoubleTensor.tanh(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.tanh(): DoubleTensor = this.map(::tanh) - override fun DoubleTensor.atanh(): DoubleTensor { - return DoubleTensor( - this.shape, - this.buffer.array().map(::atanh).toDoubleArray(), - this.bufferStart - ) - } + override fun DoubleTensor.atanh(): DoubleTensor = this.map(::atanh) - override fun DoubleTensor.ceil(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.ceil(): DoubleTensor = this.map(::ceil) - override fun DoubleTensor.floor(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.floor(): DoubleTensor = this.map(::floor) override fun DoubleTensor.clamp(min: Double, max: Double): DoubleTensor { TODO("Not yet implemented") diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 8a16dc3ed..e0abc49b7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.LinearOpsTensorAlgebra +import kotlin.math.sqrt public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -10,47 +11,47 @@ public class DoubleLinearOpsTensorAlgebra : TODO("Not yet implemented") } - override fun DoubleTensor.lu(): Pair { + override fun DoubleTensor.lu(tol: Double): Pair { - // todo checks + checkSquareMatrix(shape) - val luTensor = this.copy() + val luTensor = copy() - val n = this.shape.size - val m = this.shape.last() - val pivotsShape = IntArray(n - 1) { i -> this.shape[i] } + val n = shape.size + val m = shape.last() + val pivotsShape = IntArray(n - 1) { i -> shape[i] } val pivotsTensor = IntTensor( pivotsShape, - IntArray(pivotsShape.reduce(Int::times)) { 0 } //todo default??? + IntArray(pivotsShape.reduce(Int::times)) { 0 } ) for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())){ for (row in 0 until m) pivots[row] = row for (i in 0 until m) { - var maxA = -1.0 - var iMax = i + var maxVal = -1.0 + var maxInd = i for (k in i until m) { val absA = kotlin.math.abs(lu[k, i]) - if (absA > maxA) { - maxA = absA - iMax = k + if (absA > maxVal) { + maxVal = absA + maxInd = k } } //todo check singularity - if (iMax != i) { + if (maxInd != i) { val j = pivots[i] - pivots[i] = pivots[iMax] - pivots[iMax] = j + pivots[i] = pivots[maxInd] + pivots[maxInd] = j for (k in 0 until m) { val tmp = lu[i, k] - lu[i, k] = lu[iMax, k] - lu[iMax, k] = tmp + lu[i, k] = lu[maxInd, k] + lu[maxInd, k] = tmp } } @@ -71,6 +72,9 @@ public class DoubleLinearOpsTensorAlgebra : override fun luPivot(luTensor: DoubleTensor, pivotsTensor: IntTensor): Triple { //todo checks + checkSquareMatrix(luTensor.shape) + check(luTensor.shape.dropLast(1).toIntArray() contentEquals pivotsTensor.shape) { "Bed shapes (("} //todo rewrite + val n = luTensor.shape.last() val pTensor = luTensor.zeroesLike() for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.vectorSequence())){ @@ -104,7 +108,30 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.cholesky(): DoubleTensor { - TODO("Not yet implemented") + // todo checks + checkSquareMatrix(shape) + + val n = shape.last() + val lTensor = zeroesLike() + + for ((a, l) in this.matrixSequence().zip(lTensor.matrixSequence())) { + for (i in 0 until n) { + for (j in 0 until i) { + var h = a[i, j] + for (k in 0 until j) { + h -= l[i, k] * l[j, k] + } + l[i, j] = h / l[j, j] + } + var h = a[i, i] + for (j in 0 until i) { + h -= l[i, j] * l[i, j] + } + l[i, i] = sqrt(h) + } + } + + return lTensor } override fun DoubleTensor.qr(): DoubleTensor { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 875f21687..daa8b6d74 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra - +import kotlin.math.abs public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { @@ -277,6 +277,43 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Double): DoubleTensor { + return DoubleTensor( + this.shape, + this.buffer.array().map { transform(it) }.toDoubleArray(), + this.bufferStart + ) + } + + public fun DoubleTensor.contentEquals(other: DoubleTensor, delta: Double = 1e-5): Boolean { + return this.contentEquals(other) { x, y -> abs(x - y) < delta } + } + + public fun DoubleTensor.eq(other: DoubleTensor, delta: Double = 1e-5): Boolean { + return this.eq(other) { x, y -> abs(x - y) < delta } + } + + override fun DoubleTensor.contentEquals(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { + if (!(this.shape contentEquals other.shape)){ + return false + } + return this.eq(other, eqFunction) + } + + override fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { + // todo broadcasting checking + val n = this.strides.linearSize + if (n != other.strides.linearSize){ + return false + } + for (i in 0 until n){ + if (!eqFunction(this.buffer[this.bufferStart + i], other.buffer[other.bufferStart + i])) { + return false + } + } + return true + } + } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index f1ae89490..ec7a123a9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -64,4 +64,16 @@ internal inline fun , internal inline fun , TorchTensorAlgebraType : TensorAlgebra> TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = - check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) \ No newline at end of file + check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkSquareMatrix(shape: IntArray): Unit { + val n = shape.size + check(n >= 2) { + "Expected tensor with 2 or more dimensions, got size $n instead" + } + check(shape[n - 1] == shape[n - 2]) { + "Tensor must be batches of square matrices, but they are ${shape[n - 1]} by ${shape[n - 1]} matrices" + } +} From df402086daeb0b15c78a1a0d987cd46dd5122801 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sun, 21 Mar 2021 19:08:30 +0300 Subject: [PATCH 050/211] init test for analytic algebra --- .../core/TestDoubleAnalyticTensorAlgebra.kt | 35 +++++++++++++++++++ .../tensors/core/TestDoubleTensorAlgebra.kt | 4 +++ 2 files changed, 39 insertions(+) create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt new file mode 100644 index 000000000..8028ce175 --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -0,0 +1,35 @@ +package space.kscience.kmath.tensors.core + +import kotlin.math.abs +import kotlin.math.exp +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class TestDoubleAnalyticTensorAlgebra { + + val shape = intArrayOf(2, 1, 3, 2) + val buffer = doubleArrayOf(27.1, 20.0, 19.84, 23.123, 0.0, 1.0, 3.23, 133.7, 25.3, 100.3, 11.0, 12.012) + val tensor = DoubleTensor(shape, buffer) + + fun DoubleArray.fmap(transform: (Double) -> Double): DoubleArray { + return this.map(transform).toDoubleArray() + } + + fun DoubleArray.deltaEqual(other: DoubleArray, delta: Double = 1e-5): Boolean { + for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) { + if (abs(elem1 - elem2) > delta) { + return false + } + } + return true + } + + @Test + fun testExp() = DoubleAnalyticTensorAlgebra { + tensor.exp().let { + assertTrue { shape contentEquals it.shape } + assertTrue { buffer.fmap(::exp).deltaEqual(it.buffer.array())} + } + } +} \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index ddfba0d59..06aa3ebf7 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -79,4 +79,8 @@ class TestDoubleTensorAlgebra { assertTrue(expected.buffer.array() contentEquals assignResult.buffer.array()) } + @Test + fun testContentEqual() = DoubleTensorAlgebra { + //TODO() + } } \ No newline at end of file From 0365d41f317af785f4963611f4c3899171618720 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sun, 21 Mar 2021 17:57:19 +0000 Subject: [PATCH 051/211] Merged PR --- kmath-core/api/kmath-core.api | 485 ++++++++++++++++++ .../kscience/kmath/tensors/TensorAlgebra.kt | 5 - .../kmath/tensors/core/DoubleTensorAlgebra.kt | 10 +- 3 files changed, 490 insertions(+), 10 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 04325379e..70bec600d 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -972,6 +972,30 @@ public final class space/kscience/kmath/nd/GroupND$DefaultImpls { public static fun unaryPlus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } +public abstract interface class space/kscience/kmath/nd/MutableStructure1D : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/Structure1D, space/kscience/kmath/structures/MutableBuffer { + public abstract fun set ([ILjava/lang/Object;)V +} + +public final class space/kscience/kmath/nd/MutableStructure1D$DefaultImpls { + public static fun get (Lspace/kscience/kmath/nd/MutableStructure1D;[I)Ljava/lang/Object; + public static fun getDimension (Lspace/kscience/kmath/nd/MutableStructure1D;)I + public static fun iterator (Lspace/kscience/kmath/nd/MutableStructure1D;)Ljava/util/Iterator; + public static fun set (Lspace/kscience/kmath/nd/MutableStructure1D;[ILjava/lang/Object;)V +} + +public abstract interface class space/kscience/kmath/nd/MutableStructure2D : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/Structure2D { + public abstract fun set (IILjava/lang/Object;)V +} + +public final class space/kscience/kmath/nd/MutableStructure2D$DefaultImpls { + public static fun elements (Lspace/kscience/kmath/nd/MutableStructure2D;)Lkotlin/sequences/Sequence; + public static fun get (Lspace/kscience/kmath/nd/MutableStructure2D;[I)Ljava/lang/Object; + public static fun getColumns (Lspace/kscience/kmath/nd/MutableStructure2D;)Ljava/util/List; + public static fun getDimension (Lspace/kscience/kmath/nd/MutableStructure2D;)I + public static fun getRows (Lspace/kscience/kmath/nd/MutableStructure2D;)Ljava/util/List; + public static fun getShape (Lspace/kscience/kmath/nd/MutableStructure2D;)[I +} + public abstract interface class space/kscience/kmath/nd/MutableStructureND : space/kscience/kmath/nd/StructureND { public abstract fun set ([ILjava/lang/Object;)V } @@ -1072,6 +1096,7 @@ public final class space/kscience/kmath/nd/Structure1D$DefaultImpls { } public final class space/kscience/kmath/nd/Structure1DKt { + public static final fun as1D (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructure1D; public static final fun as1D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure1D; public static final fun asND (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/nd/Structure1D; } @@ -1101,6 +1126,7 @@ public final class space/kscience/kmath/nd/Structure2D$DefaultImpls { } public final class space/kscience/kmath/nd/Structure2DKt { + public static final fun as2D (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructure2D; public static final fun as2D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure2D; } @@ -2582,3 +2608,462 @@ public final class space/kscience/kmath/structures/VirtualBuffer : space/kscienc public fun iterator ()Ljava/util/Iterator; } +public abstract interface class space/kscience/kmath/tensors/AnalyticTensorAlgebra : space/kscience/kmath/tensors/OrderedTensorAlgebra, space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { + public abstract fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun acosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun asin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun asinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun atan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun atanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun ceil (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun clamp (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun erf (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun erfc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun erfinv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun exp (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun floor (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun heaviside (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun histc (Lspace/kscience/kmath/nd/MutableStructureND;ILjava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun igamma (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun igammac (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun lerp (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun lgamma (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun log (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun logit (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun mvlgamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun polygamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun pow (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun quantile (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun round (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun sigmoid (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun sin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun sinc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun sinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun sqrt (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun std (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun tan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun tanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun trapz (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; +} + +public abstract interface class space/kscience/kmath/tensors/ComplexTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { + public abstract fun angle (Lspace/kscience/kmath/tensors/ComplexTensorStructure;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun bartlettWindow (IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun blackmanWindow (IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cartesianEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/tensors/ComplexTensorStructure; + public abstract fun hammingWindow (IZLjava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun inverseShortTimeFourierTransform (Lspace/kscience/kmath/tensors/ComplexTensorStructure;IIILspace/kscience/kmath/nd/MutableStructureND;ZZZI)V + public abstract fun kaiserWindow (IZLjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun polarEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/tensors/ComplexTensorStructure; + public abstract fun shortTimeFourierTransform (Lspace/kscience/kmath/tensors/ComplexTensorStructure;IIILspace/kscience/kmath/nd/MutableStructureND;ZZ)V + public abstract fun viewAsComplex (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/tensors/ComplexTensorStructure; +} + +public abstract interface class space/kscience/kmath/tensors/ComplexTensorStructure : space/kscience/kmath/nd/MutableStructureND { + public abstract fun imaginaryPart ()Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun realPart ()Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun viewAsReal ()Lspace/kscience/kmath/nd/MutableStructureND; +} + +public final class space/kscience/kmath/tensors/ComplexTensorStructure$DefaultImpls { + public static fun getDimension (Lspace/kscience/kmath/tensors/ComplexTensorStructure;)I +} + +public abstract interface class space/kscience/kmath/tensors/LinearOpsTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { + public abstract fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun lu (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lkotlin/Pair; + public abstract fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; + public abstract fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; + public abstract fun symEig (Lspace/kscience/kmath/nd/MutableStructureND;Z)Lkotlin/Pair; +} + +public final class space/kscience/kmath/tensors/LinearOpsTensorAlgebra$DefaultImpls { + public static synthetic fun symEig$default (Lspace/kscience/kmath/tensors/LinearOpsTensorAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;ZILjava/lang/Object;)Lkotlin/Pair; +} + +public abstract interface class space/kscience/kmath/tensors/OrderedTensorAlgebra : space/kscience/kmath/tensors/TensorAlgebra { + public abstract fun cummax (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cummin (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun max (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun maximum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public abstract fun median (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun min (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun minimum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public abstract fun sort (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; +} + +public abstract interface class space/kscience/kmath/tensors/ReduceOpsTensorAlgebra : space/kscience/kmath/tensors/TensorAlgebra { + public abstract fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; +} + +public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { + public abstract fun abs (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cat (Ljava/util/List;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cumprod (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun flatten (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun fullLike (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public abstract fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public abstract fun ones ([I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun onesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public abstract fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public abstract fun prod (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun square (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun squeeze (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun sum (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun times (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public abstract fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public abstract fun transpose (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun zeroesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun zeros ([I)Lspace/kscience/kmath/nd/MutableStructureND; +} + +public final class space/kscience/kmath/tensors/TensorAlgebra$DefaultImpls { + public static synthetic fun diagonalEmbedding$default (Lspace/kscience/kmath/tensors/TensorAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;IIIILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; +} + +public abstract interface class space/kscience/kmath/tensors/TensorPartialDivisionAlgebra : space/kscience/kmath/tensors/TensorAlgebra { + public abstract fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public abstract fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public abstract fun mean (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun variance (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; +} + +public final class space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra { + public fun ()V + public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun div (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun minus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun plus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun times (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun timesAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V +} + +public final class space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebraKt { + public static final fun BroadcastDoubleTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public class space/kscience/kmath/tensors/core/BufferedTensor : space/kscience/kmath/nd/MutableStructureND { + public fun ([ILspace/kscience/kmath/structures/MutableBuffer;I)V + public fun elements ()Lkotlin/sequences/Sequence; + public fun equals (Ljava/lang/Object;)Z + public final fun forEachMatrix (Lkotlin/jvm/functions/Function1;)V + public final fun forEachVector (Lkotlin/jvm/functions/Function1;)V + public fun get ([I)Ljava/lang/Object; + public final fun getBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun getDimension ()I + public final fun getLinearStructure ()Lspace/kscience/kmath/tensors/core/TensorLinearStructure; + public final fun getNumel ()I + public fun getShape ()[I + public fun hashCode ()I + public final fun matrixSequence ()Lkotlin/sequences/Sequence; + public fun set ([ILjava/lang/Object;)V + public final fun vectorSequence ()Lkotlin/sequences/Sequence; +} + +public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra : space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra, space/kscience/kmath/tensors/AnalyticTensorAlgebra { + public fun ()V + public synthetic fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun acos (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun acosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun acosh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun asin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun asin (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun asinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun asinh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun atan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun atan (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun atanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun atanh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun ceil (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun ceil (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun clamp (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun clamp (Lspace/kscience/kmath/tensors/core/DoubleTensor;DD)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun cos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cos (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun cosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cosh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun erf (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun erf (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun erfc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun erfc (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun erfinv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun erfinv (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun exp (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun exp (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun floor (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun floor (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun heaviside (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun heaviside (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun histc (Lspace/kscience/kmath/nd/MutableStructureND;ILjava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun histc (Lspace/kscience/kmath/tensors/core/DoubleTensor;IDD)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun igamma (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun igamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun igammac (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun igammac (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun lerp (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun lerp (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun lgamma (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun lgamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun log (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun log (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun logit (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun logit (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun mvlgamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun mvlgamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun polygamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun polygamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun pow (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun pow (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun quantile (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun quantile (Lspace/kscience/kmath/tensors/core/DoubleTensor;DIZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun round (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun round (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun sigmoid (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sigmoid (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun sin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sin (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun sinc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sinc (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun sinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sinh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun sqrt (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sqrt (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun std (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun std (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun tan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun tan (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun tanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun tanh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun trapz (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun trapz (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; +} + +public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebraKt { + public static final fun DoubleAnalyticTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/LinearOpsTensorAlgebra { + public fun ()V + public synthetic fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cholesky (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun inv (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun lu (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lkotlin/Pair; + public fun lu (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lkotlin/Pair; + public synthetic fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; + public fun luPivot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/IntTensor;)Lkotlin/Triple; + public synthetic fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun qr (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; + public fun svd (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Triple; + public synthetic fun symEig (Lspace/kscience/kmath/nd/MutableStructureND;Z)Lkotlin/Pair; + public fun symEig (Lspace/kscience/kmath/tensors/core/DoubleTensor;Z)Lkotlin/Pair; +} + +public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebraKt { + public static final fun DoubleLinearOpsTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public class space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/OrderedTensorAlgebra { + public fun ()V + public synthetic fun cummax (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cummax (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun cummin (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cummin (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun max (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun max (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun maximum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun maximum (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun median (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun median (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun min (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun min (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun minimum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun minimum (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun sort (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sort (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; +} + +public final class space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebraKt { + public static final fun DoubleOrderedTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/ReduceOpsTensorAlgebra { + public fun ()V + public synthetic fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; + public fun value (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Ljava/lang/Double; +} + +public final class space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebraKt { + public static final fun DoubleReduceOpsTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/tensors/core/DoubleTensor : space/kscience/kmath/tensors/core/BufferedTensor { +} + +public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { + public fun ()V + public synthetic fun abs (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun abs (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun cat (Ljava/util/List;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cat (Ljava/util/List;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z + public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z + public static synthetic fun contentEquals$default (Lspace/kscience/kmath/tensors/core/DoubleTensorAlgebra;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;DILjava/lang/Object;)Z + public synthetic fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun copy (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun cumprod (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cumprod (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cumsum (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun det (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; + public fun diagonalEmbedding (Lspace/kscience/kmath/tensors/core/DoubleTensor;III)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun div (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun div (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public synthetic fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V + public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun dot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z + public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z + public static synthetic fun eq$default (Lspace/kscience/kmath/tensors/core/DoubleTensorAlgebra;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;DILjava/lang/Object;)Z + public synthetic fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun flatten (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; + public fun flatten (Lspace/kscience/kmath/tensors/core/DoubleTensor;II)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun fromArray ([I[D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun full (D[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun fullLike (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun fullLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun get (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun map (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun mean (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun mean (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun minus (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun minus (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun minus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V + public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun ones ([I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun ones ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun onesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun onesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun plus (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun plus (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun plus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V + public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun prod (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun prod (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun square (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun square (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun squeeze (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun squeeze (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun sum (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sum (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun times (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun times (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun times (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public synthetic fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun timesAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V + public fun timesAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun transpose (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; + public fun transpose (Lspace/kscience/kmath/tensors/core/DoubleTensor;II)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun unaryMinus (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun variance (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun variance (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun view (Lspace/kscience/kmath/tensors/core/DoubleTensor;[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun viewAs (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun zeroesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun zeroesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun zeros ([I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun zeros ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; +} + +public final class space/kscience/kmath/tensors/core/DoubleTensorAlgebraKt { + public static final fun DoubleTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/tensors/core/FloatTensor : space/kscience/kmath/tensors/core/BufferedTensor { +} + +public final class space/kscience/kmath/tensors/core/IntTensor : space/kscience/kmath/tensors/core/BufferedTensor { +} + +public final class space/kscience/kmath/tensors/core/LongTensor : space/kscience/kmath/tensors/core/BufferedTensor { +} + +public final class space/kscience/kmath/tensors/core/TensorLinearStructure { + public fun ([I)V + public final fun getShape ()[I + public final fun getSize ()I + public final fun getStrides ()[I + public final fun index (I)[I + public final fun indices ()Lkotlin/sequences/Sequence; + public final fun offset ([I)I + public final fun stepIndex ([I)[I +} + diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 8be0dc149..e41b7546c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -3,11 +3,6 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { - public fun TensorType.map(transform: (T) -> T): TensorType - - public fun TensorType.eq(other: TensorType, eqFunction: (T, T) -> Boolean): Boolean - public fun TensorType.contentEquals(other: TensorType, eqFunction: (T, T) -> Boolean): Boolean - //https://pytorch.org/docs/stable/generated/torch.full.html public fun full(value: T, shape: IntArray): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 57339adfa..67b50970b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -277,7 +277,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Double): DoubleTensor { + public fun DoubleTensor.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( this.shape, this.buffer.array().map { transform(it) }.toDoubleArray(), @@ -293,17 +293,17 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra abs(x - y) < delta } } - override fun DoubleTensor.contentEquals(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { + public fun DoubleTensor.contentEquals(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { if (!(this.shape contentEquals other.shape)){ return false } return this.eq(other, eqFunction) } - override fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { + public fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { // todo broadcasting checking - val n = this.strides.linearSize - if (n != other.strides.linearSize){ + val n = this.linearStructure.size + if (n != other.linearStructure.size){ return false } for (i in 0 until n){ From 2d2c4bd4744af9f3d841571d213170b1d661fa8f Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Tue, 23 Mar 2021 14:53:54 +0300 Subject: [PATCH 052/211] add broadcast of all dims except the last 2, add tensors dot, fix bug in function times --- .../core/BroadcastDoubleTensorAlgebra.kt | 59 +++++++++++++- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 80 ++++++++++++++++++- .../kmath/tensors/core/TestBroadcasting.kt | 30 +++++++ .../tensors/core/TestDoubleTensorAlgebra.kt | 14 ++++ 4 files changed, 180 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index 4bfbe5863..425178fc1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -85,7 +85,6 @@ public inline fun BroadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorA internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { - println(shapes) var totalDim = 0 for (shape in shapes) { totalDim = max(totalDim, shape.size) @@ -179,5 +178,63 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List { + var onlyTwoDims = true + for (tensor in tensors) { + if (tensor.shape.size < 2) { + throw RuntimeException("Tensors must have at least 2 dimensions") + } + if (tensor.shape.size != 2) { + onlyTwoDims = false + } + } + + if (onlyTwoDims) { + return tensors.asList() + } + + val totalShape = broadcastShapes(*(tensors.map { it.shape.sliceArray(0..it.shape.size - 3) }).toTypedArray()) + val n = totalShape.reduce { acc, i -> acc * i } + + val res = ArrayList(0) + for (tensor in tensors) { + val matrixShape = tensor.shape.sliceArray(tensor.shape.size - 2 until tensor.shape.size).copyOf() + val matrixSize = matrixShape[0] * matrixShape[1] + val matrix = DoubleTensor(matrixShape, DoubleArray(matrixSize)) + + val outerTensor = DoubleTensor(totalShape, DoubleArray(n)) + val resTensor = DoubleTensor(totalShape + matrixShape, DoubleArray(n * matrixSize)) + + for (linearIndex in 0 until n) { + val totalMultiIndex = outerTensor.linearStructure.index(linearIndex) + var curMultiIndex = tensor.shape.sliceArray(0..tensor.shape.size - 3).copyOf() + curMultiIndex = IntArray(totalMultiIndex.size - curMultiIndex.size) {1} + curMultiIndex + + val newTensor = DoubleTensor(curMultiIndex + matrixShape, tensor.buffer.array()) + + for (i in curMultiIndex.indices) { + if (curMultiIndex[i] != 1) { + curMultiIndex[i] = totalMultiIndex[i] + } else { + curMultiIndex[i] = 0 + } + } + + for (i in 0 until matrixSize) { + val curLinearIndex = newTensor.linearStructure.offset(curMultiIndex + + matrix.linearStructure.index(i)) + val newLinearIndex = resTensor.linearStructure.offset(totalMultiIndex + + matrix.linearStructure.index(i)) + + resTensor.buffer.array()[resTensor.bufferStart + newLinearIndex] = + newTensor.buffer.array()[newTensor.bufferStart + curLinearIndex] + } + } + res.add(resTensor) + } + return res } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 67b50970b..9cdc6c130 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -132,7 +132,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - this.buffer.array()[other.bufferStart + i] * + this.buffer.array()[this.bufferStart + i] * other.buffer.array()[other.bufferStart + i] } return DoubleTensor(this.shape, resBuffer) @@ -241,8 +241,84 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra 2 || other.shape.size > 2) { + throw RuntimeException("Both tensors must have a maximum of 2 dimensions") + } + + if (this.shape[1] != other.shape[0]) { + throw RuntimeException("Tensors dot operation dimension mismatch: " + + "(${this.shape[0]}, ${this.shape[1]}) x (${other.shape[0]}, ${other.shape[1]})") + } + + val l = this.shape[0] + val m = this.shape[1] + val n = other.shape[1] + + val res = DoubleTensor(intArrayOf(l, n), DoubleArray(l * n)) + + for (i in 0 until l) { + for (j in 0 until n) { + var curr = 0.0 + for (k in 0 until m) { + val ik = this.linearStructure.offset(intArrayOf(i, k)) + val kj = other.linearStructure.offset(intArrayOf(k, j)) + curr += this.buffer.array()[ik] * other.buffer.array()[kj] + } + val linearIndex = res.linearStructure.offset(intArrayOf(i, j)) + res.buffer.array()[linearIndex] = curr + } + } + return res + } + override fun DoubleTensor.dot(other: DoubleTensor): DoubleTensor { - TODO("Alya") + if (this.shape.size == 1 && other.shape.size == 1) { + return DoubleTensor(intArrayOf(1), doubleArrayOf(this.times(other).buffer.array().sum())) + } + + var newThis = this.copy() + var newOther = other.copy() + if (this.shape.size == 1) { + newThis = this.view(intArrayOf(1) + this.shape) + } + if (other.shape.size == 1) { + newOther = other.view(other.shape + intArrayOf(1) ) + } + + val broadcastTensors = broadcastOuterTensors(newThis, newOther) + newThis = broadcastTensors[0] + newOther = broadcastTensors[1] + + val l = newThis.shape[newThis.shape.size - 2] + val m1= newThis.shape[newThis.shape.size - 1] + val m2 = newOther.shape[newOther.shape.size - 2] + val n = newOther.shape[newOther.shape.size - 1] + if (m1 != m2) { + throw RuntimeException("Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)") + } + val m = m1 + + var resShape = newThis.shape.sliceArray(0..(newThis.shape.size - 2)) + intArrayOf(newOther.shape.last()) + val resSize = resShape.reduce { acc, i -> acc * i } + val resTensor = DoubleTensor(resShape, DoubleArray(resSize)) + + for ((res, ab) in resTensor.matrixSequence().zip(newThis.matrixSequence().zip(newOther.matrixSequence()))) { + val a = ab.first + val b = ab.second + + for (i in 0 until l) { + for (j in 0 until n) { + var curr = 0.0 + for (k in 0 until m) { + curr += a[i, k] * b[k, j] + } + res[i, j] = curr + } + } + } + + return resTensor } override fun diagonalEmbedding(diagonalEntries: DoubleTensor, offset: Int, dim1: Int, dim2: Int): DoubleTensor { diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 73e3993a1..41c9b72f7 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -47,6 +47,36 @@ class TestBroadcasting { assertTrue(res[2].buffer.array() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) } + @Test + fun broadcastOuterTensors() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + + val res = broadcastOuterTensors(tensor1, tensor2, tensor3) + + assertTrue(res[0].shape contentEquals intArrayOf(1, 2, 3)) + assertTrue(res[1].shape contentEquals intArrayOf(1, 1, 3)) + assertTrue(res[2].shape contentEquals intArrayOf(1, 1, 1)) + + assertTrue(res[0].buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0)) + assertTrue(res[2].buffer.array() contentEquals doubleArrayOf(500.0)) + } + + @Test + fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) {0.0}) + val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) {0.0}) + val tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0)) + + val res = broadcastOuterTensors(tensor1, tensor2, tensor3) + + assertTrue(res[0].shape contentEquals intArrayOf(4, 2, 5, 3, 2, 3)) + assertTrue(res[1].shape contentEquals intArrayOf(4, 2, 5, 3, 3, 3)) + assertTrue(res[2].shape contentEquals intArrayOf(4, 2, 5, 3, 1, 1)) + } + @Test fun minusTensor() = BroadcastDoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 06aa3ebf7..aa3c14412 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -79,6 +79,20 @@ class TestDoubleTensorAlgebra { assertTrue(expected.buffer.array() contentEquals assignResult.buffer.array()) } + @Test + fun dot() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) + val res12 = tensor1.dot(tensor2) + + assertTrue(res12.buffer.array() contentEquals doubleArrayOf(140.0, 320.0)) + assertTrue(res12.shape contentEquals intArrayOf(2, 1)) + + val tensor4 = fromArray(intArrayOf(10, 3, 4), DoubleArray(10 * 3 * 4) {0.0}) + val tensor5 = fromArray(intArrayOf(10, 4, 5), DoubleArray(10 * 4 * 5) {0.0}) + assertTrue(tensor4.dot(tensor5).shape contentEquals intArrayOf(10, 3, 5)) + } + @Test fun testContentEqual() = DoubleTensorAlgebra { //TODO() From 078686a04660e78b9929d2ed9a3c61f3fa888e62 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Tue, 23 Mar 2021 15:59:55 +0300 Subject: [PATCH 053/211] hotfix sequence --- .../space/kscience/kmath/tensors/core/BufferedTensor.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 4f5e1f9f0..160c61260 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -34,7 +34,8 @@ public open class BufferedTensor( public fun vectorSequence(): Sequence> = sequence { check(shape.size >= 1) {"todo"} - val vectorOffset = linearStructure.strides[0] + val n = shape.size + val vectorOffset = shape[n - 1] val vectorShape = intArrayOf(shape.last()) for (offset in 0 until numel step vectorOffset) { val vector = BufferedTensor(vectorShape, buffer, offset).as1D() @@ -44,8 +45,9 @@ public open class BufferedTensor( public fun matrixSequence(): Sequence> = sequence { check(shape.size >= 2) {"todo"} - val matrixOffset = linearStructure.strides[1] - val matrixShape = intArrayOf(shape[shape.size - 2], shape.last()) //todo better way? + val n = shape.size + val matrixOffset = shape[n - 1] * shape[n - 2] + val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) //todo better way? for (offset in 0 until numel step matrixOffset) { val matrix = BufferedTensor(matrixShape, buffer, offset).as2D() yield(matrix) From e01ca38fb3a7b05037582f561298928be552100e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 23 Mar 2021 13:51:52 +0000 Subject: [PATCH 054/211] Tasks for Andrei and Alya --- .../kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 8 ++++---- .../kscience/kmath/tensors/core/DoubleTensorAlgebra.kt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index e0abc49b7..8a16a991d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -8,7 +8,7 @@ public class DoubleLinearOpsTensorAlgebra : DoubleTensorAlgebra() { override fun DoubleTensor.inv(): DoubleTensor { - TODO("Not yet implemented") + TODO("ANDREI") } override fun DoubleTensor.lu(tol: Double): Pair { @@ -135,16 +135,16 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.qr(): DoubleTensor { - TODO("Not yet implemented") + TODO("ANDREI") } override fun DoubleTensor.svd(): Triple { - TODO("Not yet implemented") + TODO("ALYA") } override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { - TODO("Not yet implemented") + TODO("ANDREI") } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 67b50970b..c67687a09 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -262,7 +262,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Date: Wed, 24 Mar 2021 14:00:47 +0300 Subject: [PATCH 055/211] fix --- .../space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt | 2 +- .../kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index c4fa3e0a8..e412af7c6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -14,7 +14,7 @@ public interface LinearOpsTensorAlgebra, Inde public fun TensorType.qr(): TensorType //https://pytorch.org/docs/stable/generated/torch.lu.html - public fun TensorType.lu(tol: T): Pair + public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html public fun luPivot(luTensor: TensorType, pivotsTensor: IndexTensorType): Triple diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index e0abc49b7..d090ce79c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -11,7 +11,7 @@ public class DoubleLinearOpsTensorAlgebra : TODO("Not yet implemented") } - override fun DoubleTensor.lu(tol: Double): Pair { + override fun DoubleTensor.lu(): Pair { checkSquareMatrix(shape) @@ -138,7 +138,6 @@ public class DoubleLinearOpsTensorAlgebra : TODO("Not yet implemented") } - override fun DoubleTensor.svd(): Triple { TODO("Not yet implemented") } From 206bcfc909d56a859ec783a30cc75a8ade178786 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 24 Mar 2021 18:08:36 +0300 Subject: [PATCH 056/211] lu inv and det complete + tests --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 2 +- .../core/DoubleLinearOpsTensorAlgebra.kt | 79 +++++++++++++++++++ .../kmath/tensors/core/DoubleTensorAlgebra.kt | 35 +++++++- .../core/TestDoubleAnalyticTensorAlgebra.kt | 7 +- .../core/TestDoubleLinearOpsAlgebra.kt | 73 +++++++++++++++++ 5 files changed, 187 insertions(+), 9 deletions(-) create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index e412af7c6..f551d524a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -13,7 +13,7 @@ public interface LinearOpsTensorAlgebra, Inde //https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr public fun TensorType.qr(): TensorType - //https://pytorch.org/docs/stable/generated/torch.lu.html + //htt ps://pytorch.org/docs/stable/generated/torch.lu.html public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 7779ad029..c8c4c413f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,5 +1,8 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.nd.Structure1D +import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import kotlin.math.sqrt @@ -20,6 +23,8 @@ public class DoubleLinearOpsTensorAlgebra : val n = shape.size val m = shape.last() val pivotsShape = IntArray(n - 1) { i -> shape[i] } + pivotsShape[n - 2] = m + 1 + val pivotsTensor = IntTensor( pivotsShape, IntArray(pivotsShape.reduce(Int::times)) { 0 } @@ -54,6 +59,8 @@ public class DoubleLinearOpsTensorAlgebra : lu[maxInd, k] = tmp } + pivots[m] += 1 + } for (j in i + 1 until m) { @@ -146,6 +153,78 @@ public class DoubleLinearOpsTensorAlgebra : TODO("ANDREI") } + private fun luMatrixDet(lu: Structure2D, pivots: Structure1D): Double { + val m = lu.shape[0] + val sign = if((pivots[m] - m) % 2 == 0) 1.0 else -1.0 + var det = sign + for (i in 0 until m){ + det *= lu[i, i] + } + return det + } + + public fun DoubleTensor.detLU(): DoubleTensor { + val (luTensor, pivotsTensor) = this.lu() + val n = shape.size + + val detTensorShape = IntArray(n - 1) { i -> shape[i] } + detTensorShape[n - 2] = 1 + val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } + + val detTensor = DoubleTensor( + detTensorShape, + resBuffer + ) + + luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (luMatrix, pivots) -> + resBuffer[index] = luMatrixDet(luMatrix, pivots) + } + + return detTensor + } + + private fun luMatrixInv( + lu: Structure2D, + pivots: Structure1D, + invMatrix : MutableStructure2D + ): Unit { + val m = lu.shape[0] + + for (j in 0 until m) { + for (i in 0 until m) { + if (pivots[i] == j){ + invMatrix[i, j] = 1.0 + } + + for (k in 0 until i){ + invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] + } + } + + for (i in m - 1 downTo 0) { + for (k in i + 1 until m) { + invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] + } + invMatrix[i, j] /= lu[i, i] + } + } + } + + public fun DoubleTensor.invLU(): DoubleTensor { + val (luTensor, pivotsTensor) = this.lu() + val n = shape.size + val invTensor = luTensor.zeroesLike() + + for ( + (luP, invMatrix) in + luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) + ) { + val (lu, pivots) = luP + luMatrixInv(lu, pivots, invMatrix) + } + + return invTensor + } } public inline fun DoubleLinearOpsTensorAlgebra(block: DoubleLinearOpsTensorAlgebra.() -> R): R = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index c67687a09..ff65ca027 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,5 +1,8 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra import kotlin.math.abs @@ -262,7 +265,31 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra shape[i] } + detTensorShape[n - 1] = 1 + val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } + + val detTensor = DoubleTensor( + detTensorShape, + resBuffer + ) + + this.matrixSequence().forEachIndexed{i, matrix -> + // todo need Matrix determinant algo + // todo resBuffer[i] = matrix.det() + } + + + return detTensor + + */ } override fun DoubleTensor.square(): DoubleTensor { @@ -294,7 +321,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Boolean): Boolean { - if (!(this.shape contentEquals other.shape)){ + if (!(this.shape contentEquals other.shape)) { return false } return this.eq(other, eqFunction) @@ -303,10 +330,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Boolean): Boolean { // todo broadcasting checking val n = this.linearStructure.size - if (n != other.linearStructure.size){ + if (n != other.linearStructure.size) { return false } - for (i in 0 until n){ + for (i in 0 until n) { if (!eqFunction(this.buffer[this.bufferStart + i], other.buffer[other.bufferStart + i])) { return false } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 8028ce175..4dcdb7848 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -3,7 +3,6 @@ package space.kscience.kmath.tensors.core import kotlin.math.abs import kotlin.math.exp import kotlin.test.Test -import kotlin.test.assertEquals import kotlin.test.assertTrue class TestDoubleAnalyticTensorAlgebra { @@ -16,9 +15,9 @@ class TestDoubleAnalyticTensorAlgebra { return this.map(transform).toDoubleArray() } - fun DoubleArray.deltaEqual(other: DoubleArray, delta: Double = 1e-5): Boolean { + fun DoubleArray.epsEqual(other: DoubleArray, eps: Double = 1e-5): Boolean { for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) { - if (abs(elem1 - elem2) > delta) { + if (abs(elem1 - elem2) > eps) { return false } } @@ -29,7 +28,7 @@ class TestDoubleAnalyticTensorAlgebra { fun testExp() = DoubleAnalyticTensorAlgebra { tensor.exp().let { assertTrue { shape contentEquals it.shape } - assertTrue { buffer.fmap(::exp).deltaEqual(it.buffer.array())} + assertTrue { buffer.fmap(::exp).epsEqual(it.buffer.array())} } } } \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt new file mode 100644 index 000000000..2da79382f --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -0,0 +1,73 @@ +package space.kscience.kmath.tensors.core + +import kotlin.math.abs +import kotlin.math.exp +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class TestDoubleLinearOpsTensorAlgebra { + + private val eps = 1e-5 + + private fun Double.epsEqual(other: Double): Boolean { + return abs(this - other) < eps + } + + fun DoubleArray.epsEqual(other: DoubleArray, eps: Double = 1e-5): Boolean { + for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) { + if (abs(elem1 - elem2) > eps) { + return false + } + } + return true + } + + @Test + fun testDetLU() = DoubleLinearOpsTensorAlgebra { + val tensor = fromArray( + intArrayOf(2, 2, 2), + doubleArrayOf( + 1.0, 3.0, + 1.0, 2.0, + 1.5, 1.0, + 10.0, 2.0 + ) + ) + + val expectedShape = intArrayOf(2, 1) + val expectedBuffer = doubleArrayOf( + -1.0, + -7.0 + ) + val detTensor = tensor.detLU() + + assertTrue { detTensor.shape contentEquals expectedShape } + assertTrue { detTensor.buffer.array().epsEqual(expectedBuffer) } + } + + @Test + fun testInvLU() = DoubleLinearOpsTensorAlgebra { + val tensor = fromArray( + intArrayOf(2, 2, 2), + doubleArrayOf( + 1.0, 0.0, + 0.0, 2.0, + 1.0, 1.0, + 1.0, 0.0 + ) + ) + + val expectedShape = intArrayOf(2, 2, 2) + val expectedBuffer = doubleArrayOf( + 1.0, 0.0, + 0.0, 0.5, + 0.0, 1.0, + 1.0, -1.0 + ) + + val invTensor = tensor.invLU() + assertTrue { invTensor.shape contentEquals expectedShape } + assertTrue { invTensor.buffer.array().epsEqual(expectedBuffer) } + } +} From ab8137000146c52f10b3213c960b03917a0ada4f Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 24 Mar 2021 18:42:41 +0300 Subject: [PATCH 057/211] fixes --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 2 +- .../core/DoubleLinearOpsTensorAlgebra.kt | 22 +++++++------------ 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index f551d524a..e412af7c6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -13,7 +13,7 @@ public interface LinearOpsTensorAlgebra, Inde //https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr public fun TensorType.qr(): TensorType - //htt ps://pytorch.org/docs/stable/generated/torch.lu.html + //https://pytorch.org/docs/stable/generated/torch.lu.html public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index c8c4c413f..0b9d824f0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -10,9 +10,9 @@ public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, DoubleTensorAlgebra() { - override fun DoubleTensor.inv(): DoubleTensor { - TODO("ANDREI") - } + override fun DoubleTensor.inv(): DoubleTensor = invLU() + + override fun DoubleTensor.det(): DoubleTensor = detLU() override fun DoubleTensor.lu(): Pair { @@ -156,15 +156,11 @@ public class DoubleLinearOpsTensorAlgebra : private fun luMatrixDet(lu: Structure2D, pivots: Structure1D): Double { val m = lu.shape[0] val sign = if((pivots[m] - m) % 2 == 0) 1.0 else -1.0 - var det = sign - for (i in 0 until m){ - det *= lu[i, i] - } - return det + return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } } public fun DoubleTensor.detLU(): DoubleTensor { - val (luTensor, pivotsTensor) = this.lu() + val (luTensor, pivotsTensor) = lu() val n = shape.size val detTensorShape = IntArray(n - 1) { i -> shape[i] } @@ -211,14 +207,12 @@ public class DoubleLinearOpsTensorAlgebra : } public fun DoubleTensor.invLU(): DoubleTensor { - val (luTensor, pivotsTensor) = this.lu() + val (luTensor, pivotsTensor) = lu() val n = shape.size val invTensor = luTensor.zeroesLike() - for ( - (luP, invMatrix) in - luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) - ) { + val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) + for ((luP, invMatrix) in seq) { val (lu, pivots) = luP luMatrixInv(lu, pivots, invMatrix) } From a4aa4b80d27cecef092a1a411163e24ff70d08ec Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 24 Mar 2021 15:51:58 +0000 Subject: [PATCH 058/211] Updated API --- kmath-core/api/kmath-core.api | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 70bec600d..295df69e3 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2674,7 +2674,7 @@ public final class space/kscience/kmath/tensors/ComplexTensorStructure$DefaultIm public abstract interface class space/kscience/kmath/tensors/LinearOpsTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { public abstract fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun lu (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lkotlin/Pair; + public abstract fun lu (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; public abstract fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; public abstract fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; @@ -2884,10 +2884,14 @@ public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebr public fun ()V public synthetic fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun cholesky (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun det (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun detLU (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun inv (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun lu (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lkotlin/Pair; - public fun lu (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lkotlin/Pair; + public final fun invLU (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun lu (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; + public fun lu (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Pair; public synthetic fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; public fun luPivot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/IntTensor;)Lkotlin/Triple; public synthetic fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; From f70f60c0e8d5a3c830bc1ce577a63fa5ddfad290 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 24 Mar 2021 15:58:25 +0000 Subject: [PATCH 059/211] Moved det to LinearOps --- kmath-core/api/kmath-core.api | 4 +-- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 3 ++ .../kscience/kmath/tensors/TensorAlgebra.kt | 3 -- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 28 ------------------- 4 files changed, 4 insertions(+), 34 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 295df69e3..502628920 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2673,6 +2673,7 @@ public final class space/kscience/kmath/tensors/ComplexTensorStructure$DefaultIm public abstract interface class space/kscience/kmath/tensors/LinearOpsTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { public abstract fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun lu (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; public abstract fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; @@ -2706,7 +2707,6 @@ public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { public abstract fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun cumprod (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2958,8 +2958,6 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public fun cumprod (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public fun cumsum (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun det (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public fun diagonalEmbedding (Lspace/kscience/kmath/tensors/core/DoubleTensor;III)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index e412af7c6..3d1625a50 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -4,6 +4,9 @@ package space.kscience.kmath.tensors public interface LinearOpsTensorAlgebra, IndexTensorType: TensorStructure> : TensorPartialDivisionAlgebra { + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det + public fun TensorType.det(): TensorType + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv public fun TensorType.inv(): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index e41b7546c..702dc15e2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -52,9 +52,6 @@ public interface TensorAlgebra> { public fun TensorType.view(shape: IntArray): TensorType public fun TensorType.viewAs(other: TensorType): TensorType - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det - public fun TensorType.det(): TensorType - //https://pytorch.org/docs/stable/generated/torch.abs.html public fun TensorType.abs(): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 3ac09c8c7..df4a32bd8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -320,34 +320,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra shape[i] } - detTensorShape[n - 1] = 1 - val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } - - val detTensor = DoubleTensor( - detTensorShape, - resBuffer - ) - - this.matrixSequence().forEachIndexed{i, matrix -> - // todo need Matrix determinant algo - // todo resBuffer[i] = matrix.det() - } - - - return detTensor - - */ - } - override fun DoubleTensor.square(): DoubleTensor { TODO("Not yet implemented") } From 94b5afa6c475c4595ecb602f3ac1b66938ab04e6 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 24 Mar 2021 18:39:40 +0000 Subject: [PATCH 060/211] eq moved to interface --- .../kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt | 4 ++++ .../space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 702dc15e2..37c6a34f8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.tensors.core.DoubleTensor + // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { @@ -52,6 +54,8 @@ public interface TensorAlgebra> { public fun TensorType.view(shape: IntArray): TensorType public fun TensorType.viewAs(other: TensorType): TensorType + public fun TensorType.eq(other: TensorType, delta: T): Boolean + //https://pytorch.org/docs/stable/generated/torch.abs.html public fun TensorType.abs(): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index df4a32bd8..0c82ec9c8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -344,10 +344,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra abs(x - y) < delta } } - public fun DoubleTensor.eq(other: DoubleTensor, delta: Double = 1e-5): Boolean { + override fun DoubleTensor.eq(other: DoubleTensor, delta: Double): Boolean { return this.eq(other) { x, y -> abs(x - y) < delta } } + public fun DoubleTensor.eq(other: DoubleTensor): Boolean = this.eq(other, 1e-5) + public fun DoubleTensor.contentEquals(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { if (!(this.shape contentEquals other.shape)) { return false From daa077718299839d80256ef1705cb48f31d36c9f Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 24 Mar 2021 18:43:03 +0000 Subject: [PATCH 061/211] removed unused code --- .../kscience/kmath/tensors/core/checks.kt | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index ec7a123a9..c644a295c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -34,26 +34,6 @@ internal inline fun , } -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkDot(a: TensorType, b: TensorType): Unit { - val sa = a.shape - val sb = b.shape - val na = sa.size - val nb = sb.size - var status: Boolean - if (nb == 1) { - status = sa.last() == sb[0] - } else { - status = sa.last() == sb[nb - 2] - if ((na > 2) and (nb > 2)) { - status = status and - (sa.take(nb - 2).toIntArray() contentEquals sb.take(nb - 2).toIntArray()) - } - } - check(status) { "Incompatible shapes ${sa.toList()} and ${sb.toList()} provided for dot product" } -} - internal inline fun , TorchTensorAlgebraType : TensorAlgebra> TorchTensorAlgebraType.checkTranspose(dim: Int, i: Int, j: Int): Unit = From 1056fc7200b5fbbb03b75c66ca09c30483f12e5c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 13:48:59 +0000 Subject: [PATCH 062/211] Test for scalar product --- .../kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 2da79382f..d77f33f9d 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -70,4 +70,14 @@ class TestDoubleLinearOpsTensorAlgebra { assertTrue { invTensor.shape contentEquals expectedShape } assertTrue { invTensor.buffer.array().epsEqual(expectedBuffer) } } + + @Test + fun testScalarProduct() = DoubleLinearOpsTensorAlgebra { + val a = fromArray(intArrayOf(3), doubleArrayOf(1.8,2.5, 6.8)) + val b = fromArray(intArrayOf(3), doubleArrayOf(5.5,2.6, 6.4)) + DoubleReduceOpsTensorAlgebra { + assertEquals(a.dot(b).value(), 59.92) + } + + } } From 9162867fc28a4e948b0a520c67fca6cdf20ce53e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 14:37:27 +0000 Subject: [PATCH 063/211] Mutable structures 2D functionality added --- kmath-core/api/kmath-core.api | 17 ++++++++++++-- .../kscience/kmath/linear/LinearSpace.kt | 1 + .../space/kscience/kmath/nd/Structure2D.kt | 14 ++++++++++++ .../space/kscience/kmath/structures/Buffer.kt | 22 +++++++++++++++---- .../tensors/TensorPartialDivisionAlgebra.kt | 4 ++-- 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 502628920..a109aaab5 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -984,6 +984,8 @@ public final class space/kscience/kmath/nd/MutableStructure1D$DefaultImpls { } public abstract interface class space/kscience/kmath/nd/MutableStructure2D : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/Structure2D { + public abstract fun getColumns ()Ljava/util/List; + public abstract fun getRows ()Ljava/util/List; public abstract fun set (IILjava/lang/Object;)V } @@ -2608,6 +2610,15 @@ public final class space/kscience/kmath/structures/VirtualBuffer : space/kscienc public fun iterator ()Ljava/util/Iterator; } +public final class space/kscience/kmath/structures/VirtualMutableBuffer : space/kscience/kmath/structures/MutableBuffer { + public fun (ILkotlin/jvm/functions/Function1;)V + public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun get (I)Ljava/lang/Object; + public fun getSize ()I + public fun iterator ()Ljava/util/Iterator; + public fun set (ILjava/lang/Object;)V +} + public abstract interface class space/kscience/kmath/tensors/AnalyticTensorAlgebra : space/kscience/kmath/tensors/OrderedTensorAlgebra, space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { public abstract fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun acosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2709,6 +2720,7 @@ public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { public abstract fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun eq (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Z public abstract fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun flatten (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2970,9 +2982,10 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V public synthetic fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun dot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z + public synthetic fun eq (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Z + public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Z + public fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z - public static synthetic fun eq$default (Lspace/kscience/kmath/tensors/core/DoubleTensorAlgebra;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;DILjava/lang/Object;)Z public synthetic fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; public fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun flatten (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 6a587270b..4f2afc6fa 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -14,6 +14,7 @@ import kotlin.reflect.KClass * @param T the type of items. */ public typealias Matrix = Structure2D +public typealias MutableMatrix = MutableStructure2D /** * Alias or using [Buffer] as a point/vector in a many-dimensional space. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index d49438b2c..762b59b28 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -2,7 +2,9 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.VirtualBuffer +import space.kscience.kmath.structures.VirtualMutableBuffer import kotlin.reflect.KClass /** @@ -69,6 +71,18 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { * @param value the value. */ public operator fun set(i: Int, j: Int, value: T) + + /** + * The buffer of rows of this structure. It gets elements from the structure dynamically. + */ + override val rows: List> + get() = List(rowNum) { i -> VirtualMutableBuffer(colNum) { j -> get(i, j) } } + + /** + * The buffer of columns of this structure. It gets elements from the structure dynamically. + */ + override val columns: List> + get() = List(colNum) { j -> VirtualMutableBuffer(rowNum) { i -> get(i, j) } } } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index c85c6c5e3..72a6e3cae 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -223,11 +223,7 @@ public inline class MutableListBuffer(public val list: MutableList) : Muta } /** -<<<<<<< HEAD * Returns an [MutableListBuffer] that wraps the original list. -======= - * Returns an [ListBuffer] that wraps the original list. ->>>>>>> dev */ public fun MutableList.asMutableBuffer(): MutableListBuffer = MutableListBuffer(this) @@ -286,6 +282,24 @@ public class VirtualBuffer(override val size: Int, private val generator: (In override operator fun iterator(): Iterator = (0 until size).asSequence().map(generator).iterator() } +public class VirtualMutableBuffer(override val size: Int, private val generator: (Int) -> T) : MutableBuffer { + + private val bufferHolder: MutableListBuffer = (0 until size).map(generator).toMutableList().asMutableBuffer() + + override operator fun get(index: Int): T { + if (index < 0 || index >= size) throw IndexOutOfBoundsException("Expected index from 0 to ${size - 1}, but found $index") + return bufferHolder[index] + } + + override operator fun iterator(): Iterator = bufferHolder.iterator() + + override fun set(index: Int, value: T) { + bufferHolder[index] = value + } + + override fun copy(): MutableBuffer = bufferHolder.copy() +} + /** * Convert this buffer to read-only buffer. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt index 9f70f9621..54417e842 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -9,8 +9,8 @@ public interface TensorPartialDivisionAlgebra public operator fun TensorType.divAssign(other: TensorType) //https://pytorch.org/docs/stable/generated/torch.mean.html#torch.mean - public fun TensorType.mean(dim: Int, keepDim: Boolean): TensorType + public fun TensorType.mean(dim: Int = 0, keepDim: Boolean = false): TensorType //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var - public fun TensorType.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType + public fun TensorType.variance(dim: Int = 0, unbiased: Boolean = true, keepDim: Boolean = false): TensorType } From 1f19ac88aee34ed5b790356a81f762b21c1752f3 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 26 Mar 2021 17:43:08 +0300 Subject: [PATCH 064/211] qr fix --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 2 +- .../tensors/core/DoubleLinearOpsTensorAlgebra.kt | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index 3d1625a50..d980c510f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -14,7 +14,7 @@ public interface LinearOpsTensorAlgebra, Inde public fun TensorType.cholesky(): TensorType //https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr - public fun TensorType.qr(): TensorType + public fun TensorType.qr(): Pair //https://pytorch.org/docs/stable/generated/torch.lu.html public fun TensorType.lu(): Pair diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 0b9d824f0..d49fc941a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,8 +1,10 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.linear.Matrix import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.nd.Structure1D import space.kscience.kmath.nd.Structure2D +import space.kscience.kmath.nd.asND import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import kotlin.math.sqrt @@ -141,7 +143,15 @@ public class DoubleLinearOpsTensorAlgebra : return lTensor } - override fun DoubleTensor.qr(): DoubleTensor { + private fun matrixQR( + matrix: Structure2D, + q: MutableStructure2D, + r: MutableStructure2D + ) { + + } + + override fun DoubleTensor.qr(): Pair { TODO("ANDREI") } @@ -154,6 +164,7 @@ public class DoubleLinearOpsTensorAlgebra : } private fun luMatrixDet(lu: Structure2D, pivots: Structure1D): Double { + // todo check val m = lu.shape[0] val sign = if((pivots[m] - m) % 2 == 0) 1.0 else -1.0 return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } @@ -184,6 +195,7 @@ public class DoubleLinearOpsTensorAlgebra : pivots: Structure1D, invMatrix : MutableStructure2D ): Unit { + //todo check val m = lu.shape[0] for (j in 0 until m) { From a6354623ec08bb0c66d1e2a45eacde3b08e29c57 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 15:06:05 +0000 Subject: [PATCH 065/211] returning cols/rows as vectors --- kmath-core/api/kmath-core.api | 5 +++++ .../kotlin/space/kscience/kmath/nd/Structure1D.kt | 15 +++++++++++++++ .../kotlin/space/kscience/kmath/nd/Structure2D.kt | 8 ++++---- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index a109aaab5..0a3e3721d 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2768,6 +2768,11 @@ public abstract interface class space/kscience/kmath/tensors/TensorPartialDivisi public abstract fun variance (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; } +public final class space/kscience/kmath/tensors/TensorPartialDivisionAlgebra$DefaultImpls { + public static synthetic fun mean$default (Lspace/kscience/kmath/tensors/TensorPartialDivisionAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;IZILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public static synthetic fun variance$default (Lspace/kscience/kmath/tensors/TensorPartialDivisionAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;IZZILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; +} + public final class space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra { public fun ()V public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index c157f9a2f..354f3d802 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -71,6 +71,21 @@ private inline class Buffer1DWrapper(val buffer: Buffer) : Structure1D override operator fun get(index: Int): T = buffer[index] } +internal inline class MutableBuffer1DWrapper(val buffer: MutableBuffer) : MutableStructure1D { + override val shape: IntArray get() = intArrayOf(buffer.size) + override val size: Int get() = buffer.size + + override fun elements(): Sequence> = + buffer.asSequence().mapIndexed { index, value -> intArrayOf(index) to value } + + override operator fun get(index: Int): T = buffer[index] + override fun set(index: Int, value: T) { + buffer[index] = value + } + + override fun copy(): MutableBuffer = buffer.copy() +} + /** * Represent a [StructureND] as [Structure1D]. Throw error in case of dimension mismatch */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 762b59b28..e1a1d37de 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -75,14 +75,14 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { /** * The buffer of rows of this structure. It gets elements from the structure dynamically. */ - override val rows: List> - get() = List(rowNum) { i -> VirtualMutableBuffer(colNum) { j -> get(i, j) } } + override val rows: List> + get() = List(rowNum) { i -> MutableBuffer1DWrapper(VirtualMutableBuffer(colNum) { j -> get(i, j) })} /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ - override val columns: List> - get() = List(colNum) { j -> VirtualMutableBuffer(rowNum) { i -> get(i, j) } } + override val columns: List> + get() = List(colNum) { j -> MutableBuffer1DWrapper(VirtualMutableBuffer(rowNum) { i -> get(i, j) }) } } /** From 1588b5d94ff751fdf2d1d91686173068430723cd Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 15:09:18 +0000 Subject: [PATCH 066/211] once mutable stay it and enjoy --- .../kotlin/space/kscience/kmath/nd/Structure2D.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index e1a1d37de..8e41110fe 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -75,14 +75,14 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { /** * The buffer of rows of this structure. It gets elements from the structure dynamically. */ - override val rows: List> - get() = List(rowNum) { i -> MutableBuffer1DWrapper(VirtualMutableBuffer(colNum) { j -> get(i, j) })} + override val rows: MutableList> + get() = MutableList(rowNum) { i -> MutableBuffer1DWrapper(VirtualMutableBuffer(colNum) { j -> get(i, j) })} /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ - override val columns: List> - get() = List(colNum) { j -> MutableBuffer1DWrapper(VirtualMutableBuffer(rowNum) { i -> get(i, j) }) } + override val columns: MutableList> + get() = MutableList(colNum) { j -> MutableBuffer1DWrapper(VirtualMutableBuffer(rowNum) { i -> get(i, j) }) } } /** From e03910354e5ba02b6ec5551357ba629fa8cd8cca Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 15:14:23 +0000 Subject: [PATCH 067/211] ok reverting --- .../kotlin/space/kscience/kmath/nd/Structure2D.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 8e41110fe..e1a1d37de 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -75,14 +75,14 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { /** * The buffer of rows of this structure. It gets elements from the structure dynamically. */ - override val rows: MutableList> - get() = MutableList(rowNum) { i -> MutableBuffer1DWrapper(VirtualMutableBuffer(colNum) { j -> get(i, j) })} + override val rows: List> + get() = List(rowNum) { i -> MutableBuffer1DWrapper(VirtualMutableBuffer(colNum) { j -> get(i, j) })} /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ - override val columns: MutableList> - get() = MutableList(colNum) { j -> MutableBuffer1DWrapper(VirtualMutableBuffer(rowNum) { i -> get(i, j) }) } + override val columns: List> + get() = List(colNum) { j -> MutableBuffer1DWrapper(VirtualMutableBuffer(rowNum) { i -> get(i, j) }) } } /** From 516cd90677700d3f49096194bffa2cfd17ea78eb Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 15:36:53 +0000 Subject: [PATCH 068/211] Moved out to archive unimplemented API --- kmath-core/api/kmath-core.api | 160 +----------------- .../kmath/tensors/AnalyticTensorAlgebra.kt | 63 +------ .../kmath/tensors/ComplexTensorAlgebra.kt | 53 ------ .../kmath/tensors/ComplexTensorStructure.kt | 14 -- .../kmath/tensors/OrderedTensorAlgebra.kt | 29 ---- .../kscience/kmath/tensors/TensorAlgebra.kt | 26 --- .../tensors/TensorPartialDivisionAlgebra.kt | 6 - .../core/DoubleAnalyticTensorAlgebra.kt | 83 +-------- .../core/DoubleOrderedTensorAlgebra.kt | 43 ----- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 43 ----- 10 files changed, 4 insertions(+), 516 deletions(-) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 0a3e3721d..a45f00a55 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2619,7 +2619,7 @@ public final class space/kscience/kmath/structures/VirtualMutableBuffer : space/ public fun set (ILjava/lang/Object;)V } -public abstract interface class space/kscience/kmath/tensors/AnalyticTensorAlgebra : space/kscience/kmath/tensors/OrderedTensorAlgebra, space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { +public abstract interface class space/kscience/kmath/tensors/AnalyticTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { public abstract fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun acosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun asin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2627,59 +2627,16 @@ public abstract interface class space/kscience/kmath/tensors/AnalyticTensorAlgeb public abstract fun atan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun atanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun ceil (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun clamp (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun cos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun cosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun erf (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun erfc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun erfinv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun exp (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun floor (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun heaviside (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun histc (Lspace/kscience/kmath/nd/MutableStructureND;ILjava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun igamma (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun igammac (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun lerp (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun lgamma (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun log (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun logit (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun mvlgamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun polygamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun pow (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun quantile (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun round (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun sigmoid (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun sin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun sinc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun sinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun sqrt (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun std (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun tan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun tanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun trapz (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; -} - -public abstract interface class space/kscience/kmath/tensors/ComplexTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { - public abstract fun angle (Lspace/kscience/kmath/tensors/ComplexTensorStructure;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun bartlettWindow (IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun blackmanWindow (IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cartesianEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/tensors/ComplexTensorStructure; - public abstract fun hammingWindow (IZLjava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun inverseShortTimeFourierTransform (Lspace/kscience/kmath/tensors/ComplexTensorStructure;IIILspace/kscience/kmath/nd/MutableStructureND;ZZZI)V - public abstract fun kaiserWindow (IZLjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun polarEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/tensors/ComplexTensorStructure; - public abstract fun shortTimeFourierTransform (Lspace/kscience/kmath/tensors/ComplexTensorStructure;IIILspace/kscience/kmath/nd/MutableStructureND;ZZ)V - public abstract fun viewAsComplex (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/tensors/ComplexTensorStructure; -} - -public abstract interface class space/kscience/kmath/tensors/ComplexTensorStructure : space/kscience/kmath/nd/MutableStructureND { - public abstract fun imaginaryPart ()Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun realPart ()Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun viewAsReal ()Lspace/kscience/kmath/nd/MutableStructureND; -} - -public final class space/kscience/kmath/tensors/ComplexTensorStructure$DefaultImpls { - public static fun getDimension (Lspace/kscience/kmath/tensors/ComplexTensorStructure;)I } public abstract interface class space/kscience/kmath/tensors/LinearOpsTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { @@ -2697,32 +2654,16 @@ public final class space/kscience/kmath/tensors/LinearOpsTensorAlgebra$DefaultIm public static synthetic fun symEig$default (Lspace/kscience/kmath/tensors/LinearOpsTensorAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;ZILjava/lang/Object;)Lkotlin/Pair; } -public abstract interface class space/kscience/kmath/tensors/OrderedTensorAlgebra : space/kscience/kmath/tensors/TensorAlgebra { - public abstract fun cummax (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cummin (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun max (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun maximum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun median (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun min (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun minimum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun sort (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; -} - public abstract interface class space/kscience/kmath/tensors/ReduceOpsTensorAlgebra : space/kscience/kmath/tensors/TensorAlgebra { public abstract fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; } public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { - public abstract fun abs (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cat (Ljava/util/List;I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cumprod (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun eq (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Z public abstract fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun flatten (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun fullLike (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2738,10 +2679,6 @@ public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V public abstract fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun prod (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun square (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun squeeze (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun sum (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun times (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2764,13 +2701,6 @@ public abstract interface class space/kscience/kmath/tensors/TensorPartialDivisi public abstract fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V public abstract fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun mean (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun variance (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; -} - -public final class space/kscience/kmath/tensors/TensorPartialDivisionAlgebra$DefaultImpls { - public static synthetic fun mean$default (Lspace/kscience/kmath/tensors/TensorPartialDivisionAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;IZILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public static synthetic fun variance$default (Lspace/kscience/kmath/tensors/TensorPartialDivisionAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;IZZILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; } public final class space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra { @@ -2815,7 +2745,7 @@ public class space/kscience/kmath/tensors/core/BufferedTensor : space/kscience/k public final fun vectorSequence ()Lkotlin/sequences/Sequence; } -public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra : space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra, space/kscience/kmath/tensors/AnalyticTensorAlgebra { +public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/AnalyticTensorAlgebra { public fun ()V public synthetic fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun acos (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; @@ -2831,66 +2761,26 @@ public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra public fun atanh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun ceil (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun ceil (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun clamp (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun clamp (Lspace/kscience/kmath/tensors/core/DoubleTensor;DD)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun cos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun cos (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun cosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun cosh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun erf (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun erf (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun erfc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun erfc (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun erfinv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun erfinv (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun exp (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun exp (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun floor (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun floor (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun heaviside (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun heaviside (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun histc (Lspace/kscience/kmath/nd/MutableStructureND;ILjava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun histc (Lspace/kscience/kmath/tensors/core/DoubleTensor;IDD)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun igamma (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun igamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun igammac (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun igammac (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun lerp (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun lerp (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun lgamma (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun lgamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun log (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun log (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun logit (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun logit (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun mvlgamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun mvlgamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun polygamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun polygamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun pow (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun pow (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun quantile (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun quantile (Lspace/kscience/kmath/tensors/core/DoubleTensor;DIZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun round (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun round (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun sigmoid (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sigmoid (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun sin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun sin (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun sinc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sinc (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun sinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun sinh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun sqrt (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun sqrt (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun std (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun std (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun tan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun tan (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun tanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun tanh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun trapz (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun trapz (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; } public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebraKt { @@ -2923,30 +2813,6 @@ public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebr public static final fun DoubleLinearOpsTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } -public class space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/OrderedTensorAlgebra { - public fun ()V - public synthetic fun cummax (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cummax (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun cummin (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cummin (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun max (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun max (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun maximum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun maximum (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun median (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun median (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun min (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun min (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun minimum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun minimum (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun sort (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sort (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; -} - -public final class space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebraKt { - public static final fun DoubleOrderedTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - public final class space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/ReduceOpsTensorAlgebra { public fun ()V public synthetic fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; @@ -2962,19 +2828,11 @@ public final class space/kscience/kmath/tensors/core/DoubleTensor : space/kscien public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { public fun ()V - public synthetic fun abs (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun abs (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun cat (Ljava/util/List;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cat (Ljava/util/List;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z public static synthetic fun contentEquals$default (Lspace/kscience/kmath/tensors/core/DoubleTensorAlgebra;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;DILjava/lang/Object;)Z public synthetic fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun copy (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun cumprod (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cumprod (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cumsum (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public fun diagonalEmbedding (Lspace/kscience/kmath/tensors/core/DoubleTensor;III)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2993,8 +2851,6 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z public synthetic fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; public fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun flatten (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; - public fun flatten (Lspace/kscience/kmath/tensors/core/DoubleTensor;II)Lspace/kscience/kmath/tensors/core/DoubleTensor; public final fun fromArray ([I[D)Lspace/kscience/kmath/tensors/core/DoubleTensor; public fun full (D[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; @@ -3003,8 +2859,6 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public synthetic fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public fun get (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public final fun map (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun mean (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun mean (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; public fun minus (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -3029,14 +2883,6 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun prod (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun prod (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun square (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun square (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun squeeze (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun squeeze (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun sum (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sum (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; public fun times (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -3051,8 +2897,6 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public fun transpose (Lspace/kscience/kmath/tensors/core/DoubleTensor;II)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun unaryMinus (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun variance (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun variance (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; public fun view (Lspace/kscience/kmath/tensors/core/DoubleTensor;[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt index c3a558298..fa1de81fa 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt @@ -2,14 +2,7 @@ package space.kscience.kmath.tensors public interface AnalyticTensorAlgebra> : - TensorPartialDivisionAlgebra, - OrderedTensorAlgebra{ - - //https://pytorch.org/docs/stable/generated/torch.quantile.html#torch.quantile - public fun TensorType.quantile(q: T, dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.std.html#torch.std - public fun TensorType.std(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType + TensorPartialDivisionAlgebra { //https://pytorch.org/docs/stable/generated/torch.exp.html public fun TensorType.exp(): TensorType @@ -62,58 +55,4 @@ public interface AnalyticTensorAlgebra> : //https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor public fun TensorType.floor(): TensorType - //https://pytorch.org/docs/stable/generated/torch.clamp.html#torch.clamp - public fun TensorType.clamp(min: T, max: T): TensorType - - //https://pytorch.org/docs/stable/generated/torch.erf.html#torch.erf - public fun TensorType.erf(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.erfinv.html#torch.erfinv - public fun TensorType.erfinv(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.erfc.html#torch.erfc - public fun TensorType.erfc(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.lerp.html#torch.lerp - public fun TensorType.lerp(end: TensorType, weight: TensorType): TensorType - - //https://pytorch.org/docs/stable/generated/torch.lgamma.html#torch.lgamma - public fun TensorType.lgamma(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.logit.html#torch.logit - public fun TensorType.logit(eps: T): TensorType - - //https://pytorch.org/docs/stable/generated/torch.igamma.html#torch.igamma - public fun TensorType.igamma(other: TensorType): TensorType - - //https://pytorch.org/docs/stable/generated/torch.igammac.html#torch.igammac - public fun TensorType.igammac(other: TensorType): TensorType - - //https://pytorch.org/docs/stable/generated/torch.mvlgamma.html#torch.mvlgamma - public fun TensorType.mvlgamma(dimensions: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.polygamma.html#torch.polygamma - public fun TensorType.polygamma(order: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.pow.html#torch.pow - public fun TensorType.pow(exponent: T): TensorType - - //https://pytorch.org/docs/stable/generated/torch.round.html#torch.round - public fun TensorType.round(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.sigmoid.html#torch.sigmoid - public fun TensorType.sigmoid(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.sinc.html#torch.sinc - public fun TensorType.sinc(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.heaviside.html#torch.heaviside - public fun TensorType.heaviside(values: TensorType): TensorType - - //https://pytorch.org/docs/stable/generated/torch.trapz.html#torch.trapz - public fun TensorType.trapz(xValues: TensorType, dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.histc.html#torch.histc - public fun TensorType.histc(bins: Int, min: T, max: T): TensorType - } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt deleted file mode 100644 index e56920916..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt +++ /dev/null @@ -1,53 +0,0 @@ -package space.kscience.kmath.tensors - -public interface ComplexTensorAlgebra, - ComplexTensorType : ComplexTensorStructure> - : TensorPartialDivisionAlgebra{ - - //https://pytorch.org/docs/stable/generated/torch.view_as_complex.html - public fun RealTensorType.viewAsComplex(): ComplexTensorType - - // Embed a real tensor as real + i * imaginary - public fun RealTensorType.cartesianEmbedding(imaginary: RealTensorType): ComplexTensorType - - // Embed a real tensor as real * exp(i * angle) - public fun RealTensorType.polarEmbedding(angle: RealTensorType): ComplexTensorType - - //https://pytorch.org/docs/stable/generated/torch.angle.html - public fun ComplexTensorType.angle(): RealTensorType - - //https://pytorch.org/docs/stable/generated/torch.stft.html#torch.stft - public fun ComplexTensorType.shortTimeFourierTransform( - nFFT: Int, - hopLength: Int, - winLength: Int, - window: RealTensorType, - normalised: Boolean, - oneSided: Boolean - ) - - //https://pytorch.org/docs/stable/generated/torch.istft.html#torch.istft - public fun ComplexTensorType.inverseShortTimeFourierTransform( - nFFT: Int, - hopLength: Int, - winLength: Int, - window: RealTensorType, - center: Boolean, - normalised: Boolean, - oneSided: Boolean, - length: Int - ) - - //https://pytorch.org/docs/stable/generated/torch.bartlett_window.html#torch.bartlett_window - public fun bartlettWindow(windowLength: Int, periodic: Boolean): RealTensorType - - //https://pytorch.org/docs/stable/generated/torch.blackman_window.html#torch.blackman_window - public fun blackmanWindow(windowLength: Int, periodic: Boolean): RealTensorType - - //https://pytorch.org/docs/stable/generated/torch.hamming_window.html#torch.hamming_window - public fun hammingWindow(windowLength: Int, periodic: Boolean, alpha: T, beta: T): RealTensorType - - //https://pytorch.org/docs/stable/generated/torch.kaiser_window.html#torch.kaiser_window - public fun kaiserWindow(windowLength: Int, periodic: Boolean, beta: T): RealTensorType -} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt deleted file mode 100644 index 0e0975830..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt +++ /dev/null @@ -1,14 +0,0 @@ -package space.kscience.kmath.tensors - -public interface ComplexTensorStructure> : TensorStructure { - - //https://pytorch.org/docs/master/generated/torch.view_as_real.html - public fun viewAsReal(): RealTensorType - - //https://pytorch.org/docs/stable/generated/torch.real.html - public fun realPart(): RealTensorType - - //https://pytorch.org/docs/stable/generated/torch.imag.html - public fun imaginaryPart(): RealTensorType - -} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt deleted file mode 100644 index 3320c3a1e..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt +++ /dev/null @@ -1,29 +0,0 @@ -package space.kscience.kmath.tensors - -public interface OrderedTensorAlgebra> : - TensorAlgebra { - - //https://pytorch.org/docs/stable/generated/torch.max.html#torch.max - public fun TensorType.max(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.cummax.html#torch.cummax - public fun TensorType.cummax(dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.min.html#torch.min - public fun TensorType.min(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.cummin.html#torch.cummin - public fun TensorType.cummin(dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.median.html#torch.median - public fun TensorType.median(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.maximum.html#torch.maximum - public fun maximum(lhs: TensorType, rhs: TensorType) - - //https://pytorch.org/docs/stable/generated/torch.minimum.html#torch.minimum - public fun minimum(lhs: TensorType, rhs: TensorType) - - //https://pytorch.org/docs/stable/generated/torch.sort.html#torch.sort - public fun TensorType.sort(dim: Int, keepDim: Boolean, descending: Boolean): TensorType -} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 37c6a34f8..b05105ed8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -41,9 +41,6 @@ public interface TensorAlgebra> { public operator fun TensorType.timesAssign(other: TensorType): Unit public operator fun TensorType.unaryMinus(): TensorType - //https://pytorch.org/docs/stable/generated/torch.square.html - public fun TensorType.square(): TensorType - //https://pytorch.org/cppdocs/notes/tensor_indexing.html public operator fun TensorType.get(i: Int): TensorType @@ -56,21 +53,6 @@ public interface TensorAlgebra> { public fun TensorType.eq(other: TensorType, delta: T): Boolean - //https://pytorch.org/docs/stable/generated/torch.abs.html - public fun TensorType.abs(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.sum.html - public fun TensorType.sum(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.cumsum.html#torch.cumsum - public fun TensorType.cumsum(dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.prod.html#torch.prod - public fun TensorType.prod(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.cumprod.html#torch.cumprod - public fun TensorType.cumprod(dim: Int): TensorType - //https://pytorch.org/docs/stable/generated/torch.matmul.html public infix fun TensorType.dot(other: TensorType): TensorType @@ -80,12 +62,4 @@ public interface TensorAlgebra> { offset: Int = 0, dim1: Int = -2, dim2: Int = -1 ): TensorType - //https://pytorch.org/docs/stable/generated/torch.cat.html#torch.cat - public fun cat(tensors: List, dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.flatten.html#torch.flatten - public fun TensorType.flatten(startDim: Int, endDim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.squeeze.html - public fun TensorType.squeeze(dim: Int): TensorType } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt index 54417e842..67b9c9d73 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -7,10 +7,4 @@ public interface TensorPartialDivisionAlgebra public operator fun TensorType.div(other: TensorType): TensorType public operator fun TensorType.divAssign(value: T) public operator fun TensorType.divAssign(other: TensorType) - - //https://pytorch.org/docs/stable/generated/torch.mean.html#torch.mean - public fun TensorType.mean(dim: Int = 0, keepDim: Boolean = false): TensorType - - //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var - public fun TensorType.variance(dim: Int = 0, unbiased: Boolean = true, keepDim: Boolean = false): TensorType } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt index 1eb4c3b63..b46c7fa9c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt @@ -5,11 +5,10 @@ import kotlin.math.* public class DoubleAnalyticTensorAlgebra: AnalyticTensorAlgebra, - DoubleOrderedTensorAlgebra() + DoubleTensorAlgebra() { override fun DoubleTensor.exp(): DoubleTensor = this.map(::exp) - // todo log with other base???? override fun DoubleTensor.log(): DoubleTensor = this.map(::ln) override fun DoubleTensor.sqrt(): DoubleTensor = this.map(::sqrt) @@ -42,86 +41,6 @@ public class DoubleAnalyticTensorAlgebra: override fun DoubleTensor.floor(): DoubleTensor = this.map(::floor) - override fun DoubleTensor.clamp(min: Double, max: Double): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.erf(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.erfinv(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.erfc(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.lerp(end: DoubleTensor, weight: DoubleTensor): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.lgamma(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.logit(eps: Double): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.igamma(other: DoubleTensor): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.igammac(other: DoubleTensor): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.mvlgamma(dimensions: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.polygamma(order: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.pow(exponent: Double): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.round(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.sigmoid(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.sinc(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.heaviside(values: DoubleTensor): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.trapz(xValues: DoubleTensor, dim: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.quantile(q: Double, dim: Int, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.std(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.histc(bins: Int, min: Double, max: Double): DoubleTensor { - TODO("Not yet implemented") - } - } public inline fun DoubleAnalyticTensorAlgebra(block: DoubleAnalyticTensorAlgebra.() -> R): R = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt deleted file mode 100644 index a6bea59f4..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt +++ /dev/null @@ -1,43 +0,0 @@ -package space.kscience.kmath.tensors.core - -import space.kscience.kmath.tensors.OrderedTensorAlgebra - -public open class DoubleOrderedTensorAlgebra: - OrderedTensorAlgebra, - DoubleTensorAlgebra() -{ - override fun DoubleTensor.max(dim: Int, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.cummax(dim: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.min(dim: Int, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.cummin(dim: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.median(dim: Int, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun maximum(lhs: DoubleTensor, rhs: DoubleTensor) { - TODO("Not yet implemented") - } - - override fun minimum(lhs: DoubleTensor, rhs: DoubleTensor) { - TODO("Not yet implemented") - } - - override fun DoubleTensor.sort(dim: Int, keepDim: Boolean, descending: Boolean): DoubleTensor { - TODO("Not yet implemented") - } -} - -public inline fun DoubleOrderedTensorAlgebra(block: DoubleOrderedTensorAlgebra.() -> R): R = - DoubleOrderedTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 0c82ec9c8..0a2e8c86c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -224,26 +224,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra, dim: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.flatten(startDim: Int, endDim: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.mean(dim: Int, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.square(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.squeeze(dim: Int): DoubleTensor { - TODO("Not yet implemented") - } public fun DoubleTensor.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( From 22b68e5ca469038e8ee6c2083aafa2f54d51d032 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 20:36:21 +0000 Subject: [PATCH 069/211] BufferedTensor2D & BufferedTensor1D --- kmath-core/api/kmath-core.api | 28 ++++ .../kmath/tensors/core/BufferedTensor.kt | 133 ++++++++++++++++-- .../core/DoubleLinearOpsTensorAlgebra.kt | 11 +- .../core/TestDoubleLinearOpsAlgebra.kt | 1 - .../kmath/tensors/core/TestDoubleTensor.kt | 3 - 5 files changed, 152 insertions(+), 24 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index a45f00a55..fc0905bd0 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2745,6 +2745,34 @@ public class space/kscience/kmath/tensors/core/BufferedTensor : space/kscience/k public final fun vectorSequence ()Lkotlin/sequences/Sequence; } +public final class space/kscience/kmath/tensors/core/BufferedTensor1D : space/kscience/kmath/tensors/core/BufferedTensor, space/kscience/kmath/nd/MutableStructure1D { + public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun get (I)Ljava/lang/Object; + public fun get ([I)Ljava/lang/Object; + public fun getDimension ()I + public fun getSize ()I + public fun iterator ()Ljava/util/Iterator; + public fun set (ILjava/lang/Object;)V + public fun set ([ILjava/lang/Object;)V +} + +public final class space/kscience/kmath/tensors/core/BufferedTensor2D : space/kscience/kmath/tensors/core/BufferedTensor, space/kscience/kmath/nd/MutableStructure2D { + public fun elements ()Lkotlin/sequences/Sequence; + public fun get (II)Ljava/lang/Object; + public fun get ([I)Ljava/lang/Object; + public fun getColNum ()I + public fun getColumns ()Ljava/util/List; + public fun getRowNum ()I + public fun getRows ()Ljava/util/List; + public fun getShape ()[I + public fun set (IILjava/lang/Object;)V +} + +public final class space/kscience/kmath/tensors/core/BufferedTensorKt { + public static final fun as1D (Lspace/kscience/kmath/tensors/core/BufferedTensor;)Lspace/kscience/kmath/tensors/core/BufferedTensor1D; + public static final fun as2D (Lspace/kscience/kmath/tensors/core/BufferedTensor;)Lspace/kscience/kmath/tensors/core/BufferedTensor2D; +} + public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/AnalyticTensorAlgebra { public fun ()V public synthetic fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 160c61260..aa6e58ef6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,23 +1,26 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.* +import space.kscience.kmath.nd.MutableStructure1D +import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.TensorStructure -import kotlin.math.atanh + public open class BufferedTensor( override val shape: IntArray, public val buffer: MutableBuffer, internal val bufferStart: Int -) : TensorStructure -{ +) : TensorStructure { public val linearStructure: TensorLinearStructure get() = TensorLinearStructure(shape) public val numel: Int get() = linearStructure.size + internal constructor(tensor: BufferedTensor) : + this(tensor.shape, tensor.buffer, tensor.bufferStart) + override fun get(index: IntArray): T = buffer[bufferStart + linearStructure.offset(index)] override fun set(index: IntArray, value: T) { @@ -32,8 +35,8 @@ public open class BufferedTensor( override fun hashCode(): Int = 0 - public fun vectorSequence(): Sequence> = sequence { - check(shape.size >= 1) {"todo"} + public fun vectorSequence(): Sequence> = sequence { + check(shape.size >= 1) { "todo" } val n = shape.size val vectorOffset = shape[n - 1] val vectorShape = intArrayOf(shape.last()) @@ -43,8 +46,8 @@ public open class BufferedTensor( } } - public fun matrixSequence(): Sequence> = sequence { - check(shape.size >= 2) {"todo"} + public fun matrixSequence(): Sequence> = sequence { + check(shape.size >= 2) { "todo" } val n = shape.size val matrixOffset = shape[n - 1] * shape[n - 2] val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) //todo better way? @@ -54,14 +57,14 @@ public open class BufferedTensor( } } - public inline fun forEachVector(vectorAction : (MutableStructure1D) -> Unit): Unit { - for (vector in vectorSequence()){ + public inline fun forEachVector(vectorAction: (BufferedTensor1D) -> Unit): Unit { + for (vector in vectorSequence()) { vectorAction(vector) } } - public inline fun forEachMatrix(matrixAction : (MutableStructure2D) -> Unit): Unit { - for (matrix in matrixSequence()){ + public inline fun forEachMatrix(matrixAction: (BufferedTensor2D) -> Unit): Unit { + for (matrix in matrixSequence()) { matrixAction(matrix) } } @@ -74,21 +77,125 @@ public class IntTensor internal constructor( buffer: IntArray, offset: Int = 0 ) : BufferedTensor(shape, IntBuffer(buffer), offset) +{ + internal constructor(bufferedTensor: BufferedTensor): + this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) +} public class LongTensor internal constructor( shape: IntArray, buffer: LongArray, offset: Int = 0 ) : BufferedTensor(shape, LongBuffer(buffer), offset) +{ + internal constructor(bufferedTensor: BufferedTensor): + this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) +} public class FloatTensor internal constructor( shape: IntArray, buffer: FloatArray, offset: Int = 0 ) : BufferedTensor(shape, FloatBuffer(buffer), offset) +{ + internal constructor(bufferedTensor: BufferedTensor): + this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) +} public class DoubleTensor internal constructor( shape: IntArray, buffer: DoubleArray, offset: Int = 0 -) : BufferedTensor(shape, DoubleBuffer(buffer), offset) \ No newline at end of file +) : BufferedTensor(shape, DoubleBuffer(buffer), offset) +{ + internal constructor(bufferedTensor: BufferedTensor): + this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) +} + + +public class BufferedTensor2D internal constructor( + private val tensor: BufferedTensor, +) : BufferedTensor(tensor), MutableStructure2D { + init { + check(shape.size == 2) { + "Shape ${shape.toList()} not compatible with DoubleTensor2D" + } + } + + override val shape: IntArray + get() = tensor.shape + + override val rowNum: Int + get() = shape[0] + override val colNum: Int + get() = shape[1] + + override fun get(i: Int, j: Int): T = tensor[intArrayOf(i, j)] + + override fun get(index: IntArray): T = tensor[index] + + override fun elements(): Sequence> = tensor.elements() + + override fun set(i: Int, j: Int, value: T) { + tensor[intArrayOf(i, j)] = value + } + + override val rows: List> + get() = List(rowNum) { i -> + BufferedTensor1D( + BufferedTensor( + shape = intArrayOf(colNum), + buffer = VirtualMutableBuffer(colNum) { j -> get(i, j) }, + bufferStart = 0 + ) + ) + } + + override val columns: List> + get() = List(colNum) { j -> + BufferedTensor1D( + BufferedTensor( + shape = intArrayOf(rowNum), + buffer = VirtualMutableBuffer(rowNum) { i -> get(i, j) }, + bufferStart = 0 + ) + ) + } +} + +public class BufferedTensor1D internal constructor( + private val tensor: BufferedTensor +) : BufferedTensor(tensor), MutableStructure1D { + init { + check(shape.size == 1) { + "Shape ${shape.toList()} not compatible with DoubleTensor1D" + } + } + + override fun get(index: IntArray): T = tensor[index] + + override fun set(index: IntArray, value: T) { + tensor[index] = value + } + + override val size: Int + get() = tensor.linearStructure.size + + override fun get(index: Int): T = tensor[intArrayOf(index)] + + override fun set(index: Int, value: T) { + tensor[intArrayOf(index)] = value + } + + override fun copy(): MutableBuffer = tensor.buffer.copy() + +} + +internal fun BufferedTensor.asIntTensor(): IntTensor = IntTensor(this) +internal fun BufferedTensor.asLongTensor(): LongTensor = LongTensor(this) +internal fun BufferedTensor.asFloatTensor(): FloatTensor = FloatTensor(this) +internal fun BufferedTensor.asDoubleTensor(): DoubleTensor = DoubleTensor(this) + + +public fun BufferedTensor.as2D(): BufferedTensor2D = BufferedTensor2D(this) +public fun BufferedTensor.as1D(): BufferedTensor1D = BufferedTensor1D(this) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 0b9d824f0..70fe8a1cc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,8 +1,5 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.MutableStructure2D -import space.kscience.kmath.nd.Structure1D -import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import kotlin.math.sqrt @@ -153,7 +150,7 @@ public class DoubleLinearOpsTensorAlgebra : TODO("ANDREI") } - private fun luMatrixDet(lu: Structure2D, pivots: Structure1D): Double { + private fun luMatrixDet(lu: BufferedTensor2D, pivots: BufferedTensor1D): Double { val m = lu.shape[0] val sign = if((pivots[m] - m) % 2 == 0) 1.0 else -1.0 return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } @@ -180,9 +177,9 @@ public class DoubleLinearOpsTensorAlgebra : } private fun luMatrixInv( - lu: Structure2D, - pivots: Structure1D, - invMatrix : MutableStructure2D + lu: BufferedTensor2D, + pivots: BufferedTensor1D, + invMatrix : BufferedTensor2D ): Unit { val m = lu.shape[0] diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index d77f33f9d..3a129b03c 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -1,7 +1,6 @@ package space.kscience.kmath.tensors.core import kotlin.math.abs -import kotlin.math.exp import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index b12b08b52..40597f539 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,8 +1,5 @@ package space.kscience.kmath.tensors.core - -import space.kscience.kmath.nd.as1D -import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray import kotlin.test.Test import kotlin.test.assertEquals From 92710097f06d0ec6161e4f3518a2fd0815ff157a Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 29 Mar 2021 21:58:56 +0100 Subject: [PATCH 070/211] Fixing 2D and 1D casts --- kmath-core/api/kmath-core.api | 33 --- .../kmath/tensors/core/BufferedTensor.kt | 107 +-------- .../core/DoubleLinearOpsTensorAlgebra.kt | 220 ++++++++++-------- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 53 +++-- .../kscience/kmath/tensors/core/checks.kt | 6 +- .../kmath/tensors/core/TestDoubleTensor.kt | 2 + 6 files changed, 173 insertions(+), 248 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index fc0905bd0..786b81d19 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2731,8 +2731,6 @@ public class space/kscience/kmath/tensors/core/BufferedTensor : space/kscience/k public fun ([ILspace/kscience/kmath/structures/MutableBuffer;I)V public fun elements ()Lkotlin/sequences/Sequence; public fun equals (Ljava/lang/Object;)Z - public final fun forEachMatrix (Lkotlin/jvm/functions/Function1;)V - public final fun forEachVector (Lkotlin/jvm/functions/Function1;)V public fun get ([I)Ljava/lang/Object; public final fun getBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; public fun getDimension ()I @@ -2740,37 +2738,7 @@ public class space/kscience/kmath/tensors/core/BufferedTensor : space/kscience/k public final fun getNumel ()I public fun getShape ()[I public fun hashCode ()I - public final fun matrixSequence ()Lkotlin/sequences/Sequence; public fun set ([ILjava/lang/Object;)V - public final fun vectorSequence ()Lkotlin/sequences/Sequence; -} - -public final class space/kscience/kmath/tensors/core/BufferedTensor1D : space/kscience/kmath/tensors/core/BufferedTensor, space/kscience/kmath/nd/MutableStructure1D { - public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; - public fun get (I)Ljava/lang/Object; - public fun get ([I)Ljava/lang/Object; - public fun getDimension ()I - public fun getSize ()I - public fun iterator ()Ljava/util/Iterator; - public fun set (ILjava/lang/Object;)V - public fun set ([ILjava/lang/Object;)V -} - -public final class space/kscience/kmath/tensors/core/BufferedTensor2D : space/kscience/kmath/tensors/core/BufferedTensor, space/kscience/kmath/nd/MutableStructure2D { - public fun elements ()Lkotlin/sequences/Sequence; - public fun get (II)Ljava/lang/Object; - public fun get ([I)Ljava/lang/Object; - public fun getColNum ()I - public fun getColumns ()Ljava/util/List; - public fun getRowNum ()I - public fun getRows ()Ljava/util/List; - public fun getShape ()[I - public fun set (IILjava/lang/Object;)V -} - -public final class space/kscience/kmath/tensors/core/BufferedTensorKt { - public static final fun as1D (Lspace/kscience/kmath/tensors/core/BufferedTensor;)Lspace/kscience/kmath/tensors/core/BufferedTensor1D; - public static final fun as2D (Lspace/kscience/kmath/tensors/core/BufferedTensor;)Lspace/kscience/kmath/tensors/core/BufferedTensor2D; } public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/AnalyticTensorAlgebra { @@ -2876,7 +2844,6 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public synthetic fun eq (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Z public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Z public fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z - public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z public synthetic fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; public fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public final fun fromArray ([I[D)Lspace/kscience/kmath/tensors/core/DoubleTensor; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index aa6e58ef6..d99c35569 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -35,35 +35,34 @@ public open class BufferedTensor( override fun hashCode(): Int = 0 - public fun vectorSequence(): Sequence> = sequence { - check(shape.size >= 1) { "todo" } + internal fun vectorSequence(): Sequence> = sequence { val n = shape.size val vectorOffset = shape[n - 1] val vectorShape = intArrayOf(shape.last()) for (offset in 0 until numel step vectorOffset) { - val vector = BufferedTensor(vectorShape, buffer, offset).as1D() + val vector = BufferedTensor(vectorShape, buffer, offset) yield(vector) } } - public fun matrixSequence(): Sequence> = sequence { + internal fun matrixSequence(): Sequence> = sequence { check(shape.size >= 2) { "todo" } val n = shape.size val matrixOffset = shape[n - 1] * shape[n - 2] - val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) //todo better way? + val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) for (offset in 0 until numel step matrixOffset) { - val matrix = BufferedTensor(matrixShape, buffer, offset).as2D() + val matrix = BufferedTensor(matrixShape, buffer, offset) yield(matrix) } } - public inline fun forEachVector(vectorAction: (BufferedTensor1D) -> Unit): Unit { + internal inline fun forEachVector(vectorAction: (BufferedTensor) -> Unit): Unit { for (vector in vectorSequence()) { vectorAction(vector) } } - public inline fun forEachMatrix(matrixAction: (BufferedTensor2D) -> Unit): Unit { + internal inline fun forEachMatrix(matrixAction: (BufferedTensor) -> Unit): Unit { for (matrix in matrixSequence()) { matrixAction(matrix) } @@ -71,7 +70,6 @@ public open class BufferedTensor( } - public class IntTensor internal constructor( shape: IntArray, buffer: IntArray, @@ -112,90 +110,7 @@ public class DoubleTensor internal constructor( this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) } - -public class BufferedTensor2D internal constructor( - private val tensor: BufferedTensor, -) : BufferedTensor(tensor), MutableStructure2D { - init { - check(shape.size == 2) { - "Shape ${shape.toList()} not compatible with DoubleTensor2D" - } - } - - override val shape: IntArray - get() = tensor.shape - - override val rowNum: Int - get() = shape[0] - override val colNum: Int - get() = shape[1] - - override fun get(i: Int, j: Int): T = tensor[intArrayOf(i, j)] - - override fun get(index: IntArray): T = tensor[index] - - override fun elements(): Sequence> = tensor.elements() - - override fun set(i: Int, j: Int, value: T) { - tensor[intArrayOf(i, j)] = value - } - - override val rows: List> - get() = List(rowNum) { i -> - BufferedTensor1D( - BufferedTensor( - shape = intArrayOf(colNum), - buffer = VirtualMutableBuffer(colNum) { j -> get(i, j) }, - bufferStart = 0 - ) - ) - } - - override val columns: List> - get() = List(colNum) { j -> - BufferedTensor1D( - BufferedTensor( - shape = intArrayOf(rowNum), - buffer = VirtualMutableBuffer(rowNum) { i -> get(i, j) }, - bufferStart = 0 - ) - ) - } -} - -public class BufferedTensor1D internal constructor( - private val tensor: BufferedTensor -) : BufferedTensor(tensor), MutableStructure1D { - init { - check(shape.size == 1) { - "Shape ${shape.toList()} not compatible with DoubleTensor1D" - } - } - - override fun get(index: IntArray): T = tensor[index] - - override fun set(index: IntArray, value: T) { - tensor[index] = value - } - - override val size: Int - get() = tensor.linearStructure.size - - override fun get(index: Int): T = tensor[intArrayOf(index)] - - override fun set(index: Int, value: T) { - tensor[intArrayOf(index)] = value - } - - override fun copy(): MutableBuffer = tensor.buffer.copy() - -} - -internal fun BufferedTensor.asIntTensor(): IntTensor = IntTensor(this) -internal fun BufferedTensor.asLongTensor(): LongTensor = LongTensor(this) -internal fun BufferedTensor.asFloatTensor(): FloatTensor = FloatTensor(this) -internal fun BufferedTensor.asDoubleTensor(): DoubleTensor = DoubleTensor(this) - - -public fun BufferedTensor.as2D(): BufferedTensor2D = BufferedTensor2D(this) -public fun BufferedTensor.as1D(): BufferedTensor1D = BufferedTensor1D(this) \ No newline at end of file +internal fun BufferedTensor.asTensor(): IntTensor = IntTensor(this) +internal fun BufferedTensor.asTensor(): LongTensor = LongTensor(this) +internal fun BufferedTensor.asTensor(): FloatTensor = FloatTensor(this) +internal fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 70fe8a1cc..0d19fd3f6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,5 +1,9 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.MutableStructure1D +import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.nd.as1D +import space.kscience.kmath.nd.as2D import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import kotlin.math.sqrt @@ -11,6 +15,48 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.det(): DoubleTensor = detLU() + private inline fun luHelper(lu: MutableStructure2D, pivots: MutableStructure1D, m: Int) { + for (row in 0 until m) pivots[row] = row + + for (i in 0 until m) { + var maxVal = -1.0 + var maxInd = i + + for (k in i until m) { + val absA = kotlin.math.abs(lu[k, i]) + if (absA > maxVal) { + maxVal = absA + maxInd = k + } + } + + //todo check singularity + + if (maxInd != i) { + + val j = pivots[i] + pivots[i] = pivots[maxInd] + pivots[maxInd] = j + + for (k in 0 until m) { + val tmp = lu[i, k] + lu[i, k] = lu[maxInd, k] + lu[maxInd, k] = tmp + } + + pivots[m] += 1 + + } + + for (j in i + 1 until m) { + lu[j, i] /= lu[i, i] + for (k in i + 1 until m) { + lu[j, k] -= lu[j, i] * lu[i, k] + } + } + } + } + override fun DoubleTensor.lu(): Pair { checkSquareMatrix(shape) @@ -27,90 +73,93 @@ public class DoubleLinearOpsTensorAlgebra : IntArray(pivotsShape.reduce(Int::times)) { 0 } ) - for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())){ - for (row in 0 until m) pivots[row] = row - - for (i in 0 until m) { - var maxVal = -1.0 - var maxInd = i - - for (k in i until m) { - val absA = kotlin.math.abs(lu[k, i]) - if (absA > maxVal) { - maxVal = absA - maxInd = k - } - } - - //todo check singularity - - if (maxInd != i) { - - val j = pivots[i] - pivots[i] = pivots[maxInd] - pivots[maxInd] = j - - for (k in 0 until m) { - val tmp = lu[i, k] - lu[i, k] = lu[maxInd, k] - lu[maxInd, k] = tmp - } - - pivots[m] += 1 - - } - - for (j in i + 1 until m) { - lu[j, i] /= lu[i, i] - for (k in i + 1 until m) { - lu[j, k] -= lu[j, i] * lu[i, k] - } - } - } - } - + for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) + luHelper(lu.as2D(), pivots.as1D(), m) return Pair(luTensor, pivotsTensor) } - override fun luPivot(luTensor: DoubleTensor, pivotsTensor: IntTensor): Triple { + private inline fun pivInit( + p: MutableStructure2D, + pivot: MutableStructure1D, + n: Int + ) { + for (i in 0 until n) { + p[i, pivot[i]] = 1.0 + } + } + + private inline fun luPivotHelper( + l: MutableStructure2D, + u: MutableStructure2D, + lu: MutableStructure2D, + n: Int + ) { + for (i in 0 until n) { + for (j in 0 until n) { + if (i == j) { + l[i, j] = 1.0 + } + if (j < i) { + l[i, j] = lu[i, j] + } + if (j >= i) { + u[i, j] = lu[i, j] + } + } + } + } + + override fun luPivot( + luTensor: DoubleTensor, + pivotsTensor: IntTensor + ): Triple { //todo checks checkSquareMatrix(luTensor.shape) - check(luTensor.shape.dropLast(1).toIntArray() contentEquals pivotsTensor.shape) { "Bed shapes (("} //todo rewrite + check( + luTensor.shape.dropLast(1).toIntArray() contentEquals pivotsTensor.shape + ) { "Bed shapes ((" } //todo rewrite val n = luTensor.shape.last() val pTensor = luTensor.zeroesLike() - for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.vectorSequence())){ - for (i in 0 until n){ - p[i, pivot[i]] = 1.0 - } - } + for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) + pivInit(p.as2D(), pivot.as1D(), n) val lTensor = luTensor.zeroesLike() val uTensor = luTensor.zeroesLike() - for ((pairLU, lu) in lTensor.matrixSequence().zip(uTensor.matrixSequence()).zip(luTensor.matrixSequence())){ + for ((pairLU, lu) in lTensor.matrixSequence().zip(uTensor.matrixSequence()) + .zip(luTensor.matrixSequence())) { val (l, u) = pairLU - for (i in 0 until n) { - for (j in 0 until n) { - if (i == j) { - l[i, j] = 1.0 - } - if (j < i) { - l[i, j] = lu[i, j] - } - if (j >= i) { - u[i, j] = lu[i, j] - } - } - } + luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) } return Triple(pTensor, lTensor, uTensor) } + private inline fun choleskyHelper( + a: MutableStructure2D, + l: MutableStructure2D, + n: Int + ) { + for (i in 0 until n) { + for (j in 0 until i) { + var h = a[i, j] + for (k in 0 until j) { + h -= l[i, k] * l[j, k] + } + l[i, j] = h / l[j, j] + } + var h = a[i, i] + for (j in 0 until i) { + h -= l[i, j] * l[i, j] + } + l[i, i] = sqrt(h) + } + } + override fun DoubleTensor.cholesky(): DoubleTensor { // todo checks checkSquareMatrix(shape) @@ -118,22 +167,8 @@ public class DoubleLinearOpsTensorAlgebra : val n = shape.last() val lTensor = zeroesLike() - for ((a, l) in this.matrixSequence().zip(lTensor.matrixSequence())) { - for (i in 0 until n) { - for (j in 0 until i) { - var h = a[i, j] - for (k in 0 until j) { - h -= l[i, k] * l[j, k] - } - l[i, j] = h / l[j, j] - } - var h = a[i, i] - for (j in 0 until i) { - h -= l[i, j] * l[i, j] - } - l[i, i] = sqrt(h) - } - } + for ((a, l) in this.matrixSequence().zip(lTensor.matrixSequence())) + for (i in 0 until n) choleskyHelper(a.as2D(), l.as2D(), n) return lTensor } @@ -150,9 +185,11 @@ public class DoubleLinearOpsTensorAlgebra : TODO("ANDREI") } - private fun luMatrixDet(lu: BufferedTensor2D, pivots: BufferedTensor1D): Double { + private fun luMatrixDet(luTensor: MutableStructure2D, pivotsTensor: MutableStructure1D): Double { + val lu = luTensor.as2D() + val pivots = pivotsTensor.as1D() val m = lu.shape[0] - val sign = if((pivots[m] - m) % 2 == 0) 1.0 else -1.0 + val sign = if ((pivots[m] - m) % 2 == 0) 1.0 else -1.0 return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } } @@ -162,34 +199,34 @@ public class DoubleLinearOpsTensorAlgebra : val detTensorShape = IntArray(n - 1) { i -> shape[i] } detTensorShape[n - 2] = 1 - val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } + val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } val detTensor = DoubleTensor( detTensorShape, resBuffer ) - luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (luMatrix, pivots) -> - resBuffer[index] = luMatrixDet(luMatrix, pivots) + luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (lu, pivots) -> + resBuffer[index] = luMatrixDet(lu.as2D(), pivots.as1D()) } return detTensor } private fun luMatrixInv( - lu: BufferedTensor2D, - pivots: BufferedTensor1D, - invMatrix : BufferedTensor2D - ): Unit { + lu: MutableStructure2D, + pivots: MutableStructure1D, + invMatrix: MutableStructure2D + ) { val m = lu.shape[0] for (j in 0 until m) { for (i in 0 until m) { - if (pivots[i] == j){ + if (pivots[i] == j) { invMatrix[i, j] = 1.0 } - for (k in 0 until i){ + for (k in 0 until i) { invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] } } @@ -205,13 +242,12 @@ public class DoubleLinearOpsTensorAlgebra : public fun DoubleTensor.invLU(): DoubleTensor { val (luTensor, pivotsTensor) = lu() - val n = shape.size val invTensor = luTensor.zeroesLike() val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) for ((luP, invMatrix) in seq) { val (lu, pivots) = luP - luMatrixInv(lu, pivots, invMatrix) + luMatrixInv(lu.as2D(), pivots.as1D(), invMatrix.as2D()) } return invTensor diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 0a2e8c86c..b25f0164b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,8 +1,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.linear.Matrix import space.kscience.kmath.nd.MutableStructure2D -import space.kscience.kmath.nd.Structure2D +import space.kscience.kmath.nd.as2D import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra import kotlin.math.abs @@ -224,6 +223,23 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra, + b: MutableStructure2D, + res: MutableStructure2D, + l: Int, m: Int, n: Int + ) { + for (i in 0 until l) { + for (j in 0 until n) { + var curr = 0.0 + for (k in 0 until m) { + curr += a[i, k] * b[k, j] + } + res[i, j] = curr + } + } + } + override fun DoubleTensor.dot(other: DoubleTensor): DoubleTensor { if (this.shape.size == 1 && other.shape.size == 1) { return DoubleTensor(intArrayOf(1), doubleArrayOf(this.times(other).buffer.array().sum())) @@ -240,7 +256,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Boolean): Boolean { - if (!(this.shape contentEquals other.shape)) { - return false - } - return this.eq(other, eqFunction) - } + public fun DoubleTensor.contentEquals(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean = + this.eq(other, eqFunction) - public fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { - // todo broadcasting checking + private fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { + checkShapesCompatible(this, other) val n = this.linearStructure.size if (n != other.linearStructure.size) { return false diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index c644a295c..247ed3913 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -11,14 +11,14 @@ internal inline fun , "Illegal empty shape provided" } -internal inline fun < TensorType : TensorStructure, +internal inline fun , TorchTensorAlgebraType : TensorAlgebra> TorchTensorAlgebraType.checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = check(buffer.isNotEmpty()) { "Illegal empty buffer provided" } -internal inline fun < TensorType : TensorStructure, +internal inline fun , TorchTensorAlgebraType : TensorAlgebra> TorchTensorAlgebraType.checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = check(buffer.size == shape.reduce(Int::times)) { @@ -56,4 +56,4 @@ internal inline fun , check(shape[n - 1] == shape[n - 2]) { "Tensor must be batches of square matrices, but they are ${shape[n - 1]} by ${shape[n - 1]} matrices" } -} +} \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 40597f539..5e6fdcdc5 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.as1D +import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray import kotlin.test.Test import kotlin.test.assertEquals From 51eca003af9daeb72a53fc05867d955d1167154c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 29 Mar 2021 22:11:34 +0100 Subject: [PATCH 071/211] Moved back value to main algebra context --- kmath-core/api/kmath-core.api | 17 +++-------------- .../kmath/tensors/ReduceOpsTensorAlgebra.kt | 7 ------- .../kscience/kmath/tensors/TensorAlgebra.kt | 2 ++ .../core/DoubleReduceOpsTensorAlgebra.kt | 18 ------------------ .../kmath/tensors/core/DoubleTensorAlgebra.kt | 7 +++++++ .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 9 +++------ .../kmath/tensors/core/TestDoubleTensor.kt | 10 +++++++++- 7 files changed, 24 insertions(+), 46 deletions(-) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ReduceOpsTensorAlgebra.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 786b81d19..373920204 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2654,10 +2654,6 @@ public final class space/kscience/kmath/tensors/LinearOpsTensorAlgebra$DefaultIm public static synthetic fun symEig$default (Lspace/kscience/kmath/tensors/LinearOpsTensorAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;ZILjava/lang/Object;)Lkotlin/Pair; } -public abstract interface class space/kscience/kmath/tensors/ReduceOpsTensorAlgebra : space/kscience/kmath/tensors/TensorAlgebra { - public abstract fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; -} - public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { public abstract fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2686,6 +2682,7 @@ public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { public abstract fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V public abstract fun transpose (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; public abstract fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun zeroesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2809,16 +2806,6 @@ public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebr public static final fun DoubleLinearOpsTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } -public final class space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/ReduceOpsTensorAlgebra { - public fun ()V - public synthetic fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; - public fun value (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Ljava/lang/Double; -} - -public final class space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebraKt { - public static final fun DoubleReduceOpsTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - public final class space/kscience/kmath/tensors/core/DoubleTensor : space/kscience/kmath/tensors/core/BufferedTensor { } @@ -2892,6 +2879,8 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public fun transpose (Lspace/kscience/kmath/tensors/core/DoubleTensor;II)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun unaryMinus (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; + public fun value (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Ljava/lang/Double; public synthetic fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; public fun view (Lspace/kscience/kmath/tensors/core/DoubleTensor;[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ReduceOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ReduceOpsTensorAlgebra.kt deleted file mode 100644 index 820b9b25b..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ReduceOpsTensorAlgebra.kt +++ /dev/null @@ -1,7 +0,0 @@ -package space.kscience.kmath.tensors - -public interface ReduceOpsTensorAlgebra> : - TensorAlgebra { - public fun TensorType.value(): T - -} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index b05105ed8..5b7515b20 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -5,6 +5,8 @@ import space.kscience.kmath.tensors.core.DoubleTensor // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { + public fun TensorType.value(): T + //https://pytorch.org/docs/stable/generated/torch.full.html public fun full(value: T, shape: IntArray): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt deleted file mode 100644 index 9a8aa9ebf..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt +++ /dev/null @@ -1,18 +0,0 @@ -package space.kscience.kmath.tensors.core - -import space.kscience.kmath.tensors.ReduceOpsTensorAlgebra - -public class DoubleReduceOpsTensorAlgebra: - DoubleTensorAlgebra(), - ReduceOpsTensorAlgebra { - - override fun DoubleTensor.value(): Double { - check(this.shape contentEquals intArrayOf(1)) { - "Inconsistent value for tensor of shape ${shape.toList()}" - } - return this.buffer.array()[this.bufferStart] - } -} - -public inline fun DoubleReduceOpsTensorAlgebra(block: DoubleReduceOpsTensorAlgebra.() -> R): R = - DoubleReduceOpsTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index b25f0164b..b418f3647 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -7,6 +7,13 @@ import kotlin.math.abs public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { + override fun DoubleTensor.value(): Double { + check(this.shape contentEquals intArrayOf(1)) { + "Inconsistent value for tensor of shape ${shape.toList()}" + } + return this.buffer.array()[this.bufferStart] + } + public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor { checkEmptyShape(shape) checkEmptyDoubleBuffer(buffer) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 3a129b03c..d2d4ffb67 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -72,11 +72,8 @@ class TestDoubleLinearOpsTensorAlgebra { @Test fun testScalarProduct() = DoubleLinearOpsTensorAlgebra { - val a = fromArray(intArrayOf(3), doubleArrayOf(1.8,2.5, 6.8)) - val b = fromArray(intArrayOf(3), doubleArrayOf(5.5,2.6, 6.4)) - DoubleReduceOpsTensorAlgebra { - assertEquals(a.dot(b).value(), 59.92) - } - + val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) + val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) + assertEquals(a.dot(b).value(), 59.92) } } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 5e6fdcdc5..4f4d9bbdf 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -10,7 +10,7 @@ import kotlin.test.assertTrue class TestDoubleTensor { @Test - fun valueTest() = DoubleReduceOpsTensorAlgebra { + fun valueTest() = DoubleTensorAlgebra { val value = 12.5 val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) @@ -37,5 +37,13 @@ class TestDoubleTensor { vector[0] = 109.56 assertEquals(tensor[intArrayOf(0,1,0)], 109.56) + + tensor.matrixSequence().forEach { + val a = it.asTensor() + val secondRow = a[1].as1D() + val secondColumn = a.transpose(0,1)[1].as1D() + assertEquals(secondColumn[0], 77.89) + assertEquals(secondRow[1], secondColumn[1]) + } } } \ No newline at end of file From d281dfca3ab869fcfb16181f82cc91b57bb4d26d Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 30 Mar 2021 11:22:55 +0100 Subject: [PATCH 072/211] Separate linear algebra utils into dedicated module --- .../kmath/tensors/core/BufferedTensor.kt | 38 ---- .../core/DoubleLinearOpsTensorAlgebra.kt | 134 +------------ .../kmath/tensors/core/DoubleTensorAlgebra.kt | 20 +- .../kscience/kmath/tensors/core/linutils.kt | 188 ++++++++++++++++++ 4 files changed, 190 insertions(+), 190 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index d99c35569..9a4d13d2c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,7 +1,5 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.MutableStructure1D -import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.TensorStructure @@ -18,9 +16,6 @@ public open class BufferedTensor( public val numel: Int get() = linearStructure.size - internal constructor(tensor: BufferedTensor) : - this(tensor.shape, tensor.buffer, tensor.bufferStart) - override fun get(index: IntArray): T = buffer[bufferStart + linearStructure.offset(index)] override fun set(index: IntArray, value: T) { @@ -35,39 +30,6 @@ public open class BufferedTensor( override fun hashCode(): Int = 0 - internal fun vectorSequence(): Sequence> = sequence { - val n = shape.size - val vectorOffset = shape[n - 1] - val vectorShape = intArrayOf(shape.last()) - for (offset in 0 until numel step vectorOffset) { - val vector = BufferedTensor(vectorShape, buffer, offset) - yield(vector) - } - } - - internal fun matrixSequence(): Sequence> = sequence { - check(shape.size >= 2) { "todo" } - val n = shape.size - val matrixOffset = shape[n - 1] * shape[n - 2] - val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) - for (offset in 0 until numel step matrixOffset) { - val matrix = BufferedTensor(matrixShape, buffer, offset) - yield(matrix) - } - } - - internal inline fun forEachVector(vectorAction: (BufferedTensor) -> Unit): Unit { - for (vector in vectorSequence()) { - vectorAction(vector) - } - } - - internal inline fun forEachMatrix(matrixAction: (BufferedTensor) -> Unit): Unit { - for (matrix in matrixSequence()) { - matrixAction(matrix) - } - } - } public class IntTensor internal constructor( diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 0d19fd3f6..b81cf0364 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,11 +1,8 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.MutableStructure1D -import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D -import space.kscience.kmath.tensors.LinearOpsTensorAlgebra -import kotlin.math.sqrt public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -15,48 +12,6 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.det(): DoubleTensor = detLU() - private inline fun luHelper(lu: MutableStructure2D, pivots: MutableStructure1D, m: Int) { - for (row in 0 until m) pivots[row] = row - - for (i in 0 until m) { - var maxVal = -1.0 - var maxInd = i - - for (k in i until m) { - val absA = kotlin.math.abs(lu[k, i]) - if (absA > maxVal) { - maxVal = absA - maxInd = k - } - } - - //todo check singularity - - if (maxInd != i) { - - val j = pivots[i] - pivots[i] = pivots[maxInd] - pivots[maxInd] = j - - for (k in 0 until m) { - val tmp = lu[i, k] - lu[i, k] = lu[maxInd, k] - lu[maxInd, k] = tmp - } - - pivots[m] += 1 - - } - - for (j in i + 1 until m) { - lu[j, i] /= lu[i, i] - for (k in i + 1 until m) { - lu[j, k] -= lu[j, i] * lu[i, k] - } - } - } - } - override fun DoubleTensor.lu(): Pair { checkSquareMatrix(shape) @@ -80,37 +35,6 @@ public class DoubleLinearOpsTensorAlgebra : } - private inline fun pivInit( - p: MutableStructure2D, - pivot: MutableStructure1D, - n: Int - ) { - for (i in 0 until n) { - p[i, pivot[i]] = 1.0 - } - } - - private inline fun luPivotHelper( - l: MutableStructure2D, - u: MutableStructure2D, - lu: MutableStructure2D, - n: Int - ) { - for (i in 0 until n) { - for (j in 0 until n) { - if (i == j) { - l[i, j] = 1.0 - } - if (j < i) { - l[i, j] = lu[i, j] - } - if (j >= i) { - u[i, j] = lu[i, j] - } - } - } - } - override fun luPivot( luTensor: DoubleTensor, pivotsTensor: IntTensor @@ -139,27 +63,6 @@ public class DoubleLinearOpsTensorAlgebra : } - private inline fun choleskyHelper( - a: MutableStructure2D, - l: MutableStructure2D, - n: Int - ) { - for (i in 0 until n) { - for (j in 0 until i) { - var h = a[i, j] - for (k in 0 until j) { - h -= l[i, k] * l[j, k] - } - l[i, j] = h / l[j, j] - } - var h = a[i, i] - for (j in 0 until i) { - h -= l[i, j] * l[i, j] - } - l[i, i] = sqrt(h) - } - } - override fun DoubleTensor.cholesky(): DoubleTensor { // todo checks checkSquareMatrix(shape) @@ -185,14 +88,6 @@ public class DoubleLinearOpsTensorAlgebra : TODO("ANDREI") } - private fun luMatrixDet(luTensor: MutableStructure2D, pivotsTensor: MutableStructure1D): Double { - val lu = luTensor.as2D() - val pivots = pivotsTensor.as1D() - val m = lu.shape[0] - val sign = if ((pivots[m] - m) % 2 == 0) 1.0 else -1.0 - return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } - } - public fun DoubleTensor.detLU(): DoubleTensor { val (luTensor, pivotsTensor) = lu() val n = shape.size @@ -213,33 +108,6 @@ public class DoubleLinearOpsTensorAlgebra : return detTensor } - private fun luMatrixInv( - lu: MutableStructure2D, - pivots: MutableStructure1D, - invMatrix: MutableStructure2D - ) { - val m = lu.shape[0] - - for (j in 0 until m) { - for (i in 0 until m) { - if (pivots[i] == j) { - invMatrix[i, j] = 1.0 - } - - for (k in 0 until i) { - invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] - } - } - - for (i in m - 1 downTo 0) { - for (k in i + 1 until m) { - invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] - } - invMatrix[i, j] /= lu[i, i] - } - } - } - public fun DoubleTensor.invLU(): DoubleTensor { val (luTensor, pivotsTensor) = lu() val invTensor = luTensor.zeroesLike() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index b418f3647..c878fc58c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,8 +1,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.MutableStructure2D -import space.kscience.kmath.nd.as2D import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra +import space.kscience.kmath.nd.as2D import kotlin.math.abs public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { @@ -230,23 +229,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra, - b: MutableStructure2D, - res: MutableStructure2D, - l: Int, m: Int, n: Int - ) { - for (i in 0 until l) { - for (j in 0 until n) { - var curr = 0.0 - for (k in 0 until m) { - curr += a[i, k] * b[k, j] - } - res[i, j] = curr - } - } - } - override fun DoubleTensor.dot(other: DoubleTensor): DoubleTensor { if (this.shape.size == 1 && other.shape.size == 1) { return DoubleTensor(intArrayOf(1), doubleArrayOf(this.times(other).buffer.array().sum())) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt new file mode 100644 index 000000000..e78cc33c7 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -0,0 +1,188 @@ +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.nd.MutableStructure1D +import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.nd.as1D +import space.kscience.kmath.nd.as2D +import kotlin.math.sqrt + + +internal inline fun BufferedTensor.vectorSequence(): Sequence> = sequence { + val n = shape.size + val vectorOffset = shape[n - 1] + val vectorShape = intArrayOf(shape.last()) + for (offset in 0 until numel step vectorOffset) { + val vector = BufferedTensor(vectorShape, buffer, offset) + yield(vector) + } +} + +internal inline fun BufferedTensor.matrixSequence(): Sequence> = sequence { + check(shape.size >= 2) { "todo" } + val n = shape.size + val matrixOffset = shape[n - 1] * shape[n - 2] + val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) + for (offset in 0 until numel step matrixOffset) { + val matrix = BufferedTensor(matrixShape, buffer, offset) + yield(matrix) + } +} + +internal inline fun BufferedTensor.forEachVector(vectorAction: (BufferedTensor) -> Unit): Unit { + for (vector in vectorSequence()) { + vectorAction(vector) + } +} + +internal inline fun BufferedTensor.forEachMatrix(matrixAction: (BufferedTensor) -> Unit): Unit { + for (matrix in matrixSequence()) { + matrixAction(matrix) + } +} + + +internal inline fun dotHelper( + a: MutableStructure2D, + b: MutableStructure2D, + res: MutableStructure2D, + l: Int, m: Int, n: Int +) { + for (i in 0 until l) { + for (j in 0 until n) { + var curr = 0.0 + for (k in 0 until m) { + curr += a[i, k] * b[k, j] + } + res[i, j] = curr + } + } +} + +internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStructure1D, m: Int) { + for (row in 0 until m) pivots[row] = row + + for (i in 0 until m) { + var maxVal = -1.0 + var maxInd = i + + for (k in i until m) { + val absA = kotlin.math.abs(lu[k, i]) + if (absA > maxVal) { + maxVal = absA + maxInd = k + } + } + + //todo check singularity + + if (maxInd != i) { + + val j = pivots[i] + pivots[i] = pivots[maxInd] + pivots[maxInd] = j + + for (k in 0 until m) { + val tmp = lu[i, k] + lu[i, k] = lu[maxInd, k] + lu[maxInd, k] = tmp + } + + pivots[m] += 1 + + } + + for (j in i + 1 until m) { + lu[j, i] /= lu[i, i] + for (k in i + 1 until m) { + lu[j, k] -= lu[j, i] * lu[i, k] + } + } + } +} + +internal inline fun pivInit( + p: MutableStructure2D, + pivot: MutableStructure1D, + n: Int +) { + for (i in 0 until n) { + p[i, pivot[i]] = 1.0 + } +} + +internal inline fun luPivotHelper( + l: MutableStructure2D, + u: MutableStructure2D, + lu: MutableStructure2D, + n: Int +) { + for (i in 0 until n) { + for (j in 0 until n) { + if (i == j) { + l[i, j] = 1.0 + } + if (j < i) { + l[i, j] = lu[i, j] + } + if (j >= i) { + u[i, j] = lu[i, j] + } + } + } +} + +internal inline fun choleskyHelper( + a: MutableStructure2D, + l: MutableStructure2D, + n: Int +) { + for (i in 0 until n) { + for (j in 0 until i) { + var h = a[i, j] + for (k in 0 until j) { + h -= l[i, k] * l[j, k] + } + l[i, j] = h / l[j, j] + } + var h = a[i, i] + for (j in 0 until i) { + h -= l[i, j] * l[i, j] + } + l[i, i] = sqrt(h) + } +} + +internal inline fun luMatrixDet(luTensor: MutableStructure2D, pivotsTensor: MutableStructure1D): Double { + val lu = luTensor.as2D() + val pivots = pivotsTensor.as1D() + val m = lu.shape[0] + val sign = if ((pivots[m] - m) % 2 == 0) 1.0 else -1.0 + return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } +} + +internal inline fun luMatrixInv( + lu: MutableStructure2D, + pivots: MutableStructure1D, + invMatrix: MutableStructure2D +) { + val m = lu.shape[0] + + for (j in 0 until m) { + for (i in 0 until m) { + if (pivots[i] == j) { + invMatrix[i, j] = 1.0 + } + + for (k in 0 until i) { + invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] + } + } + + for (i in m - 1 downTo 0) { + for (k in i + 1 until m) { + invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] + } + invMatrix[i, j] /= lu[i, i] + } + } +} From 2503d35ba8629055aaffc03f6b2e12e2030d7dd3 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Tue, 30 Mar 2021 14:53:19 +0300 Subject: [PATCH 073/211] complete qr + test qr and lu --- .../core/DoubleLinearOpsTensorAlgebra.kt | 51 +++++++++++++++++-- .../core/TestDoubleLinearOpsAlgebra.kt | 46 +++++++++++++++++ 2 files changed, 92 insertions(+), 5 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 1558e6af9..59ec944f2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -118,7 +118,8 @@ public class DoubleLinearOpsTensorAlgebra : //todo checks checkSquareMatrix(luTensor.shape) check( - luTensor.shape.dropLast(1).toIntArray() contentEquals pivotsTensor.shape + luTensor.shape.dropLast(2).toIntArray() contentEquals pivotsTensor.shape.dropLast(1).toIntArray() || + luTensor.shape.last() == pivotsTensor.shape.last() - 1 ) { "Bed shapes ((" } //todo rewrite val n = luTensor.shape.last() @@ -173,16 +174,56 @@ public class DoubleLinearOpsTensorAlgebra : return lTensor } - private fun matrixQR( - matrix: Structure2D, + private fun MutableStructure1D.dot(other: MutableStructure1D): Double { + var res = 0.0 + for (i in 0 until size) { + res += this[i] * other[i] + } + return res + } + + private fun MutableStructure1D.l2Norm(): Double { + var squareSum = 0.0 + for (i in 0 until size) { + squareSum += this[i] * this[i] + } + return sqrt(squareSum) + } + + fun qrHelper( + matrix: MutableStructure2D, q: MutableStructure2D, r: MutableStructure2D ) { - + //todo check square + val n = matrix.colNum + for (j in 0 until n) { + val v = matrix.columns[j] + if (j > 0) { + for (i in 0 until j) { + r[i, j] = q.columns[i].dot(matrix.columns[j]) + for (k in 0 until n) { + v[k] = v[k] - r[i, j] * q.columns[i][k] + } + } + } + r[j, j] = v.l2Norm() + for (i in 0 until n) { + q[i, j] = v[i] / r[j, j] + } + } } override fun DoubleTensor.qr(): Pair { - TODO("ANDREI") + checkSquareMatrix(shape) + val qTensor = zeroesLike() + val rTensor = zeroesLike() + val seq = matrixSequence().zip((qTensor.matrixSequence().zip(rTensor.matrixSequence()))) + for ((matrix, qr) in seq) { + val (q, r) = qr + qrHelper(matrix.as2D(), q.as2D(), r.as2D()) + } + return Pair(qTensor, rTensor) } override fun DoubleTensor.svd(): Triple { diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index d2d4ffb67..b79c54dd1 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -76,4 +76,50 @@ class TestDoubleLinearOpsTensorAlgebra { val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) assertEquals(a.dot(b).value(), 59.92) } + + @Test + fun testQR() = DoubleLinearOpsTensorAlgebra { + val shape = intArrayOf(2, 2, 2) + val buffer = doubleArrayOf( + 1.0, 3.0, + 1.0, 2.0, + 1.5, 1.0, + 10.0, 2.0 + ) + + val tensor = fromArray(shape, buffer) + + val (q, r) = tensor.qr() + + assertTrue { q.shape contentEquals shape } + assertTrue { r.shape contentEquals shape } + + assertTrue { q.dot(r).buffer.array().epsEqual(buffer) } + + //todo check orthogonality/upper triang. + } + + @Test + fun testLU() = DoubleLinearOpsTensorAlgebra { + val shape = intArrayOf(2, 2, 2) + val buffer = doubleArrayOf( + 1.0, 3.0, + 1.0, 2.0, + 1.5, 1.0, + 10.0, 2.0 + ) + val tensor = fromArray(shape, buffer) + + val (lu, pivots) = tensor.lu() + + // todo check lu + + val (p, l, u) = luPivot(lu, pivots) + + assertTrue { p.shape contentEquals shape } + assertTrue { l.shape contentEquals shape } + assertTrue { u.shape contentEquals shape } + + assertTrue { p.dot(tensor).buffer.array().epsEqual(l.dot(u).buffer.array()) } + } } From 139534fdb343b984c94f5bc089df34b9e1d5946b Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Tue, 30 Mar 2021 15:13:45 +0300 Subject: [PATCH 074/211] fix --- .../kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 59ec944f2..6be50e710 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -183,11 +183,7 @@ public class DoubleLinearOpsTensorAlgebra : } private fun MutableStructure1D.l2Norm(): Double { - var squareSum = 0.0 - for (i in 0 until size) { - squareSum += this[i] * this[i] - } - return sqrt(squareSum) + return sqrt((0 until size).sumOf { this[it] * this[it] }) } fun qrHelper( @@ -223,7 +219,7 @@ public class DoubleLinearOpsTensorAlgebra : val (q, r) = qr qrHelper(matrix.as2D(), q.as2D(), r.as2D()) } - return Pair(qTensor, rTensor) + return qTensor to rTensor } override fun DoubleTensor.svd(): Triple { From 370bab462cae6d883677d0ed5cda7e0b885caa96 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 30 Mar 2021 13:14:09 +0100 Subject: [PATCH 075/211] merged pull request --- .../core/DoubleLinearOpsTensorAlgebra.kt | 40 ------------------- .../kscience/kmath/tensors/core/linutils.kt | 40 +++++++++++++++++++ 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 46ab5f80f..13fb18c01 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -77,46 +77,6 @@ public class DoubleLinearOpsTensorAlgebra : return lTensor } - private fun MutableStructure1D.dot(other: MutableStructure1D): Double { - var res = 0.0 - for (i in 0 until size) { - res += this[i] * other[i] - } - return res - } - - private fun MutableStructure1D.l2Norm(): Double { - var squareSum = 0.0 - for (i in 0 until size) { - squareSum += this[i] * this[i] - } - return sqrt(squareSum) - } - - fun qrHelper( - matrix: MutableStructure2D, - q: MutableStructure2D, - r: MutableStructure2D - ) { - //todo check square - val n = matrix.colNum - for (j in 0 until n) { - val v = matrix.columns[j] - if (j > 0) { - for (i in 0 until j) { - r[i, j] = q.columns[i].dot(matrix.columns[j]) - for (k in 0 until n) { - v[k] = v[k] - r[i, j] * q.columns[i][k] - } - } - } - r[j, j] = v.l2Norm() - for (i in 0 until n) { - q[i, j] = v[i] / r[j, j] - } - } - } - override fun DoubleTensor.qr(): Pair { checkSquareMatrix(shape) val qTensor = zeroesLike() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index e78cc33c7..49a4384c2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -186,3 +186,43 @@ internal inline fun luMatrixInv( } } } + +internal inline fun MutableStructure1D.dot(other: MutableStructure1D): Double { + var res = 0.0 + for (i in 0 until size) { + res += this[i] * other[i] + } + return res +} + +internal inline fun MutableStructure1D.l2Norm(): Double { + var squareSum = 0.0 + for (i in 0 until size) { + squareSum += this[i] * this[i] + } + return sqrt(squareSum) +} + +internal inline fun qrHelper( + matrix: MutableStructure2D, + q: MutableStructure2D, + r: MutableStructure2D +) { + //todo check square + val n = matrix.colNum + for (j in 0 until n) { + val v = matrix.columns[j] + if (j > 0) { + for (i in 0 until j) { + r[i, j] = q.columns[i].dot(matrix.columns[j]) + for (k in 0 until n) { + v[k] = v[k] - r[i, j] * q.columns[i][k] + } + } + } + r[j, j] = v.l2Norm() + for (i in 0 until n) { + q[i, j] = v[i] / r[j, j] + } + } +} From 581c13c573179dd9b2b67e65a4a2c84047ed9171 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 30 Mar 2021 14:14:05 +0100 Subject: [PATCH 076/211] drop code duplication --- kmath-core/api/kmath-core.api | 6 +-- .../core/DoubleLinearOpsTensorAlgebra.kt | 2 +- .../kscience/kmath/tensors/core/linutils.kt | 42 +++++++------------ 3 files changed, 20 insertions(+), 30 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 373920204..634f38bed 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2645,7 +2645,7 @@ public abstract interface class space/kscience/kmath/tensors/LinearOpsTensorAlge public abstract fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun lu (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; public abstract fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; - public abstract fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; public abstract fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; public abstract fun symEig (Lspace/kscience/kmath/nd/MutableStructureND;Z)Lkotlin/Pair; } @@ -2794,8 +2794,8 @@ public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebr public fun lu (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Pair; public synthetic fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; public fun luPivot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/IntTensor;)Lkotlin/Triple; - public synthetic fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun qr (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; + public fun qr (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Pair; public synthetic fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; public fun svd (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Triple; public synthetic fun symEig (Lspace/kscience/kmath/nd/MutableStructureND;Z)Lkotlin/Pair; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 13fb18c01..3d2d21e0c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -84,7 +84,7 @@ public class DoubleLinearOpsTensorAlgebra : val seq = matrixSequence().zip((qTensor.matrixSequence().zip(rTensor.matrixSequence()))) for ((matrix, qr) in seq) { val (q, r) = qr - qrHelper(matrix.as2D(), q.as2D(), r.as2D()) + qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) } return Pair(qTensor, rTensor) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index 49a4384c2..4067de5f4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -187,42 +187,32 @@ internal inline fun luMatrixInv( } } -internal inline fun MutableStructure1D.dot(other: MutableStructure1D): Double { - var res = 0.0 - for (i in 0 until size) { - res += this[i] * other[i] - } - return res -} - -internal inline fun MutableStructure1D.l2Norm(): Double { - var squareSum = 0.0 - for (i in 0 until size) { - squareSum += this[i] * this[i] - } - return sqrt(squareSum) -} - -internal inline fun qrHelper( - matrix: MutableStructure2D, - q: MutableStructure2D, +internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper( + matrix: DoubleTensor, + q: DoubleTensor, r: MutableStructure2D ) { - //todo check square - val n = matrix.colNum + checkSquareMatrix(matrix.shape) + val n = matrix.shape[0] + val qM = q.as2D() + val matrixT = matrix.transpose(0,1) + val qT = q.transpose(0,1) + for (j in 0 until n) { - val v = matrix.columns[j] + val v = matrixT[j] + val vv = v.as1D() if (j > 0) { for (i in 0 until j) { - r[i, j] = q.columns[i].dot(matrix.columns[j]) + r[i, j] = qT[i].dot(matrixT[j]).value() for (k in 0 until n) { - v[k] = v[k] - r[i, j] * q.columns[i][k] + val qTi = qT[i].as1D() + vv[k] = vv[k] - r[i, j] * qTi[k] } } } - r[j, j] = v.l2Norm() + r[j, j] = DoubleAnalyticTensorAlgebra { v.dot(v).sqrt().value() } for (i in 0 until n) { - q[i, j] = v[i] / r[j, j] + qM[i, j] = vv[i] / r[j, j] } } } From 03455a3bebc617e09392e6da7ac361040babf67a Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 30 Mar 2021 14:36:59 +0100 Subject: [PATCH 077/211] infix dot forgotten --- .../space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt | 2 +- .../kotlin/space/kscience/kmath/tensors/core/linutils.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index c878fc58c..965aef1ea 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -229,7 +229,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra 0) { for (i in 0 until j) { - r[i, j] = qT[i].dot(matrixT[j]).value() + r[i, j] = (qT[i] dot matrixT[j]).value() for (k in 0 until n) { val qTi = qT[i].as1D() vv[k] = vv[k] - r[i, j] * qTi[k] } } } - r[j, j] = DoubleAnalyticTensorAlgebra { v.dot(v).sqrt().value() } + r[j, j] = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } From b5d3ca76db28552aa534f04813234047b2b6a9ae Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 30 Mar 2021 19:20:20 +0100 Subject: [PATCH 078/211] Dropping creation methods from interface --- .../kscience/kmath/tensors/TensorAlgebra.kt | 21 ------------------- .../tensors/TensorPartialDivisionAlgebra.kt | 2 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 18 ++++++++-------- .../kscience/kmath/tensors/core/utils.kt | 8 ++++++- 4 files changed, 17 insertions(+), 32 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 5b7515b20..d7c6eaefd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -1,29 +1,10 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.tensors.core.DoubleTensor - // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { public fun TensorType.value(): T - //https://pytorch.org/docs/stable/generated/torch.full.html - public fun full(value: T, shape: IntArray): TensorType - - public fun ones(shape: IntArray): TensorType - public fun zeros(shape: IntArray): TensorType - - //https://pytorch.org/docs/stable/generated/torch.full_like.html#torch.full_like - public fun TensorType.fullLike(value: T): TensorType - - public fun TensorType.zeroesLike(): TensorType - public fun TensorType.onesLike(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.eye.html - public fun eye(n: Int): TensorType - - public fun TensorType.copy(): TensorType - public operator fun T.plus(other: TensorType): TensorType public operator fun TensorType.plus(value: T): TensorType public operator fun TensorType.plus(other: TensorType): TensorType @@ -53,8 +34,6 @@ public interface TensorAlgebra> { public fun TensorType.view(shape: IntArray): TensorType public fun TensorType.viewAs(other: TensorType): TensorType - public fun TensorType.eq(other: TensorType, delta: T): Boolean - //https://pytorch.org/docs/stable/generated/torch.matmul.html public infix fun TensorType.dot(other: TensorType): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt index 67b9c9d73..0b9079967 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Division_Algebra public interface TensorPartialDivisionAlgebra> : - TensorAlgebra { + TensorAlgebra { public operator fun TensorType.div(value: T): TensorType public operator fun TensorType.div(other: TensorType): TensorType public operator fun TensorType.divAssign(value: T) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 965aef1ea..323ade45d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -27,27 +27,27 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra abs(x - y) < delta } } - override fun DoubleTensor.eq(other: DoubleTensor, delta: Double): Boolean { + public fun DoubleTensor.eq(other: DoubleTensor, delta: Double): Boolean { return this.eq(other) { x, y -> abs(x - y) < delta } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 591ebb89c..33e78db33 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -1,7 +1,8 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.structures.* - +import kotlin.random.Random +import kotlin.math.* /** * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. @@ -34,3 +35,8 @@ internal fun Buffer.array(): DoubleArray = when (this) { is DoubleBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") } + +internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { + val u = Random(seed) + return (0 until n).map { sqrt(-2.0 * u.nextDouble()) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() +} From 07b6f988c296592cc28c93de12009fced255f43d Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 30 Mar 2021 19:31:42 +0100 Subject: [PATCH 079/211] forgot ln --- .../kotlin/space/kscience/kmath/tensors/core/utils.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 33e78db33..d8a073d64 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -38,5 +38,5 @@ internal fun Buffer.array(): DoubleArray = when (this) { internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { val u = Random(seed) - return (0 until n).map { sqrt(-2.0 * u.nextDouble()) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() + return (0 until n).map { sqrt(-2.0 * ln(u.nextDouble())) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() } From 6305acea68a8b34e9ddd01b7daf1711f17829151 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 31 Mar 2021 08:32:53 +0100 Subject: [PATCH 080/211] API dump --- kmath-core/api/kmath-core.api | 36 +++++++++-------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 634f38bed..f0e749d2b 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2655,21 +2655,14 @@ public final class space/kscience/kmath/tensors/LinearOpsTensorAlgebra$DefaultIm } public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { - public abstract fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun eq (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Z - public abstract fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun fullLike (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V public abstract fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun ones ([I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun onesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2685,8 +2678,6 @@ public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { public abstract fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; public abstract fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun zeroesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun zeros ([I)Lspace/kscience/kmath/nd/MutableStructureND; } public final class space/kscience/kmath/tensors/TensorAlgebra$DefaultImpls { @@ -2814,8 +2805,7 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z public static synthetic fun contentEquals$default (Lspace/kscience/kmath/tensors/core/DoubleTensorAlgebra;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;DILjava/lang/Object;)Z - public synthetic fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun copy (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun copy (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public fun diagonalEmbedding (Lspace/kscience/kmath/tensors/core/DoubleTensor;III)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2828,16 +2818,12 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V public synthetic fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun dot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun eq (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Z public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Z - public fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z - public synthetic fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z + public final fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public final fun fromArray ([I[D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun full (D[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun fullLike (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun fullLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun full (D[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun fullLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public fun get (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public final fun map (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/tensors/core/DoubleTensor; @@ -2851,10 +2837,8 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun ones ([I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun ones ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun onesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun onesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun ones ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun onesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public fun plus (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2885,10 +2869,8 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public fun view (Lspace/kscience/kmath/tensors/core/DoubleTensor;[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun viewAs (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun zeroesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun zeroesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun zeros ([I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun zeros ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun zeroesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun zeros ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; } public final class space/kscience/kmath/tensors/core/DoubleTensorAlgebraKt { From 5abd63cde28fcf63e72809799b10211647adb73b Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 31 Mar 2021 09:07:45 +0100 Subject: [PATCH 081/211] moving to kmath-tensors module --- kmath-core/api/kmath-core.api | 278 ------------------ kmath-tensors/build.gradle.kts | 16 + .../kmath/tensors/AnalyticTensorAlgebra.kt | 0 .../kmath/tensors/LinearOpsTensorAlgebra.kt | 0 .../kscience/kmath/tensors/TensorAlgebra.kt | 0 .../tensors/TensorPartialDivisionAlgebra.kt | 0 .../kscience/kmath/tensors/TensorStructure.kt | 0 .../core/BroadcastDoubleTensorAlgebra.kt | 0 .../kmath/tensors/core/BufferedTensor.kt | 0 .../core/DoubleAnalyticTensorAlgebra.kt | 0 .../core/DoubleLinearOpsTensorAlgebra.kt | 0 .../kmath/tensors/core/DoubleTensorAlgebra.kt | 0 .../tensors/core/TensorLinearStructure.kt | 0 .../kscience/kmath/tensors/core/checks.kt | 0 .../kscience/kmath/tensors/core/linutils.kt | 0 .../kscience/kmath/tensors/core/utils.kt | 0 .../kmath/tensors/core/TestBroadcasting.kt | 0 .../core/TestDoubleAnalyticTensorAlgebra.kt | 0 .../core/TestDoubleLinearOpsAlgebra.kt | 0 .../kmath/tensors/core/TestDoubleTensor.kt | 0 .../tensors/core/TestDoubleTensorAlgebra.kt | 0 settings.gradle.kts | 1 + 22 files changed, 17 insertions(+), 278 deletions(-) create mode 100644 kmath-tensors/build.gradle.kts rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt (100%) rename {kmath-core => kmath-tensors}/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt (100%) rename {kmath-core => kmath-tensors}/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt (100%) rename {kmath-core => kmath-tensors}/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt (100%) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index cc6c93c20..fee874b12 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2602,281 +2602,3 @@ public final class space/kscience/kmath/structures/VirtualMutableBuffer : space/ public fun set (ILjava/lang/Object;)V } -public abstract interface class space/kscience/kmath/tensors/AnalyticTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { - public abstract fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun acosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun asin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun asinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun atan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun atanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun ceil (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun exp (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun floor (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun log (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun sin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun sinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun sqrt (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun tan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun tanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; -} - -public abstract interface class space/kscience/kmath/tensors/LinearOpsTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { - public abstract fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun lu (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; - public abstract fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; - public abstract fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; - public abstract fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; - public abstract fun symEig (Lspace/kscience/kmath/nd/MutableStructureND;Z)Lkotlin/Pair; -} - -public final class space/kscience/kmath/tensors/LinearOpsTensorAlgebra$DefaultImpls { - public static synthetic fun symEig$default (Lspace/kscience/kmath/tensors/LinearOpsTensorAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;ZILjava/lang/Object;)Lkotlin/Pair; -} - -public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { - public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public abstract fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public abstract fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun times (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public abstract fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun transpose (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; - public abstract fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; -} - -public final class space/kscience/kmath/tensors/TensorAlgebra$DefaultImpls { - public static synthetic fun diagonalEmbedding$default (Lspace/kscience/kmath/tensors/TensorAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;IIIILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; -} - -public abstract interface class space/kscience/kmath/tensors/TensorPartialDivisionAlgebra : space/kscience/kmath/tensors/TensorAlgebra { - public abstract fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public abstract fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V -} - -public final class space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra { - public fun ()V - public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun div (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun minus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun plus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun times (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun timesAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V -} - -public final class space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebraKt { - public static final fun BroadcastDoubleTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - -public class space/kscience/kmath/tensors/core/BufferedTensor : space/kscience/kmath/nd/MutableStructureND { - public fun ([ILspace/kscience/kmath/structures/MutableBuffer;I)V - public fun elements ()Lkotlin/sequences/Sequence; - public fun equals (Ljava/lang/Object;)Z - public fun get ([I)Ljava/lang/Object; - public final fun getBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; - public fun getDimension ()I - public final fun getLinearStructure ()Lspace/kscience/kmath/tensors/core/TensorLinearStructure; - public final fun getNumel ()I - public fun getShape ()[I - public fun hashCode ()I - public fun set ([ILjava/lang/Object;)V -} - -public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/AnalyticTensorAlgebra { - public fun ()V - public synthetic fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun acos (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun acosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun acosh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun asin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun asin (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun asinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun asinh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun atan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun atan (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun atanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun atanh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun ceil (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun ceil (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun cos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cos (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun cosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cosh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun exp (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun exp (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun floor (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun floor (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun log (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun log (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun sin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sin (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun sinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sinh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun sqrt (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sqrt (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun tan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun tan (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun tanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun tanh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; -} - -public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebraKt { - public static final fun DoubleAnalyticTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - -public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/LinearOpsTensorAlgebra { - public fun ()V - public synthetic fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cholesky (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun det (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun detLU (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun inv (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun invLU (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun lu (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; - public fun lu (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Pair; - public synthetic fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; - public fun luPivot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/IntTensor;)Lkotlin/Triple; - public synthetic fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; - public fun qr (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Pair; - public synthetic fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; - public fun svd (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Triple; - public synthetic fun symEig (Lspace/kscience/kmath/nd/MutableStructureND;Z)Lkotlin/Pair; - public fun symEig (Lspace/kscience/kmath/tensors/core/DoubleTensor;Z)Lkotlin/Pair; -} - -public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebraKt { - public static final fun DoubleLinearOpsTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - -public final class space/kscience/kmath/tensors/core/DoubleTensor : space/kscience/kmath/tensors/core/BufferedTensor { -} - -public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { - public fun ()V - public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z - public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z - public static synthetic fun contentEquals$default (Lspace/kscience/kmath/tensors/core/DoubleTensorAlgebra;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;DILjava/lang/Object;)Z - public final fun copy (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; - public fun diagonalEmbedding (Lspace/kscience/kmath/tensors/core/DoubleTensor;III)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun div (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun div (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public synthetic fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V - public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun dot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Z - public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z - public final fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun fromArray ([I[D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun full (D[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun fullLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun get (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun map (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun minus (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun minus (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun minus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V - public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public final fun ones ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun onesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun plus (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun plus (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun plus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V - public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public fun times (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun times (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun times (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public synthetic fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun timesAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V - public fun timesAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun transpose (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; - public fun transpose (Lspace/kscience/kmath/tensors/core/DoubleTensor;II)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun unaryMinus (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; - public fun value (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Ljava/lang/Double; - public synthetic fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun view (Lspace/kscience/kmath/tensors/core/DoubleTensor;[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun viewAs (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun zeroesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun zeros ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; -} - -public final class space/kscience/kmath/tensors/core/DoubleTensorAlgebraKt { - public static final fun DoubleTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - -public final class space/kscience/kmath/tensors/core/FloatTensor : space/kscience/kmath/tensors/core/BufferedTensor { -} - -public final class space/kscience/kmath/tensors/core/IntTensor : space/kscience/kmath/tensors/core/BufferedTensor { -} - -public final class space/kscience/kmath/tensors/core/LongTensor : space/kscience/kmath/tensors/core/BufferedTensor { -} - -public final class space/kscience/kmath/tensors/core/TensorLinearStructure { - public fun ([I)V - public final fun getShape ()[I - public final fun getSize ()I - public final fun getStrides ()[I - public final fun index (I)[I - public final fun indices ()Lkotlin/sequences/Sequence; - public final fun offset ([I)I - public final fun stepIndex ([I)[I -} - diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts new file mode 100644 index 000000000..8e823416b --- /dev/null +++ b/kmath-tensors/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + id("ru.mipt.npm.gradle.mpp") +} + +kotlin.sourceSets { + commonMain { + dependencies { + api(project(":kmath-core")) + api(project(":kmath-stat")) + } + } +} + +readme { + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt similarity index 100% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt rename to kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt rename to kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt similarity index 100% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt rename to kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt similarity index 100% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt rename to kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt rename to kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt diff --git a/settings.gradle.kts b/settings.gradle.kts index 4467d5ed6..ffc93d576 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -40,5 +40,6 @@ include( ":kmath-ast", ":kmath-ejml", ":kmath-kotlingrad", + ":kmath-tensors", ":examples" ) From 706a44fd3300f050115e4b40042fe32046b181e0 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 31 Mar 2021 09:15:55 +0100 Subject: [PATCH 082/211] get normals TBD --- .../space/kscience/kmath/tensors/core/utils.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index d8a073d64..e46d39cf2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.samplers.BoxMullerNormalizedGaussianSampler import space.kscience.kmath.structures.* import kotlin.random.Random import kotlin.math.* @@ -35,8 +37,10 @@ internal fun Buffer.array(): DoubleArray = when (this) { is DoubleBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") } - -internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { - val u = Random(seed) - return (0 until n).map { sqrt(-2.0 * ln(u.nextDouble())) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() +/* +internal inline fun getRandomNormals(n: Int,): DoubleArray { + val sampler = BoxMullerNormalizedGaussianSampler.of() + val chain = sampler.sample(RandomGenerator.default) + return (0 until n).map { chain.next() }.toDoubleArray() } +*/ \ No newline at end of file From b36281fa39d810ae1e60d2e7a9e042be754b8687 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 31 Mar 2021 09:23:41 +0100 Subject: [PATCH 083/211] roll back --- .../space/kscience/kmath/tensors/core/utils.kt | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index e46d39cf2..fc0ebe7fa 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -37,10 +37,8 @@ internal fun Buffer.array(): DoubleArray = when (this) { is DoubleBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") } -/* -internal inline fun getRandomNormals(n: Int,): DoubleArray { - val sampler = BoxMullerNormalizedGaussianSampler.of() - val chain = sampler.sample(RandomGenerator.default) - return (0 until n).map { chain.next() }.toDoubleArray() -} -*/ \ No newline at end of file + +internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { + val u = Random(seed) + return (0 until n).map { sqrt(-2.0 * ln(u.nextDouble())) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() +} \ No newline at end of file From 3e98240b94b99170ffd8525d9b307ac6c715ebd6 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 1 Apr 2021 20:21:14 +0300 Subject: [PATCH 084/211] add function diagonalEmbedding with tests --- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 42 ++++++++++++++++++- .../tensors/core/TestDoubleTensorAlgebra.kt | 33 +++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) 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 323ade45d..ab692c0f9 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 @@ -283,7 +283,47 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra n || dim2 > n) { + throw RuntimeException("Dimension out of range") + } + + var lessDim = dim1 + var greaterDim = dim2 + var realOffset = offset + if (lessDim > greaterDim) { + realOffset *= -1 + lessDim = greaterDim.also {greaterDim = lessDim} + } + + val resShape = diagonalEntries.shape.slice(0 until lessDim).toIntArray() + + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + + diagonalEntries.shape.slice(lessDim until greaterDim - 1).toIntArray() + + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + + diagonalEntries.shape.slice(greaterDim - 1 until n - 1).toIntArray() + val resTensor = zeros(resShape) + + for (i in 0 until diagonalEntries.linearStructure.size) { + val multiIndex = diagonalEntries.linearStructure.index(i) + + var offset1 = 0 + var offset2 = abs(realOffset) + if (realOffset < 0) { + offset1 = offset2.also {offset2 = offset1} + } + val diagonalMultiIndex = multiIndex.slice(0 until lessDim).toIntArray() + + intArrayOf(multiIndex[n - 1] + offset1) + + multiIndex.slice(lessDim until greaterDim - 1).toIntArray() + + intArrayOf(multiIndex[n - 1] + offset2) + + multiIndex.slice(greaterDim - 1 until n - 1).toIntArray() + + resTensor[diagonalMultiIndex] = diagonalEntries[multiIndex] + } + + return resTensor } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 168d80a9d..692db69af 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -115,6 +115,39 @@ class TestDoubleTensorAlgebra { assertTrue(tensor4.dot(tensor5).shape contentEquals intArrayOf(5, 4, 2, 8, 3, 8, 5)) } + @Test + fun diagonalEmbedding() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor3 = zeros(intArrayOf(2, 3, 4, 5)) + + assertTrue(diagonalEmbedding(tensor3, 0, 3, 4).shape contentEquals + intArrayOf(2, 3, 4, 5, 5)) + assertTrue(diagonalEmbedding(tensor3, 1, 3, 4).shape contentEquals + intArrayOf(2, 3, 4, 6, 6)) + assertTrue(diagonalEmbedding(tensor3, 2, 0, 3).shape contentEquals + intArrayOf(7, 2, 3, 7, 4)) + + val diagonal1 = diagonalEmbedding(tensor1, 0, 1, 0) + assertTrue(diagonal1.shape contentEquals intArrayOf(3, 3)) + assertTrue(diagonal1.buffer.array() contentEquals + doubleArrayOf(10.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 30.0)) + + val diagonal1_offset = diagonalEmbedding(tensor1, 1, 1, 0) + assertTrue(diagonal1_offset.shape contentEquals intArrayOf(4, 4)) + assertTrue(diagonal1_offset.buffer.array() contentEquals + doubleArrayOf(0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 30.0, 0.0)) + + val diagonal2 = diagonalEmbedding(tensor2, 1, 0, 2) + assertTrue(diagonal2.shape contentEquals intArrayOf(4, 2, 4)) + assertTrue(diagonal2.buffer.array() contentEquals + doubleArrayOf( + 0.0, 1.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, + 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 5.0, 0.0, + 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 6.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) + } + @Test fun testContentEqual() = DoubleTensorAlgebra { //TODO() From 814eab8cde1dff4b94b49efbb8d93c6b0bc06002 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Tue, 6 Apr 2021 00:06:14 +0300 Subject: [PATCH 085/211] implement svd function and tests for it --- .../core/DoubleLinearOpsTensorAlgebra.kt | 77 ++++++++++++++++++- .../core/TestDoubleLinearOpsAlgebra.kt | 32 ++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index c571fe446..fbd9da18e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -3,6 +3,8 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import kotlin.math.abs +import kotlin.math.min public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -89,8 +91,81 @@ public class DoubleLinearOpsTensorAlgebra : return qTensor to rTensor } + internal fun svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { + val (n, m) = a.shape + var v: DoubleTensor + val b: DoubleTensor + if (n > m) { + b = a.transpose(0, 1).dot(a) + v = DoubleTensor(intArrayOf(m), getRandomNormals(m, 0)) + } else { + b = a.dot(a.transpose(0, 1)) + v = DoubleTensor(intArrayOf(n), getRandomNormals(n, 0)) + } + + var lastV: DoubleTensor + while (true) { + lastV = v + v = b.dot(lastV) + val norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + v = v.times(1.0 / norm) + if (abs(v.dot(lastV).value()) > 1 - epsilon) { + return v + } + } + } + override fun DoubleTensor.svd(): Triple { - TODO("ALYA") + val size = this.shape.size + val commonShape = this.shape.sliceArray(0 until size - 2) + val (n, m) = this.shape.sliceArray(size - 2 until size) + val resU = zeros(commonShape + intArrayOf(n, min(n, m))) + val resS = zeros(commonShape + intArrayOf(min(n, m))) + val resV = zeros(commonShape + intArrayOf(min(n, m), m)) + + for ((matrix, USV) in this.matrixSequence() + .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) { + val res = ArrayList>(0) + val (matrixU, SV) = USV + val (matrixS, matrixV) = SV + + for (k in 0 until min(n, m)) { + var a = matrix.asTensor().copy() + for ((singularValue, u, v) in res.slice(0 until k)) { + val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) + for (i in 0 until u.shape[0]) { + for (j in 0 until v.shape[0]) { + outerProduct[i * v.shape[0] + j] = u[i].value() * v[j].value() + } + } + a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct)) + } + var v: DoubleTensor + var u: DoubleTensor + var norm: Double + if (n > m) { + v = svd1d(a) + u = matrix.asTensor().dot(v) + norm = DoubleAnalyticTensorAlgebra { (u dot u).sqrt().value() } + u = u.times(1.0 / norm) + } else { + u = svd1d(a) + v = matrix.asTensor().transpose(0, 1).dot(u) + norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + v = v.times(1.0 / norm) + } + + res.add(Triple(norm, u, v)) + } + + val s = res.map { it.first }.toDoubleArray() + val uBuffer = res.map { it.second }.flatMap { it.buffer.array().toList() }.toDoubleArray() + val vBuffer = res.map { it.third }.flatMap { it.buffer.array().toList() }.toDoubleArray() + uBuffer.copyInto(matrixU.buffer.array()) + s.copyInto(matrixS.buffer.array()) + vBuffer.copyInto(matrixV.buffer.array()) + } + return Triple(resU, resS, resV.transpose(size - 2, size - 1)) } override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { 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 b79c54dd1..843707153 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 @@ -122,4 +122,36 @@ class TestDoubleLinearOpsTensorAlgebra { assertTrue { p.dot(tensor).buffer.array().epsEqual(l.dot(u).buffer.array()) } } + + @Test + fun svd1d() = DoubleLinearOpsTensorAlgebra { + val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + + val res = svd1d(tensor2) + + assertTrue(res.shape contentEquals intArrayOf(2)) + assertTrue { abs(abs(res.buffer.array()[res.bufferStart]) - 0.386) < 0.01} + assertTrue { abs(abs(res.buffer.array()[res.bufferStart + 1]) - 0.922) < 0.01} + } + + @Test + fun svd() = DoubleLinearOpsTensorAlgebra { + val epsilon = 1e-10 + fun test_tensor(tensor: DoubleTensor) { + val svd = tensor.svd() + + val tensorSVD = svd.first + .dot( + diagonalEmbedding(svd.second, 0, 0, 1) + .dot(svd.third.transpose(0, 1)) + ) + + for ((x1, x2) in tensor.buffer.array() zip tensorSVD.buffer.array()) { + assertTrue { abs(x1 - x2) < epsilon } + } + } + test_tensor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) + test_tensor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) + + } } From 4336788a6ba846af6a63be1352d1bec1c1f39b56 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 6 Apr 2021 09:00:13 +0100 Subject: [PATCH 086/211] Moving Alya's SVD implementation to linutils --- .../core/DoubleLinearOpsTensorAlgebra.kt | 66 +--------------- .../kscience/kmath/tensors/core/linutils.kt | 76 ++++++++++++++++++- .../core/TestDoubleLinearOpsAlgebra.kt | 4 +- 3 files changed, 78 insertions(+), 68 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index fbd9da18e..7db812d9d 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -91,29 +91,6 @@ public class DoubleLinearOpsTensorAlgebra : return qTensor to rTensor } - internal fun svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { - val (n, m) = a.shape - var v: DoubleTensor - val b: DoubleTensor - if (n > m) { - b = a.transpose(0, 1).dot(a) - v = DoubleTensor(intArrayOf(m), getRandomNormals(m, 0)) - } else { - b = a.dot(a.transpose(0, 1)) - v = DoubleTensor(intArrayOf(n), getRandomNormals(n, 0)) - } - - var lastV: DoubleTensor - while (true) { - lastV = v - v = b.dot(lastV) - val norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } - v = v.times(1.0 / norm) - if (abs(v.dot(lastV).value()) > 1 - epsilon) { - return v - } - } - } override fun DoubleTensor.svd(): Triple { val size = this.shape.size @@ -124,47 +101,8 @@ public class DoubleLinearOpsTensorAlgebra : val resV = zeros(commonShape + intArrayOf(min(n, m), m)) for ((matrix, USV) in this.matrixSequence() - .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) { - val res = ArrayList>(0) - val (matrixU, SV) = USV - val (matrixS, matrixV) = SV - - for (k in 0 until min(n, m)) { - var a = matrix.asTensor().copy() - for ((singularValue, u, v) in res.slice(0 until k)) { - val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) - for (i in 0 until u.shape[0]) { - for (j in 0 until v.shape[0]) { - outerProduct[i * v.shape[0] + j] = u[i].value() * v[j].value() - } - } - a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct)) - } - var v: DoubleTensor - var u: DoubleTensor - var norm: Double - if (n > m) { - v = svd1d(a) - u = matrix.asTensor().dot(v) - norm = DoubleAnalyticTensorAlgebra { (u dot u).sqrt().value() } - u = u.times(1.0 / norm) - } else { - u = svd1d(a) - v = matrix.asTensor().transpose(0, 1).dot(u) - norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } - v = v.times(1.0 / norm) - } - - res.add(Triple(norm, u, v)) - } - - val s = res.map { it.first }.toDoubleArray() - val uBuffer = res.map { it.second }.flatMap { it.buffer.array().toList() }.toDoubleArray() - val vBuffer = res.map { it.third }.flatMap { it.buffer.array().toList() }.toDoubleArray() - uBuffer.copyInto(matrixU.buffer.array()) - s.copyInto(matrixS.buffer.array()) - vBuffer.copyInto(matrixV.buffer.array()) - } + .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) + svdHelper(matrix.asTensor(), USV, m, n) return Triple(resU, resS, resV.transpose(size - 2, size - 1)) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index f6cf71b07..e1d5c1819 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -4,6 +4,8 @@ import space.kscience.kmath.nd.MutableStructure1D import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import kotlin.math.abs +import kotlin.math.min import kotlin.math.sqrt @@ -195,8 +197,8 @@ internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper( checkSquareMatrix(matrix.shape) val n = matrix.shape[0] val qM = q.as2D() - val matrixT = matrix.transpose(0,1) - val qT = q.transpose(0,1) + val matrixT = matrix.transpose(0, 1) + val qT = q.transpose(0, 1) for (j in 0 until n) { val v = matrixT[j] @@ -216,3 +218,73 @@ internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper( } } } + +internal inline fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { + val (n, m) = a.shape + var v: DoubleTensor + val b: DoubleTensor + if (n > m) { + b = a.transpose(0, 1).dot(a) + v = DoubleTensor(intArrayOf(m), getRandomNormals(m, 0)) + } else { + b = a.dot(a.transpose(0, 1)) + v = DoubleTensor(intArrayOf(n), getRandomNormals(n, 0)) + } + + var lastV: DoubleTensor + while (true) { + lastV = v + v = b.dot(lastV) + val norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + v = v.times(1.0 / norm) + if (abs(v.dot(lastV).value()) > 1 - epsilon) { + return v + } + } +} + +internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( + matrix: DoubleTensor, + USV: Pair, Pair, BufferedTensor>>, + m: Int, n: Int +): Unit { + val res = ArrayList>(0) + val (matrixU, SV) = USV + val (matrixS, matrixV) = SV + + for (k in 0 until min(n, m)) { + var a = matrix.copy() + for ((singularValue, u, v) in res.slice(0 until k)) { + val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) + for (i in 0 until u.shape[0]) { + for (j in 0 until v.shape[0]) { + outerProduct[i * v.shape[0] + j] = u[i].value() * v[j].value() + } + } + a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct)) + } + var v: DoubleTensor + var u: DoubleTensor + var norm: Double + if (n > m) { + v = svd1d(a) + u = matrix.dot(v) + norm = DoubleAnalyticTensorAlgebra { (u dot u).sqrt().value() } + u = u.times(1.0 / norm) + } else { + u = svd1d(a) + v = matrix.transpose(0, 1).dot(u) + norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + v = v.times(1.0 / norm) + } + + res.add(Triple(norm, u, v)) + } + + val s = res.map { it.first }.toDoubleArray() + val uBuffer = res.map { it.second }.flatMap { it.buffer.array().toList() }.toDoubleArray() + val vBuffer = res.map { it.third }.flatMap { it.buffer.array().toList() }.toDoubleArray() + uBuffer.copyInto(matrixU.buffer.array()) + s.copyInto(matrixS.buffer.array()) + vBuffer.copyInto(matrixV.buffer.array()) +} 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 843707153..60f7f4a97 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 @@ -124,7 +124,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun svd1d() = DoubleLinearOpsTensorAlgebra { + fun testSVD1D() = DoubleLinearOpsTensorAlgebra { val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = svd1d(tensor2) @@ -135,7 +135,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun svd() = DoubleLinearOpsTensorAlgebra { + fun testSVD() = DoubleLinearOpsTensorAlgebra { val epsilon = 1e-10 fun test_tensor(tensor: DoubleTensor) { val svd = tensor.svd() From dcdc22dd9dddf8d3157fb51f1ee7b6bf226b3b8c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 6 Apr 2021 11:04:00 +0100 Subject: [PATCH 087/211] SVD test to be fixed --- .../kscience/kmath/tensors/TensorAlgebra.kt | 2 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 6 ++ .../kscience/kmath/tensors/core/utils.kt | 2 - .../core/TestDoubleLinearOpsAlgebra.kt | 65 +++++++++++-------- 4 files changed, 44 insertions(+), 31 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index d7c6eaefd..966806de1 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -40,7 +40,7 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.diag_embed.html public fun diagonalEmbedding( diagonalEntries: TensorType, - offset: Int = 0, dim1: Int = -2, dim2: Int = -1 + offset: Int = 0, dim1: Int = 0, dim2: Int = 1 ): TensorType } 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 ab692c0f9..53063a066 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 @@ -362,6 +362,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra eps) { - return false - } - } - return true - } - @Test fun testDetLU() = DoubleLinearOpsTensorAlgebra { val tensor = fromArray( @@ -136,22 +121,46 @@ class TestDoubleLinearOpsTensorAlgebra { @Test fun testSVD() = DoubleLinearOpsTensorAlgebra { - val epsilon = 1e-10 - fun test_tensor(tensor: DoubleTensor) { - val svd = tensor.svd() + testSVDFor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) + testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) + } - val tensorSVD = svd.first - .dot( - diagonalEmbedding(svd.second, 0, 0, 1) - .dot(svd.third.transpose(0, 1)) - ) + @Test + fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { + val tensor = randNormal(intArrayOf(7, 5, 3), 0) + val (tensorU, tensorS, tensorV) = tensor.svd() + val tensorSVD = tensorU dot (diagonalEmbedding(tensorS,0,1,2) dot tensorV) + println(tensor.eq(tensorSVD)) + } - for ((x1, x2) in tensor.buffer.array() zip tensorSVD.buffer.array()) { - assertTrue { abs(x1 - x2) < epsilon } - } + +} + +private inline fun Double.epsEqual(other: Double, eps: Double = 1e-5): Boolean { + return abs(this - other) < eps +} + +private inline fun DoubleArray.epsEqual(other: DoubleArray, eps: Double = 1e-5): Boolean { + for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) { + if (abs(elem1 - elem2) > eps) { + return false } - test_tensor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) - test_tensor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) + } + return true +} +private inline fun DoubleLinearOpsTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10): Unit { + val svd = tensor.svd() + + val tensorSVD = svd.first + .dot( + diagonalEmbedding(svd.second, 0, 0, 1) + .dot(svd.third.transpose(0, 1)) + ) + + for ((x1, x2) in tensor.buffer.array() zip tensorSVD.buffer.array()) { + assertTrue { abs(x1 - x2) < epsilon } } } + + From 2bbe10e41c83e5ce44a920ad0a4c071b7d25f252 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 6 Apr 2021 11:41:41 +0100 Subject: [PATCH 088/211] SymEig test --- .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) 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 0bd0ff5bd..29632e771 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 @@ -1,6 +1,7 @@ package space.kscience.kmath.tensors.core import kotlin.math.abs +import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -125,12 +126,21 @@ class TestDoubleLinearOpsTensorAlgebra { testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } - @Test + @Test @Ignore fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { val tensor = randNormal(intArrayOf(7, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS,0,1,2) dot tensorV) - println(tensor.eq(tensorSVD)) + assertTrue(tensor.eq(tensorSVD)) + } + + @Test @Ignore + fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { + val tensor = randNormal(shape = intArrayOf(5, 2, 2), 0) + val tensorSigma = tensor + tensor.transpose(1, 2) + val (tensorS, tensorV) = tensorSigma.symEig() + val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS, 0,1,2) dot tensorV.transpose(1, 2)) + assertTrue(tensorSigma.eq(tensorSigmaCalc)) } From 174f6566e116b43e70622785c58291532b170369 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 6 Apr 2021 12:07:39 +0100 Subject: [PATCH 089/211] Negative indices --- .../kscience/kmath/tensors/TensorAlgebra.kt | 4 ++-- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 20 +++++++++++-------- .../tensors/core/TensorLinearStructure.kt | 3 +++ .../kscience/kmath/tensors/core/utils.kt | 12 ++++++++++- .../core/TestDoubleLinearOpsAlgebra.kt | 4 ++-- .../tensors/core/TestDoubleTensorAlgebra.kt | 4 ++-- 6 files changed, 32 insertions(+), 15 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 966806de1..8fd1cf2ed 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -28,7 +28,7 @@ public interface TensorAlgebra> { public operator fun TensorType.get(i: Int): TensorType //https://pytorch.org/docs/stable/generated/torch.transpose.html - public fun TensorType.transpose(i: Int, j: Int): TensorType + public fun TensorType.transpose(i: Int = -2, j: Int = -1): TensorType //https://pytorch.org/docs/stable/tensor_view.html public fun TensorType.view(shape: IntArray): TensorType @@ -40,7 +40,7 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.diag_embed.html public fun diagonalEmbedding( diagonalEntries: TensorType, - offset: Int = 0, dim1: Int = 0, dim2: Int = 1 + offset: Int = 0, dim1: Int = -2, dim2: Int = -1 ): TensorType } 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 53063a066..870dbe8a7 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 @@ -198,19 +198,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra n || dim2 > n) { + if (d1 > n || d2 > n) { throw RuntimeException("Dimension out of range") } - var lessDim = dim1 - var greaterDim = dim2 + var lessDim = d1 + var greaterDim = d2 var realOffset = offset if (lessDim > greaterDim) { realOffset *= -1 diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt index 97ce29657..47745c2be 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt @@ -73,6 +73,9 @@ public class TensorLinearStructure(public val shape: IntArray) public val size: Int get() = shape.reduce(Int::times) + public val dim: Int + get() = shape.size + public fun indices(): Sequence = (0 until size).asSequence().map { index(it) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 5fd3cfd28..785b59ede 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -39,4 +39,14 @@ internal fun Buffer.array(): DoubleArray = when (this) { internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { val u = Random(seed) return (0 until n).map { sqrt(-2.0 * ln(u.nextDouble())) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() -} \ No newline at end of file +} + +internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { + val ii = n + i + check(ii >= 0) { + "Out of bound index $i for tensor of dim $n" + } + ii +} + +internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.linearStructure.dim, i) \ No newline at end of file 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 29632e771..56f9332f6 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 @@ -130,7 +130,7 @@ class TestDoubleLinearOpsTensorAlgebra { fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { val tensor = randNormal(intArrayOf(7, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() - val tensorSVD = tensorU dot (diagonalEmbedding(tensorS,0,1,2) dot tensorV) + val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV) assertTrue(tensor.eq(tensorSVD)) } @@ -139,7 +139,7 @@ class TestDoubleLinearOpsTensorAlgebra { val tensor = randNormal(shape = intArrayOf(5, 2, 2), 0) val tensorSigma = tensor + tensor.transpose(1, 2) val (tensorS, tensorV) = tensorSigma.symEig() - val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS, 0,1,2) dot tensorV.transpose(1, 2)) + val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose(1, 2)) assertTrue(tensorSigma.eq(tensorSigmaCalc)) } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 692db69af..fa7a8fd32 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -35,8 +35,8 @@ class TestDoubleTensorAlgebra { fun transpose1x2x3() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transpose(0, 1) - val res02 = tensor.transpose(0, 2) - val res12 = tensor.transpose(1, 2) + val res02 = tensor.transpose(-3, 2) + val res12 = tensor.transpose() assertTrue(res01.shape contentEquals intArrayOf(2, 1, 3)) assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) From 74dfca4e2e265a17bcba9b4d968a56ddd5d07ad9 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 7 Apr 2021 15:11:00 +0100 Subject: [PATCH 090/211] Using kmath-stat for random normals --- .../kotlin/space/kscience/kmath/tensors/core/utils.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 785b59ede..c99f9d156 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.samplers.GaussianSampler +import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.* -import kotlin.random.Random -import kotlin.math.* /** * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. @@ -37,8 +37,9 @@ internal fun Buffer.array(): DoubleArray = when (this) { } internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { - val u = Random(seed) - return (0 until n).map { sqrt(-2.0 * ln(u.nextDouble())) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() + val distribution = GaussianSampler(0.0, 1.0) + val generator = RandomGenerator.default(seed) + return distribution.sample(generator).nextBufferBlocking(n).toDoubleArray() } internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { From ea4d6618b4c2c7ecc22f82c4376b2b06904ff7c2 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 8 Apr 2021 23:58:44 +0300 Subject: [PATCH 091/211] fix bugs in svd --- .../tensors/core/DoubleLinearOpsTensorAlgebra.kt | 14 ++++++++++---- .../kscience/kmath/tensors/core/linutils.kt | 16 +++++++++++----- .../space/kscience/kmath/tensors/core/utils.kt | 7 +++++++ .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 4 ++-- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 7db812d9d..83a41b80d 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -96,14 +96,20 @@ public class DoubleLinearOpsTensorAlgebra : val size = this.shape.size val commonShape = this.shape.sliceArray(0 until size - 2) val (n, m) = this.shape.sliceArray(size - 2 until size) - val resU = zeros(commonShape + intArrayOf(n, min(n, m))) + val resU = zeros(commonShape + intArrayOf(min(n, m), n)) val resS = zeros(commonShape + intArrayOf(min(n, m))) val resV = zeros(commonShape + intArrayOf(min(n, m), m)) for ((matrix, USV) in this.matrixSequence() - .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) - svdHelper(matrix.asTensor(), USV, m, n) - return Triple(resU, resS, resV.transpose(size - 2, size - 1)) + .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) { + val size = matrix.shape.reduce { acc, i -> acc * i } + val curMatrix = DoubleTensor( + matrix.shape, + matrix.buffer.array().slice(matrix.bufferStart until matrix.bufferStart + size).toDoubleArray() + ) + svdHelper(curMatrix, USV, m, n) + } + return Triple(resU.transpose(size - 2, size - 1), resS, resV) } override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index e1d5c1819..1bdfee2d5 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -225,10 +225,10 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: val b: DoubleTensor if (n > m) { b = a.transpose(0, 1).dot(a) - v = DoubleTensor(intArrayOf(m), getRandomNormals(m, 0)) + v = DoubleTensor(intArrayOf(m), getRandomUnitVector(m, 0)) } else { b = a.dot(a.transpose(0, 1)) - v = DoubleTensor(intArrayOf(n), getRandomNormals(n, 0)) + v = DoubleTensor(intArrayOf(n), getRandomUnitVector(n, 0)) } var lastV: DoubleTensor @@ -284,7 +284,13 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( val s = res.map { it.first }.toDoubleArray() val uBuffer = res.map { it.second }.flatMap { it.buffer.array().toList() }.toDoubleArray() val vBuffer = res.map { it.third }.flatMap { it.buffer.array().toList() }.toDoubleArray() - uBuffer.copyInto(matrixU.buffer.array()) - s.copyInto(matrixS.buffer.array()) - vBuffer.copyInto(matrixV.buffer.array()) + for (i in uBuffer.indices) { + matrixU.buffer.array()[matrixU.bufferStart + i] = uBuffer[i] + } + for (i in s.indices) { + matrixS.buffer.array()[matrixS.bufferStart + i] = s[i] + } + for (i in vBuffer.indices) { + matrixV.buffer.array()[matrixV.bufferStart + i] = vBuffer[i] + } } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index c99f9d156..392abd1c2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -3,6 +3,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.* +import kotlin.math.sqrt /** * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. @@ -42,6 +43,12 @@ internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { return distribution.sample(generator).nextBufferBlocking(n).toDoubleArray() } +internal inline fun getRandomUnitVector(n: Int, seed: Long): DoubleArray { + val unnorm = getRandomNormals(n, seed) + val norm = sqrt(unnorm.map { it * it }.sum()) + return unnorm.map { it / norm }.toDoubleArray() +} + internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { val ii = n + i check(ii >= 0) { 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 56f9332f6..35390968e 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 @@ -126,9 +126,9 @@ class TestDoubleLinearOpsTensorAlgebra { testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } - @Test @Ignore + @Test fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { - val tensor = randNormal(intArrayOf(7, 5, 3), 0) + val tensor = randNormal(intArrayOf(1, 15, 4, 7, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV) assertTrue(tensor.eq(tensorSVD)) From a09a1c7adc73615d46b4fa5d1611c3a694b8d5a8 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 07:33:25 +0100 Subject: [PATCH 092/211] Fixed tests --- .../core/DoubleLinearOpsTensorAlgebra.kt | 6 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 7 --- .../kscience/kmath/tensors/core/checks.kt | 3 +- .../core/TestDoubleLinearOpsAlgebra.kt | 63 ++++++++----------- 4 files changed, 31 insertions(+), 48 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 83a41b80d..916361abe 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -93,7 +93,7 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.svd(): Triple { - val size = this.shape.size + val size = this.linearStructure.dim val commonShape = this.shape.sliceArray(0 until size - 2) val (n, m) = this.shape.sliceArray(size - 2 until size) val resU = zeros(commonShape + intArrayOf(min(n, m), n)) @@ -109,11 +109,11 @@ public class DoubleLinearOpsTensorAlgebra : ) svdHelper(curMatrix, USV, m, n) } - return Triple(resU.transpose(size - 2, size - 1), resS, resV) + return Triple(resU.transpose(), resS, resV.transpose()) } override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { - TODO("ANDREI") + TODO() } public fun DoubleTensor.detLU(): DoubleTensor { 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 870dbe8a7..8f355dd3d 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 @@ -339,19 +339,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra abs(x - y) < delta } - } - public fun DoubleTensor.eq(other: DoubleTensor, delta: Double): Boolean { return this.eq(other) { x, y -> abs(x - y) < delta } } public fun DoubleTensor.eq(other: DoubleTensor): Boolean = this.eq(other, 1e-5) - public fun DoubleTensor.contentEquals(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean = - this.eq(other, eqFunction) - private fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { checkShapesCompatible(this, other) val n = this.linearStructure.size diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 247ed3913..f994324ff 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -56,4 +56,5 @@ internal inline fun , check(shape[n - 1] == shape[n - 2]) { "Tensor must be batches of square matrices, but they are ${shape[n - 1]} by ${shape[n - 1]} matrices" } -} \ No newline at end of file +} + 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 35390968e..df896bace 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 @@ -20,15 +20,17 @@ class TestDoubleLinearOpsTensorAlgebra { ) ) - val expectedShape = intArrayOf(2, 1) - val expectedBuffer = doubleArrayOf( - -1.0, - -7.0 + val expectedTensor = fromArray( + intArrayOf(2, 1), + doubleArrayOf( + -1.0, + -7.0 + ) ) val detTensor = tensor.detLU() - assertTrue { detTensor.shape contentEquals expectedShape } - assertTrue { detTensor.buffer.array().epsEqual(expectedBuffer) } + assertTrue(detTensor.eq(expectedTensor)) + } @Test @@ -43,17 +45,17 @@ class TestDoubleLinearOpsTensorAlgebra { ) ) - val expectedShape = intArrayOf(2, 2, 2) - val expectedBuffer = doubleArrayOf( - 1.0, 0.0, - 0.0, 0.5, - 0.0, 1.0, - 1.0, -1.0 + val expectedTensor = fromArray( + intArrayOf(2, 2, 2), doubleArrayOf( + 1.0, 0.0, + 0.0, 0.5, + 0.0, 1.0, + 1.0, -1.0 + ) ) val invTensor = tensor.invLU() - assertTrue { invTensor.shape contentEquals expectedShape } - assertTrue { invTensor.buffer.array().epsEqual(expectedBuffer) } + assertTrue(invTensor.eq(expectedTensor)) } @Test @@ -80,7 +82,7 @@ class TestDoubleLinearOpsTensorAlgebra { assertTrue { q.shape contentEquals shape } assertTrue { r.shape contentEquals shape } - assertTrue { q.dot(r).buffer.array().epsEqual(buffer) } + assertTrue((q dot r).eq(tensor)) //todo check orthogonality/upper triang. } @@ -106,7 +108,7 @@ class TestDoubleLinearOpsTensorAlgebra { assertTrue { l.shape contentEquals shape } assertTrue { u.shape contentEquals shape } - assertTrue { p.dot(tensor).buffer.array().epsEqual(l.dot(u).buffer.array()) } + assertTrue((p dot tensor).eq(l dot u)) } @Test @@ -116,8 +118,8 @@ class TestDoubleLinearOpsTensorAlgebra { val res = svd1d(tensor2) assertTrue(res.shape contentEquals intArrayOf(2)) - assertTrue { abs(abs(res.buffer.array()[res.bufferStart]) - 0.386) < 0.01} - assertTrue { abs(abs(res.buffer.array()[res.bufferStart + 1]) - 0.922) < 0.01} + assertTrue { abs(abs(res.buffer.array()[res.bufferStart]) - 0.386) < 0.01 } + assertTrue { abs(abs(res.buffer.array()[res.bufferStart + 1]) - 0.922) < 0.01 } } @Test @@ -130,11 +132,12 @@ class TestDoubleLinearOpsTensorAlgebra { fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { val tensor = randNormal(intArrayOf(1, 15, 4, 7, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() - val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV) + val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) assertTrue(tensor.eq(tensorSVD)) } - @Test @Ignore + @Test + @Ignore fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { val tensor = randNormal(shape = intArrayOf(5, 2, 2), 0) val tensorSigma = tensor + tensor.transpose(1, 2) @@ -146,31 +149,17 @@ class TestDoubleLinearOpsTensorAlgebra { } -private inline fun Double.epsEqual(other: Double, eps: Double = 1e-5): Boolean { - return abs(this - other) < eps -} - -private inline fun DoubleArray.epsEqual(other: DoubleArray, eps: Double = 1e-5): Boolean { - for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) { - if (abs(elem1 - elem2) > eps) { - return false - } - } - return true -} private inline fun DoubleLinearOpsTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10): Unit { val svd = tensor.svd() val tensorSVD = svd.first .dot( - diagonalEmbedding(svd.second, 0, 0, 1) - .dot(svd.third.transpose(0, 1)) + diagonalEmbedding(svd.second) + .dot(svd.third.transpose()) ) - for ((x1, x2) in tensor.buffer.array() zip tensorSVD.buffer.array()) { - assertTrue { abs(x1 - x2) < epsilon } - } + assertTrue(tensor.eq(tensorSVD, epsilon)) } From 8c1131dd5818f75b1b0eb9e0b3ef23f12f6a7c07 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 08:03:47 +0100 Subject: [PATCH 093/211] Approaching SymEig through SVD --- .../kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 6 ++++-- .../kotlin/space/kscience/kmath/tensors/core/checks.kt | 4 ++++ .../kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 916361abe..43502e79a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -67,7 +67,7 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.cholesky(): DoubleTensor { - // todo checks + checkSymmetric(this) checkSquareMatrix(shape) val n = shape.last() @@ -113,7 +113,9 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { - TODO() + checkSymmetric(this) + val svd = this.svd() + TODO("U might have some columns negative to V") } public fun DoubleTensor.detLU(): DoubleTensor { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index f994324ff..1f70eb300 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -58,3 +58,7 @@ internal inline fun , } } +internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor): Unit = + check(tensor.eq(tensor.transpose())){ + "Tensor is not symmetric about the last 2 dimensions" + } \ No newline at end of file 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 df896bace..cc127b5a7 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 @@ -140,9 +140,9 @@ class TestDoubleLinearOpsTensorAlgebra { @Ignore fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { val tensor = randNormal(shape = intArrayOf(5, 2, 2), 0) - val tensorSigma = tensor + tensor.transpose(1, 2) + val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() - val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose(1, 2)) + val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) assertTrue(tensorSigma.eq(tensorSigmaCalc)) } From 5d8b42da906fec8c5450a4babf461a4873a8aee9 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 08:29:08 +0100 Subject: [PATCH 094/211] minor corrections to linear stuff --- .../kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 43502e79a..4e67e1d16 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -67,6 +67,7 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.cholesky(): DoubleTensor { + //positive definite check checkSymmetric(this) checkSquareMatrix(shape) @@ -114,8 +115,7 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { checkSymmetric(this) - val svd = this.svd() - TODO("U might have some columns negative to V") + TODO("maybe use SVD") } public fun DoubleTensor.detLU(): DoubleTensor { From e4dbabc30f5a740deae2055c33c982637463d85e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 08:32:03 +0100 Subject: [PATCH 095/211] more infor --- .../kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 4e67e1d16..7d99b7b51 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -115,6 +115,8 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { checkSymmetric(this) + //http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html + //see the last point TODO("maybe use SVD") } From 3f0dff3ce9f830f6c04ac72346eb6053c61ae0bf Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 09:18:00 +0100 Subject: [PATCH 096/211] Approximate spectral decomposition for symmetric matrices based on SVD --- .../tensors/core/DoubleLinearOpsTensorAlgebra.kt | 11 ++++++++--- .../kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 6 +++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 7d99b7b51..268f2fe55 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -3,8 +3,10 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.structures.toList import kotlin.math.abs import kotlin.math.min +import kotlin.math.sign public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -113,11 +115,14 @@ public class DoubleLinearOpsTensorAlgebra : return Triple(resU.transpose(), resS, resV.transpose()) } + //http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { checkSymmetric(this) - //http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html - //see the last point - TODO("maybe use SVD") + val (u, s, v) = this.svd() + val shp = s.shape + intArrayOf(1) + val utv = (u.transpose() dot v).map { if (abs(it) < 0.99) 0.0 else sign(it) } + val eig = (utv dot s.view(shp)).view(s.shape) + return Pair(eig, v) } public fun DoubleTensor.detLU(): DoubleTensor { 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 cc127b5a7..c96fcb1c0 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 @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.structures.toList import kotlin.math.abs import kotlin.test.Ignore import kotlin.test.Test @@ -137,13 +138,12 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - @Ignore fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { - val tensor = randNormal(shape = intArrayOf(5, 2, 2), 0) + val tensor = randNormal(shape = intArrayOf(5, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) - assertTrue(tensorSigma.eq(tensorSigmaCalc)) + assertTrue(tensorSigma.eq(tensorSigmaCalc, 0.01)) } From fe8579180d8ebe92b8ba2a41a74d5932d90694a9 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 09:56:37 +0100 Subject: [PATCH 097/211] Open epsilon to client to control numerical precision for power methods --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 4 ++-- .../core/DoubleLinearOpsTensorAlgebra.kt | 17 +++++++++++------ .../space/kscience/kmath/tensors/core/checks.kt | 6 +++--- .../kscience/kmath/tensors/core/linutils.kt | 6 +++--- .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 2 +- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index d980c510f..87c459f35 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.tensors -public interface LinearOpsTensorAlgebra, IndexTensorType: TensorStructure> : +public interface LinearOpsTensorAlgebra, IndexTensorType : TensorStructure> : TensorPartialDivisionAlgebra { //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det @@ -26,6 +26,6 @@ public interface LinearOpsTensorAlgebra, Inde public fun TensorType.svd(): Triple //https://pytorch.org/docs/stable/generated/torch.symeig.html - public fun TensorType.symEig(eigenvectors: Boolean = true): Pair + public fun TensorType.symEig(): Pair } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 268f2fe55..95b668917 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -94,8 +94,10 @@ public class DoubleLinearOpsTensorAlgebra : return qTensor to rTensor } + override fun DoubleTensor.svd(): Triple = + svd(epsilon = 1e-10) - override fun DoubleTensor.svd(): Triple { + public fun DoubleTensor.svd(epsilon: Double): Triple { val size = this.linearStructure.dim val commonShape = this.shape.sliceArray(0 until size - 2) val (n, m) = this.shape.sliceArray(size - 2 until size) @@ -110,17 +112,20 @@ public class DoubleLinearOpsTensorAlgebra : matrix.shape, matrix.buffer.array().slice(matrix.bufferStart until matrix.bufferStart + size).toDoubleArray() ) - svdHelper(curMatrix, USV, m, n) + svdHelper(curMatrix, USV, m, n, epsilon) } return Triple(resU.transpose(), resS, resV.transpose()) } + override fun DoubleTensor.symEig(): Pair = + symEig(epsilon = 1e-15) + //http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html - override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { - checkSymmetric(this) - val (u, s, v) = this.svd() + public fun DoubleTensor.symEig(epsilon: Double): Pair { + checkSymmetric(this, epsilon) + val (u, s, v) = this.svd(epsilon) val shp = s.shape + intArrayOf(1) - val utv = (u.transpose() dot v).map { if (abs(it) < 0.99) 0.0 else sign(it) } + val utv = (u.transpose() dot v).map { if (abs(it) < 0.9) 0.0 else sign(it) } val eig = (utv dot s.view(shp)).view(s.shape) return Pair(eig, v) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 1f70eb300..1dde2ea56 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -58,7 +58,7 @@ internal inline fun , } } -internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor): Unit = - check(tensor.eq(tensor.transpose())){ - "Tensor is not symmetric about the last 2 dimensions" +internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor, epsilon: Double = 1e-6): Unit = + check(tensor.eq(tensor.transpose(), epsilon)) { + "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index 1bdfee2d5..685c16a1b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -246,7 +246,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( matrix: DoubleTensor, USV: Pair, Pair, BufferedTensor>>, - m: Int, n: Int + m: Int, n: Int, epsilon: Double ): Unit { val res = ArrayList>(0) val (matrixU, SV) = USV @@ -267,12 +267,12 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( var u: DoubleTensor var norm: Double if (n > m) { - v = svd1d(a) + v = svd1d(a, epsilon) u = matrix.dot(v) norm = DoubleAnalyticTensorAlgebra { (u dot u).sqrt().value() } u = u.times(1.0 / norm) } else { - u = svd1d(a) + u = svd1d(a, epsilon) v = matrix.transpose(0, 1).dot(u) norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } v = v.times(1.0 / norm) 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 c96fcb1c0..0997a9b86 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 @@ -143,7 +143,7 @@ class TestDoubleLinearOpsTensorAlgebra { val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) - assertTrue(tensorSigma.eq(tensorSigmaCalc, 0.01)) + assertTrue(tensorSigma.eq(tensorSigmaCalc)) } From a692412cff00241031258e37e1f7c2ad151518f4 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 10:08:55 +0100 Subject: [PATCH 098/211] Safer cleaner for symeig --- .../tensors/core/DoubleLinearOpsTensorAlgebra.kt | 10 ++++++---- .../space/kscience/kmath/tensors/core/linutils.kt | 12 ++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 95b668917..c26046e37 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -3,10 +3,8 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D -import space.kscience.kmath.structures.toList -import kotlin.math.abs import kotlin.math.min -import kotlin.math.sign + public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -125,7 +123,11 @@ public class DoubleLinearOpsTensorAlgebra : checkSymmetric(this, epsilon) val (u, s, v) = this.svd(epsilon) val shp = s.shape + intArrayOf(1) - val utv = (u.transpose() dot v).map { if (abs(it) < 0.9) 0.0 else sign(it) } + val utv = u.transpose() dot v + val n = s.shape.last() + for( matrix in utv.matrixSequence()) + cleanSymHelper(matrix.as2D(),n) + val eig = (utv dot s.view(shp)).view(s.shape) return Pair(eig, v) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index 685c16a1b..b3cfc1092 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -6,6 +6,7 @@ import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import kotlin.math.abs import kotlin.math.min +import kotlin.math.sign import kotlin.math.sqrt @@ -294,3 +295,14 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( matrixV.buffer.array()[matrixV.bufferStart + i] = vBuffer[i] } } + +internal inline fun cleanSymHelper(matrix: MutableStructure2D, n: Int): Unit { + for (i in 0 until n) + for (j in 0 until n) { + if (i == j) { + matrix[i, j] = sign(matrix[i, j]) + } else { + matrix[i, j] = 0.0 + } + } +} From 1e8da7a87bcc00830338d66f8d68fb2dfda7698b Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 10:53:36 +0100 Subject: [PATCH 099/211] Cholesky decomp tests and checks - det to be fixed --- .../tensors/core/DoubleLinearOpsTensorAlgebra.kt | 3 ++- .../space/kscience/kmath/tensors/core/checks.kt | 9 ++++++++- .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 13 +++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index c26046e37..4d6d14764 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -67,9 +67,10 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.cholesky(): DoubleTensor { - //positive definite check checkSymmetric(this) checkSquareMatrix(shape) + //TODO("Andrei the det routine has bugs") + //checkPositiveDefinite(this) val n = shape.last() val lTensor = zeroesLike() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 1dde2ea56..8dbf9eb81 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -61,4 +61,11 @@ internal inline fun , internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor, epsilon: Double = 1e-6): Unit = check(tensor.eq(tensor.transpose(), epsilon)) { "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" - } \ No newline at end of file + } + +internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor): Unit { + for( mat in tensor.matrixSequence()) + check(mat.asTensor().detLU().value() > 0.0){ + "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" + } +} \ No newline at end of file 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 0997a9b86..2914b216b 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 @@ -112,6 +112,19 @@ class TestDoubleLinearOpsTensorAlgebra { assertTrue((p dot tensor).eq(l dot u)) } + @Test + fun testCholesky() = DoubleLinearOpsTensorAlgebra { + val tensor = randNormal(intArrayOf(2, 5, 5), 0) + val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( + fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) + ) + //checkPositiveDefinite(sigma) sigma must be positive definite + val low = sigma.cholesky() + val sigmChol = low dot low.transpose() + assertTrue(sigma.eq(sigmChol)) + + } + @Test fun testSVD1D() = DoubleLinearOpsTensorAlgebra { val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) From b51427d2abb401d1402eebd7bf61e93bca47f3a2 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 12:26:03 +0100 Subject: [PATCH 100/211] test to fix determinant --- .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 2914b216b..37caf88fe 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 @@ -34,6 +34,19 @@ class TestDoubleLinearOpsTensorAlgebra { } + @Test + fun testDet() = DoubleLinearOpsTensorAlgebra { + val m = fromArray( + intArrayOf(3, 3), doubleArrayOf( + 2.1843, 1.4391, -0.4845, + 1.4391, 1.7772, 0.4055, + -0.4845, 0.4055, 0.7519 + ) + ) + println(m.det().value()) + println(0.0197) //expected value + } + @Test fun testInvLU() = DoubleLinearOpsTensorAlgebra { val tensor = fromArray( From 75783bcb038d1649f5587a15e906d9450fce5c8c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 14:06:44 +0100 Subject: [PATCH 101/211] some todos --- .../kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 4d6d14764..82f63dd40 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -154,6 +154,7 @@ public class DoubleLinearOpsTensorAlgebra : } public fun DoubleTensor.invLU(): DoubleTensor { + //TODO("Andrei the det is non-zero") val (luTensor, pivotsTensor) = lu() val invTensor = luTensor.zeroesLike() From a2d41d5e73e8eef1413a4f1671d0717b8b97aa9b Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 14 Apr 2021 20:30:42 +0100 Subject: [PATCH 102/211] Cholesky with precision in client API --- .../kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 7 ++++--- .../kotlin/space/kscience/kmath/tensors/core/checks.kt | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 82f63dd40..e0ec49333 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -66,11 +66,10 @@ public class DoubleLinearOpsTensorAlgebra : } - override fun DoubleTensor.cholesky(): DoubleTensor { - checkSymmetric(this) + public fun DoubleTensor.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) //TODO("Andrei the det routine has bugs") - //checkPositiveDefinite(this) + //checkPositiveDefinite(this, epsilon) val n = shape.last() val lTensor = zeroesLike() @@ -81,6 +80,8 @@ public class DoubleLinearOpsTensorAlgebra : return lTensor } + override fun DoubleTensor.cholesky(): DoubleTensor = cholesky(1e-6) + override fun DoubleTensor.qr(): Pair { checkSquareMatrix(shape) val qTensor = zeroesLike() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 8dbf9eb81..730b6ed9a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -63,7 +63,9 @@ internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor, eps "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } -internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor): Unit { +internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( + tensor: DoubleTensor, epsilon: Double = 1e-6): Unit { + checkSymmetric(tensor, epsilon) for( mat in tensor.matrixSequence()) check(mat.asTensor().detLU().value() > 0.0){ "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" From c7669d4fba20ccd856918504d4836d2619961927 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 14 Apr 2021 23:05:54 +0300 Subject: [PATCH 103/211] fix det --- .../core/DoubleLinearOpsTensorAlgebra.kt | 22 +++++++++---- .../kscience/kmath/tensors/core/checks.kt | 10 ++++++ .../kscience/kmath/tensors/core/linutils.kt | 11 +++++-- .../core/TestDoubleLinearOpsAlgebra.kt | 17 ++++++++-- kmath-tensors/src/jvmMain/kotlin/andMain.kt | 32 +++++++++++++++++++ 5 files changed, 81 insertions(+), 11 deletions(-) create mode 100644 kmath-tensors/src/jvmMain/kotlin/andMain.kt diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 82f63dd40..59678947a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -14,8 +14,7 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.det(): DoubleTensor = detLU() - override fun DoubleTensor.lu(): Pair { - + internal fun DoubleTensor.luForDet(forDet: Boolean = false): Pair { checkSquareMatrix(shape) val luTensor = copy() @@ -31,10 +30,22 @@ public class DoubleLinearOpsTensorAlgebra : ) for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) - luHelper(lu.as2D(), pivots.as1D(), m) + try { + luHelper(lu.as2D(), pivots.as1D(), m) + } catch (e: RuntimeException) { + if (forDet) { + lu.as2D()[intArrayOf(0, 0)] = 0.0 + } else { + throw IllegalStateException("LUP decomposition can't be performed") + } + } + return Pair(luTensor, pivotsTensor) + } + override fun DoubleTensor.lu(): Pair { + return luForDet(false) } override fun luPivot( @@ -69,8 +80,7 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.cholesky(): DoubleTensor { checkSymmetric(this) checkSquareMatrix(shape) - //TODO("Andrei the det routine has bugs") - //checkPositiveDefinite(this) + checkPositiveDefinite(this) val n = shape.last() val lTensor = zeroesLike() @@ -134,7 +144,7 @@ public class DoubleLinearOpsTensorAlgebra : } public fun DoubleTensor.detLU(): DoubleTensor { - val (luTensor, pivotsTensor) = lu() + val (luTensor, pivotsTensor) = luForDet(forDet = true) val n = shape.size val detTensorShape = IntArray(n - 1) { i -> shape[i] } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 8dbf9eb81..c61759da2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -2,6 +2,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.TensorAlgebra import space.kscience.kmath.tensors.TensorStructure +import kotlin.math.abs internal inline fun , @@ -68,4 +69,13 @@ internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite(tensor: D check(mat.asTensor().detLU().value() > 0.0){ "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" } +} + +internal inline fun DoubleLinearOpsTensorAlgebra.checkNonSingularMatrix(tensor: DoubleTensor): Unit { + for( mat in tensor.matrixSequence()) { + val detTensor = mat.asTensor().detLU() + check(!(detTensor.eq(detTensor.zeroesLike()))){ + "Tensor contains matrices which are singular" + } + } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index b3cfc1092..f2c9d8c76 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -62,10 +62,10 @@ internal inline fun dotHelper( } internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStructure1D, m: Int) { - for (row in 0 until m) pivots[row] = row + for (row in 0..m) pivots[row] = row for (i in 0 until m) { - var maxVal = -1.0 + var maxVal = 0.0 var maxInd = i for (k in i until m) { @@ -76,7 +76,9 @@ internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStru } } - //todo check singularity + if (abs(maxVal) < 1e-9) { + throw RuntimeException() + } if (maxInd != i) { @@ -158,6 +160,9 @@ internal inline fun choleskyHelper( internal inline fun luMatrixDet(luTensor: MutableStructure2D, pivotsTensor: MutableStructure1D): Double { val lu = luTensor.as2D() val pivots = pivotsTensor.as1D() + if (lu[0, 0] == 0.0) { + return 0.0 + } val m = lu.shape[0] val sign = if ((pivots[m] - m) % 2 == 0) 1.0 else -1.0 return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } 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 37caf88fe..75ff12355 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 @@ -36,6 +36,7 @@ class TestDoubleLinearOpsTensorAlgebra { @Test fun testDet() = DoubleLinearOpsTensorAlgebra { + val expectedValue = 0.019827417 val m = fromArray( intArrayOf(3, 3), doubleArrayOf( 2.1843, 1.4391, -0.4845, @@ -43,8 +44,20 @@ class TestDoubleLinearOpsTensorAlgebra { -0.4845, 0.4055, 0.7519 ) ) - println(m.det().value()) - println(0.0197) //expected value + + assertTrue { abs(m.det().value() - expectedValue) < 1e-5} + } + + @Test + fun testDetSingle() = DoubleLinearOpsTensorAlgebra { + val expectedValue = 48.151623 + val m = fromArray( + intArrayOf(1, 1), doubleArrayOf( + expectedValue + ) + ) + + assertTrue { abs(m.det().value() - expectedValue) < 1e-5} } @Test diff --git a/kmath-tensors/src/jvmMain/kotlin/andMain.kt b/kmath-tensors/src/jvmMain/kotlin/andMain.kt new file mode 100644 index 000000000..68facf467 --- /dev/null +++ b/kmath-tensors/src/jvmMain/kotlin/andMain.kt @@ -0,0 +1,32 @@ +import space.kscience.kmath.nd.* +import space.kscience.kmath.tensors.core.DoubleLinearOpsTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.array +import kotlin.math.abs +import kotlin.math.sqrt + + +fun main() { + + DoubleTensorAlgebra { + val tensor = fromArray( + intArrayOf(2, 2, 2), + doubleArrayOf( + 1.0, 3.0, + 1.0, 2.0, + 1.5, 1.0, + 10.0, 2.0 + ) + ) + val tensor2 = fromArray( + intArrayOf(2, 2), + doubleArrayOf( + 0.0, 0.0, + 0.0, 0.0 + ) + ) + DoubleLinearOpsTensorAlgebra { + println(tensor2.det().value()) + } + } +} From aeb71b5d270f7e40f8c5b8c2416c163e6baec206 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 14 Apr 2021 23:10:42 +0300 Subject: [PATCH 104/211] fix det --- .../core/DoubleLinearOpsTensorAlgebra.kt | 28 +++++++++++++------ .../kscience/kmath/tensors/core/checks.kt | 14 +++++++++- .../kscience/kmath/tensors/core/linutils.kt | 11 ++++++-- .../core/TestDoubleLinearOpsAlgebra.kt | 17 +++++++++-- 4 files changed, 56 insertions(+), 14 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 82f63dd40..027fcf5d0 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -14,8 +14,7 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.det(): DoubleTensor = detLU() - override fun DoubleTensor.lu(): Pair { - + internal fun DoubleTensor.luForDet(forDet: Boolean = false): Pair { checkSquareMatrix(shape) val luTensor = copy() @@ -31,10 +30,22 @@ public class DoubleLinearOpsTensorAlgebra : ) for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) - luHelper(lu.as2D(), pivots.as1D(), m) + try { + luHelper(lu.as2D(), pivots.as1D(), m) + } catch (e: RuntimeException) { + if (forDet) { + lu.as2D()[intArrayOf(0, 0)] = 0.0 + } else { + throw IllegalStateException("LUP decomposition can't be performed") + } + } + return Pair(luTensor, pivotsTensor) + } + override fun DoubleTensor.lu(): Pair { + return luForDet(false) } override fun luPivot( @@ -66,11 +77,10 @@ public class DoubleLinearOpsTensorAlgebra : } - override fun DoubleTensor.cholesky(): DoubleTensor { - checkSymmetric(this) + public fun DoubleTensor.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) - //TODO("Andrei the det routine has bugs") - //checkPositiveDefinite(this) + checkPositiveDefinite(this) + //checkPositiveDefinite(this, epsilon) val n = shape.last() val lTensor = zeroesLike() @@ -81,6 +91,8 @@ public class DoubleLinearOpsTensorAlgebra : return lTensor } + override fun DoubleTensor.cholesky(): DoubleTensor = cholesky(1e-6) + override fun DoubleTensor.qr(): Pair { checkSquareMatrix(shape) val qTensor = zeroesLike() @@ -134,7 +146,7 @@ public class DoubleLinearOpsTensorAlgebra : } public fun DoubleTensor.detLU(): DoubleTensor { - val (luTensor, pivotsTensor) = lu() + val (luTensor, pivotsTensor) = luForDet(forDet = true) val n = shape.size val detTensorShape = IntArray(n - 1) { i -> shape[i] } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 8dbf9eb81..45a71d1bc 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -2,6 +2,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.TensorAlgebra import space.kscience.kmath.tensors.TensorStructure +import kotlin.math.abs internal inline fun , @@ -63,9 +64,20 @@ internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor, eps "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } -internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor): Unit { +internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( + tensor: DoubleTensor, epsilon: Double = 1e-6): Unit { + checkSymmetric(tensor, epsilon) for( mat in tensor.matrixSequence()) check(mat.asTensor().detLU().value() > 0.0){ "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" } +} + +internal inline fun DoubleLinearOpsTensorAlgebra.checkNonSingularMatrix(tensor: DoubleTensor): Unit { + for( mat in tensor.matrixSequence()) { + val detTensor = mat.asTensor().detLU() + check(!(detTensor.eq(detTensor.zeroesLike()))){ + "Tensor contains matrices which are singular" + } + } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index b3cfc1092..f2c9d8c76 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -62,10 +62,10 @@ internal inline fun dotHelper( } internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStructure1D, m: Int) { - for (row in 0 until m) pivots[row] = row + for (row in 0..m) pivots[row] = row for (i in 0 until m) { - var maxVal = -1.0 + var maxVal = 0.0 var maxInd = i for (k in i until m) { @@ -76,7 +76,9 @@ internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStru } } - //todo check singularity + if (abs(maxVal) < 1e-9) { + throw RuntimeException() + } if (maxInd != i) { @@ -158,6 +160,9 @@ internal inline fun choleskyHelper( internal inline fun luMatrixDet(luTensor: MutableStructure2D, pivotsTensor: MutableStructure1D): Double { val lu = luTensor.as2D() val pivots = pivotsTensor.as1D() + if (lu[0, 0] == 0.0) { + return 0.0 + } val m = lu.shape[0] val sign = if ((pivots[m] - m) % 2 == 0) 1.0 else -1.0 return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } 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 37caf88fe..75ff12355 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 @@ -36,6 +36,7 @@ class TestDoubleLinearOpsTensorAlgebra { @Test fun testDet() = DoubleLinearOpsTensorAlgebra { + val expectedValue = 0.019827417 val m = fromArray( intArrayOf(3, 3), doubleArrayOf( 2.1843, 1.4391, -0.4845, @@ -43,8 +44,20 @@ class TestDoubleLinearOpsTensorAlgebra { -0.4845, 0.4055, 0.7519 ) ) - println(m.det().value()) - println(0.0197) //expected value + + assertTrue { abs(m.det().value() - expectedValue) < 1e-5} + } + + @Test + fun testDetSingle() = DoubleLinearOpsTensorAlgebra { + val expectedValue = 48.151623 + val m = fromArray( + intArrayOf(1, 1), doubleArrayOf( + expectedValue + ) + ) + + assertTrue { abs(m.det().value() - expectedValue) < 1e-5} } @Test From b46e8c5fe23bb64fa6868363848e2e13e0c1edfb Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 14 Apr 2021 22:13:54 +0100 Subject: [PATCH 105/211] LU and det refactored --- .../core/DoubleLinearOpsTensorAlgebra.kt | 64 ++++++------------- .../kscience/kmath/tensors/core/linutils.kt | 43 +++++++++++-- .../core/TestDoubleLinearOpsAlgebra.kt | 8 +-- 3 files changed, 59 insertions(+), 56 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index a6bd5d5f7..e72948c84 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -10,43 +10,15 @@ public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, DoubleTensorAlgebra() { - override fun DoubleTensor.inv(): DoubleTensor = invLU() + override fun DoubleTensor.inv(): DoubleTensor = invLU(1e-9) - override fun DoubleTensor.det(): DoubleTensor = detLU() + override fun DoubleTensor.det(): DoubleTensor = detLU(1e-9) - internal fun DoubleTensor.luForDet(forDet: Boolean = false): Pair { - checkSquareMatrix(shape) + public fun DoubleTensor.lu(epsilon: Double): Pair = + computeLU(this, epsilon) ?: + throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon") - val luTensor = copy() - - val n = shape.size - val m = shape.last() - val pivotsShape = IntArray(n - 1) { i -> shape[i] } - pivotsShape[n - 2] = m + 1 - - val pivotsTensor = IntTensor( - pivotsShape, - IntArray(pivotsShape.reduce(Int::times)) { 0 } - ) - - for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) - try { - luHelper(lu.as2D(), pivots.as1D(), m) - } catch (e: RuntimeException) { - if (forDet) { - lu.as2D()[intArrayOf(0, 0)] = 0.0 - } else { - throw IllegalStateException("LUP decomposition can't be performed") - } - } - - - return Pair(luTensor, pivotsTensor) - } - - override fun DoubleTensor.lu(): Pair { - return luForDet(false) - } + override fun DoubleTensor.lu(): Pair = lu(1e-9) override fun luPivot( luTensor: DoubleTensor, @@ -79,9 +51,7 @@ public class DoubleLinearOpsTensorAlgebra : public fun DoubleTensor.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) - checkPositiveDefinite(this) - //checkPositiveDefinite(this, epsilon) - + checkPositiveDefinite(this, epsilon) val n = shape.last() val lTensor = zeroesLike() @@ -139,15 +109,19 @@ public class DoubleLinearOpsTensorAlgebra : val shp = s.shape + intArrayOf(1) val utv = u.transpose() dot v val n = s.shape.last() - for( matrix in utv.matrixSequence()) - cleanSymHelper(matrix.as2D(),n) + for (matrix in utv.matrixSequence()) + cleanSymHelper(matrix.as2D(), n) val eig = (utv dot s.view(shp)).view(s.shape) return Pair(eig, v) } - public fun DoubleTensor.detLU(): DoubleTensor { - val (luTensor, pivotsTensor) = luForDet(forDet = true) + public fun DoubleTensor.detLU(epsilon: Double = 1e-9): DoubleTensor { + + checkSquareMatrix(this.shape) + val luTensor = this.copy() + val pivotsTensor = this.setUpPivots() + val n = shape.size val detTensorShape = IntArray(n - 1) { i -> shape[i] } @@ -160,15 +134,15 @@ public class DoubleLinearOpsTensorAlgebra : ) luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (lu, pivots) -> - resBuffer[index] = luMatrixDet(lu.as2D(), pivots.as1D()) + resBuffer[index] = if (luHelper(lu.as2D(), pivots.as1D(), epsilon)) + 0.0 else luMatrixDet(lu.as2D(), pivots.as1D()) } return detTensor } - public fun DoubleTensor.invLU(): DoubleTensor { - //TODO("Andrei the det is non-zero") - val (luTensor, pivotsTensor) = lu() + public fun DoubleTensor.invLU(epsilon: Double = 1e-9): DoubleTensor { + val (luTensor, pivotsTensor) = lu(epsilon) val invTensor = luTensor.zeroesLike() val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index f2c9d8c76..ee159b614 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -61,7 +61,13 @@ internal inline fun dotHelper( } } -internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStructure1D, m: Int) { +internal inline fun luHelper( + lu: MutableStructure2D, + pivots: MutableStructure1D, + epsilon: Double): Boolean { + + val m = lu.rowNum + for (row in 0..m) pivots[row] = row for (i in 0 until m) { @@ -69,16 +75,15 @@ internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStru var maxInd = i for (k in i until m) { - val absA = kotlin.math.abs(lu[k, i]) + val absA = abs(lu[k, i]) if (absA > maxVal) { maxVal = absA maxInd = k } } - if (abs(maxVal) < 1e-9) { - throw RuntimeException() - } + if (abs(maxVal) < epsilon) + return true // matrix is singular if (maxInd != i) { @@ -103,6 +108,34 @@ internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStru } } } + return false +} + +internal inline fun BufferedTensor.setUpPivots(): IntTensor { + val n = this.shape.size + val m = this.shape.last() + val pivotsShape = IntArray(n - 1) { i -> this.shape[i] } + pivotsShape[n - 2] = m + 1 + + return IntTensor( + pivotsShape, + IntArray(pivotsShape.reduce(Int::times)) { 0 } + ) +} + +internal inline fun DoubleLinearOpsTensorAlgebra.computeLU( + tensor: DoubleTensor, + epsilon: Double): Pair? { + + checkSquareMatrix(tensor.shape) + val luTensor = tensor.copy() + val pivotsTensor = tensor.setUpPivots() + + for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) + if(luHelper(lu.as2D(), pivots.as1D(), epsilon)) + return null + + return Pair(luTensor, pivotsTensor) } internal inline fun pivInit( 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 75ff12355..d19d0b6f6 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 @@ -1,8 +1,6 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.structures.toList import kotlin.math.abs -import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -45,7 +43,7 @@ class TestDoubleLinearOpsTensorAlgebra { ) ) - assertTrue { abs(m.det().value() - expectedValue) < 1e-5} + assertTrue { abs(m.det().value() - expectedValue) < 1e-5 } } @Test @@ -57,7 +55,7 @@ class TestDoubleLinearOpsTensorAlgebra { ) ) - assertTrue { abs(m.det().value() - expectedValue) < 1e-5} + assertTrue { abs(m.det().value() - expectedValue) < 1e-5 } } @Test @@ -144,11 +142,9 @@ class TestDoubleLinearOpsTensorAlgebra { val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) ) - //checkPositiveDefinite(sigma) sigma must be positive definite val low = sigma.cholesky() val sigmChol = low dot low.transpose() assertTrue(sigma.eq(sigmChol)) - } @Test From 0fa73e1e9e4cca8cf4377d580bbfbcceb394d8c0 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 14 Apr 2021 22:21:18 +0100 Subject: [PATCH 106/211] Drop unused code --- .../kotlin/space/kscience/kmath/tensors/core/checks.kt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 45a71d1bc..730b6ed9a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -2,7 +2,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.TensorAlgebra import space.kscience.kmath.tensors.TensorStructure -import kotlin.math.abs internal inline fun , @@ -71,13 +70,4 @@ internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( check(mat.asTensor().detLU().value() > 0.0){ "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" } -} - -internal inline fun DoubleLinearOpsTensorAlgebra.checkNonSingularMatrix(tensor: DoubleTensor): Unit { - for( mat in tensor.matrixSequence()) { - val detTensor = mat.asTensor().detLU() - check(!(detTensor.eq(detTensor.zeroesLike()))){ - "Tensor contains matrices which are singular" - } - } } \ No newline at end of file From b7da52edb196769ac5afb42ae5dbdca6bedd58f5 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Thu, 15 Apr 2021 23:10:15 +0300 Subject: [PATCH 107/211] pretty printer --- .../kscience/kmath/tensors/core/utils.kt | 48 +++++++++++++- .../src/jvmMain/kotlin/tensorPrettyPrinter.kt | 64 +++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 392abd1c2..e67591c9e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.as1D +import space.kscience.kmath.nd.as2D import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.* @@ -57,4 +59,48 @@ internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { ii } -internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.linearStructure.dim, i) \ No newline at end of file +internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.linearStructure.dim, i) + +public fun DoubleTensor.toPrettyString(): String = buildString { + var offset = 0 + val shape = this@toPrettyString.shape + val linearStructure = this@toPrettyString.linearStructure + var vectorSize = shape.last() + val initString = "DoubleTensor(\n" + append(initString) + var charOffset = 3 + for (vector in vectorSequence()) { + append(" ".repeat(charOffset)) + val index = linearStructure.index(offset) + for (ind in index.reversed()) { + if (ind != 0) { + break + } + append("[") + charOffset += 1 + } + // todo refactor + val values = mutableListOf() + for (i in 0 until vectorSize) { + values.add(vector[intArrayOf(i)]) + } + // todo apply exp formatting + append(values.joinToString(", ")) + append("]") + charOffset -= 1 + for ((ind, maxInd) in index.reversed().zip(shape.reversed()).drop(1)){ + if (ind != maxInd - 1) { + break + } + append("]") + charOffset -=1 + } + offset += vectorSize + // todo refactor + if (this@toPrettyString.numel == offset) { + break + } + append(",\n") + } + append("\n)") +} diff --git a/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt b/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt new file mode 100644 index 000000000..669a5494b --- /dev/null +++ b/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt @@ -0,0 +1,64 @@ + +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.vectorSequence +import java.lang.StringBuilder + +internal fun format(value: Double, digits: Int = 4): String { + val res = "%.${digits}e".format(value).replace(',', '.') + if (value < 0.0) { + return res + } + return StringBuilder().append(" ").append(res).toString() +} + +public fun DoubleTensor.toPrettyString(): String { + val builder = StringBuilder() + with(builder) { + var offset = 0 + val shape = this@toPrettyString.shape + val linearStructure = this@toPrettyString.linearStructure + var vectorSize = shape.last() + val initString = "DoubleTensor(\n" + append(initString) + var charOffset = 3 + for (vector in vectorSequence()) { + append(" ".repeat(charOffset)) + val index = linearStructure.index(offset) + for (ind in index.reversed()) { + if (ind != 0) { + break + } + append("[") + charOffset += 1 + } + // todo refactor + val values = mutableListOf() + for (i in 0 until vectorSize) { + values.add(vector[intArrayOf(i)]) + } + append(values.map { format(it) }.joinToString(", ")) + append("]") + charOffset -= 1 + for (i in shape.size - 2 downTo 0){ + val ind = index[i] + val maxInd = shape[i] + if (ind != maxInd - 1) { + break + } + append("]") + charOffset -=1 + } + offset += vectorSize + // todo refactor + if (this@toPrettyString.numel == offset) { + break + } + append(",\n") + } + append("\n)") + } + return builder.toString() +} + + + From 41ac72b4fbf5527a9a37296da90ff412e66cf542 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 16 Apr 2021 07:45:31 +0100 Subject: [PATCH 108/211] MPP toString for DoubleTensor --- .../kmath/tensors/core/BufferedTensor.kt | 4 ++- .../kscience/kmath/tensors/core/linutils.kt | 4 +-- .../kscience/kmath/tensors/core/utils.kt | 33 ++++++++++++++----- .../src/jvmMain/kotlin/tensorPrettyPrinter.kt | 4 +-- 4 files changed, 30 insertions(+), 15 deletions(-) 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 9a4d13d2c..9e393f1a8 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 @@ -4,7 +4,6 @@ import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.TensorStructure - public open class BufferedTensor( override val shape: IntArray, public val buffer: MutableBuffer, @@ -70,6 +69,9 @@ public class DoubleTensor internal constructor( { internal constructor(bufferedTensor: BufferedTensor): this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) + + override fun toString(): String = toPrettyString() + } internal fun BufferedTensor.asTensor(): IntTensor = IntTensor(this) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index ee159b614..ba5e0caaf 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -190,9 +190,7 @@ internal inline fun choleskyHelper( } } -internal inline fun luMatrixDet(luTensor: MutableStructure2D, pivotsTensor: MutableStructure1D): Double { - val lu = luTensor.as2D() - val pivots = pivotsTensor.as1D() +internal inline fun luMatrixDet(lu: MutableStructure2D, pivots: MutableStructure1D): Double { if (lu[0, 0] == 0.0) { return 0.0 } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index e67591c9e..daab79016 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -1,11 +1,11 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.as1D -import space.kscience.kmath.nd.as2D import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.* -import kotlin.math.sqrt +import kotlin.math.* /** * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. @@ -61,7 +61,25 @@ internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.linearStructure.dim, i) -public fun DoubleTensor.toPrettyString(): String = buildString { +internal inline fun format(value: Double, digits: Int = 4): String { + val ten = 10.0 + val approxOrder = ceil(log10(abs(value))).toInt() + val order = if( + ((value % ten) == 0.0) or + (value == 1.0) or + ((1/value) % ten == 0.0)) approxOrder else approxOrder - 1 + + val lead = value / ten.pow(order) + val leadDisplay = round(lead*ten.pow(digits)) / ten.pow(digits) + val orderDisplay = if(order >= 0) "+$order" else "$order" + val valueDisplay = "${leadDisplay}E$orderDisplay" + val res = if(value < 0.0) valueDisplay else " $valueDisplay" + val fLength = digits + 6 + val endSpace = " ".repeat(fLength - res.length) + return "$res$endSpace" +} + +internal inline fun DoubleTensor.toPrettyString(): String = buildString { var offset = 0 val shape = this@toPrettyString.shape val linearStructure = this@toPrettyString.linearStructure @@ -79,12 +97,9 @@ public fun DoubleTensor.toPrettyString(): String = buildString { append("[") charOffset += 1 } - // todo refactor - val values = mutableListOf() - for (i in 0 until vectorSize) { - values.add(vector[intArrayOf(i)]) - } - // todo apply exp formatting + + val values = vector.as1D().toMutableList().map(::format) + append(values.joinToString(", ")) append("]") charOffset -= 1 diff --git a/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt b/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt index 669a5494b..d3ce5933e 100644 --- a/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt +++ b/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt @@ -2,7 +2,7 @@ import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.vectorSequence import java.lang.StringBuilder - +/* internal fun format(value: Double, digits: Int = 4): String { val res = "%.${digits}e".format(value).replace(',', '.') if (value < 0.0) { @@ -59,6 +59,6 @@ public fun DoubleTensor.toPrettyString(): String { } return builder.toString() } - +*/ From baa303171eb9a6a99b3f5e83cae87a1e0a1abb5f Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 16 Apr 2021 07:47:06 +0100 Subject: [PATCH 109/211] No jvm specifics please --- .../src/jvmMain/kotlin/tensorPrettyPrinter.kt | 64 ------------------- 1 file changed, 64 deletions(-) delete mode 100644 kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt diff --git a/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt b/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt deleted file mode 100644 index d3ce5933e..000000000 --- a/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt +++ /dev/null @@ -1,64 +0,0 @@ - -import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.vectorSequence -import java.lang.StringBuilder -/* -internal fun format(value: Double, digits: Int = 4): String { - val res = "%.${digits}e".format(value).replace(',', '.') - if (value < 0.0) { - return res - } - return StringBuilder().append(" ").append(res).toString() -} - -public fun DoubleTensor.toPrettyString(): String { - val builder = StringBuilder() - with(builder) { - var offset = 0 - val shape = this@toPrettyString.shape - val linearStructure = this@toPrettyString.linearStructure - var vectorSize = shape.last() - val initString = "DoubleTensor(\n" - append(initString) - var charOffset = 3 - for (vector in vectorSequence()) { - append(" ".repeat(charOffset)) - val index = linearStructure.index(offset) - for (ind in index.reversed()) { - if (ind != 0) { - break - } - append("[") - charOffset += 1 - } - // todo refactor - val values = mutableListOf() - for (i in 0 until vectorSize) { - values.add(vector[intArrayOf(i)]) - } - append(values.map { format(it) }.joinToString(", ")) - append("]") - charOffset -= 1 - for (i in shape.size - 2 downTo 0){ - val ind = index[i] - val maxInd = shape[i] - if (ind != maxInd - 1) { - break - } - append("]") - charOffset -=1 - } - offset += vectorSize - // todo refactor - if (this@toPrettyString.numel == offset) { - break - } - append(",\n") - } - append("\n)") - } - return builder.toString() -} -*/ - - From 1e7cf39150be8393acd0f24572d0a1a93ef87e15 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 16 Apr 2021 11:58:42 +0100 Subject: [PATCH 110/211] Don't print 0 order --- .../kotlin/space/kscience/kmath/tensors/core/utils.kt | 6 +++--- .../space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index daab79016..40d40b593 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -71,8 +71,8 @@ internal inline fun format(value: Double, digits: Int = 4): String { val lead = value / ten.pow(order) val leadDisplay = round(lead*ten.pow(digits)) / ten.pow(digits) - val orderDisplay = if(order >= 0) "+$order" else "$order" - val valueDisplay = "${leadDisplay}E$orderDisplay" + val orderDisplay = if(order == 0) "" else if(order > 0) "E+$order" else "E$order" + val valueDisplay = "${leadDisplay}$orderDisplay" val res = if(value < 0.0) valueDisplay else " $valueDisplay" val fLength = digits + 6 val endSpace = " ".repeat(fLength - res.length) @@ -83,7 +83,7 @@ internal inline fun DoubleTensor.toPrettyString(): String = buildString { var offset = 0 val shape = this@toPrettyString.shape val linearStructure = this@toPrettyString.linearStructure - var vectorSize = shape.last() + val vectorSize = shape.last() val initString = "DoubleTensor(\n" append(initString) var charOffset = 3 diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 4f4d9bbdf..ddcf0369c 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -46,4 +46,10 @@ class TestDoubleTensor { assertEquals(secondRow[1], secondColumn[1]) } } + + @Test + fun toStringTest() = DoubleTensorAlgebra { + val tensor = randNormal(intArrayOf(2,3)) + println(tensor) + } } \ No newline at end of file From 4f8ab4dd78ea1a9a8925fce8898c33313e6be9ec Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 16 Apr 2021 12:03:27 +0100 Subject: [PATCH 111/211] Ignore print test --- .../kotlin/space/kscience/kmath/tensors/core/utils.kt | 3 +-- .../space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 40d40b593..0b2b5c0df 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -1,6 +1,5 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.as1D import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator @@ -72,7 +71,7 @@ internal inline fun format(value: Double, digits: Int = 4): String { val lead = value / ten.pow(order) val leadDisplay = round(lead*ten.pow(digits)) / ten.pow(digits) val orderDisplay = if(order == 0) "" else if(order > 0) "E+$order" else "E$order" - val valueDisplay = "${leadDisplay}$orderDisplay" + val valueDisplay = "$leadDisplay$orderDisplay" val res = if(value < 0.0) valueDisplay else " $valueDisplay" val fLength = digits + 6 val endSpace = " ".repeat(fLength - res.length) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index ddcf0369c..f950dfce3 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,8 +1,10 @@ package space.kscience.kmath.tensors.core +import kotlinx.coroutines.InternalCoroutinesApi import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray +import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -47,7 +49,7 @@ class TestDoubleTensor { } } - @Test + @Test @Ignore fun toStringTest() = DoubleTensorAlgebra { val tensor = randNormal(intArrayOf(2,3)) println(tensor) From 82d8394a9fd19461e90a331157e5ac4eee705aab Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 16 Apr 2021 12:05:18 +0100 Subject: [PATCH 112/211] remove kolinx import --- .../kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index f950dfce3..fd75f77fe 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,6 +1,5 @@ package space.kscience.kmath.tensors.core -import kotlinx.coroutines.InternalCoroutinesApi import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray From 2ac55e851f7c9d7156eb10de49abf83d1ec352fd Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 16 Apr 2021 20:03:44 +0300 Subject: [PATCH 113/211] Update pages.yml remove caches from build pages --- .github/workflows/pages.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 82b0fb303..110537a10 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -15,20 +15,6 @@ jobs: uses: actions/setup-java@v1 with: java-version: 11 - - name: Cache gradle - uses: actions/cache@v2 - with: - path: ~/.gradle/caches - key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }} - restore-keys: | - ubuntu-20.04-gradle- - - name: Cache konan - uses: actions/cache@v2 - with: - path: ~/.konan - key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} - restore-keys: | - ${{ runner.os }}-gradle- - name: Build run: | ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace From 6c215abf13c4cdc7839966634b0523d32de60f3f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 17 Apr 2021 10:08:04 +0300 Subject: [PATCH 114/211] Fix BigInt benchmark. --- .../kmath/benchmarks/BigIntBenchmark.kt | 21 +++++++++---------- .../kmath/integration/GaussIntegralTest.kt | 4 ++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index b9a10c774..2076aedc7 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -15,8 +15,7 @@ import space.kscience.kmath.operations.BigIntField import space.kscience.kmath.operations.JBigIntegerField import space.kscience.kmath.operations.invoke -private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ONE) - +private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ZERO) @State(Scope.Benchmark) internal class BigIntBenchmark { @@ -57,13 +56,13 @@ internal class BigIntBenchmark { blackhole.consume(largeJvmNumber*largeJvmNumber) } - @Benchmark - fun kmPower(blackhole: Blackhole) = BigIntField { - blackhole.consume(kmNumber.pow(bigExponent)) - } - - @Benchmark - fun jvmPower(blackhole: Blackhole) = JBigIntegerField { - blackhole.consume(jvmNumber.pow(bigExponent)) - } +// @Benchmark +// fun kmPower(blackhole: Blackhole) = BigIntField { +// blackhole.consume(kmNumber.pow(bigExponent)) +// } +// +// @Benchmark +// fun jvmPower(blackhole: Blackhole) = JBigIntegerField { +// blackhole.consume(jvmNumber.pow(bigExponent)) +// } } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 5ec90f42a..509821e61 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -19,7 +19,7 @@ class GaussIntegralTest { val res = DoubleField.integrate(0.0..2 * PI) { x -> sin(x) } - assertEquals(0.0, res.value!!, 1e-4) + assertEquals(0.0, res.value!!, 1e-2) } @Test @@ -31,7 +31,7 @@ class GaussIntegralTest { 0.0 } } - assertEquals(20.0, res.value!!, 0.5) + assertEquals(20.0, res.value!!, 1.0) } From 07e39a068d5055f34e2c3190beb242e4960b48f8 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 18 Apr 2021 19:43:03 +0300 Subject: [PATCH 115/211] Use split interval for integration. --- .../space/kscience/kmath/linear/gradient.kt | 4 +- .../kmath/commons/integration/CMIntegrator.kt | 2 +- .../integration/GaussRuleIntegrator.kt | 2 +- .../kmath/integration/GaussIntegrator.kt | 64 +++++++++++++++---- .../kmath/integration/UnivariateIntegrand.kt | 2 +- 5 files changed, 56 insertions(+), 18 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt index f7b284e89..a01ea7fe2 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt @@ -22,8 +22,8 @@ fun main() { return DoubleBuffer(x.size) { i -> val h = sigma[i] / 5 val dVector = DoubleBuffer(x.size) { if (it == i) h else 0.0 } - val f1 = invoke(x + dVector / 2) - val f0 = invoke(x - dVector / 2) + val f1 = this(x + dVector / 2) + val f0 = this(x - dVector / 2) (f1 - f0) / h } } diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt index 535c6b39e..92bf86128 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt @@ -28,7 +28,7 @@ public class CMIntegrator( val integrator = integratorBuilder(integrand) val maxCalls = integrand.getFeature()?.maxCalls ?: defaultMaxCalls val remainingCalls = maxCalls - integrand.calls - val range = integrand.getFeature>()?.range + val range = integrand.getFeature()?.range ?: error("Integration range is not provided") val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt index 071bac315..1c9915563 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt @@ -17,7 +17,7 @@ public class GaussRuleIntegrator( ) : UnivariateIntegrator { override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand { - val range = integrand.getFeature>()?.range + val range = integrand.getFeature()?.range ?: error("Integration range is not provided") val integrator: GaussIntegrator = getIntegrator(range) //TODO check performance diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index bc23e2f1b..749f3cc72 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -8,6 +8,13 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Field import space.kscience.kmath.structures.* +/** + * Set of univariate integration ranges. First components correspond to ranges themselves, second components to number of + * integration nodes per range + */ +public class UnivariateIntegrandRanges(public val ranges: List, Int>>) : IntegrandFeature { + public constructor(vararg pairs: Pair, Int>) : this(pairs.toList()) +} /** * A simple one-pass integrator based on Gauss rule @@ -18,9 +25,29 @@ public class GaussIntegrator( private fun buildRule(integrand: UnivariateIntegrand): Pair, Buffer> { val factory = integrand.getFeature() ?: GaussLegendreRuleFactory - val numPoints = integrand.getFeature()?.maxCalls ?: 100 - val range = integrand.getFeature>()?.range ?: 0.0..1.0 - return factory.build(numPoints, range) + val predefinedRanges = integrand.getFeature() + if (predefinedRanges == null || predefinedRanges.ranges.isEmpty()) { + val numPoints = integrand.getFeature()?.maxCalls ?: 100 + val range = integrand.getFeature()?.range ?: 0.0..1.0 + return factory.build(numPoints, range) + } else { + val ranges = predefinedRanges.ranges + var counter = 0 + val length = ranges.sumOf { it.second } + val pointsArray = DoubleArray(length) + val weightsArray = DoubleArray(length) + + for (range in ranges) { + val rule = factory.build(range.second, range.first) + repeat(rule.first.size) { i -> + pointsArray[counter] = rule.first[i] + weightsArray[counter] = rule.second[i] + counter++ + } + + } + return pointsArray.asBuffer() to weightsArray.asBuffer() + } } override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand = with(algebra) { @@ -49,7 +76,8 @@ public class GaussIntegrator( * Following features are evaluated: * * [GaussIntegratorRuleFactory] - A factory for computing the Gauss integration rule. By default uses [GaussLegendreRuleFactory] * * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. - * * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 100 points. + * * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 10 points. + * * [UnivariateIntegrandRanges] - Set of ranges and number of points per range. Defaults to given [IntegrationRange] and [IntegrandMaxCalls] */ @UnstableKMathAPI public fun Field.integrate( @@ -64,15 +92,25 @@ public fun Field.integrate( @UnstableKMathAPI public fun Field.integrate( range: ClosedRange, - numPoints: Int = 100, + order: Int = 10, + intervals: Int = 10, vararg features: IntegrandFeature, function: (Double) -> T, -): UnivariateIntegrand = GaussIntegrator(this).integrate( - UnivariateIntegrand( - function, - IntegrationRange(range), - GaussLegendreRuleFactory, - IntegrandMaxCalls(numPoints), - *features +): UnivariateIntegrand { + require(range.endInclusive > range.start) { "The range upper bound should be higher than lower bound" } + require(order > 1) { "The order of polynomial must be more than 1" } + require(intervals > 0) { "Number of intervals must be positive" } + val rangeSize = (range.endInclusive - range.start) / intervals + val ranges = UnivariateIntegrandRanges( + (0 until intervals).map { i -> (rangeSize * i)..(rangeSize * i + 1) to order } ) -) \ No newline at end of file + return GaussIntegrator(this).integrate( + UnivariateIntegrand( + function, + IntegrationRange(range), + GaussLegendreRuleFactory, + ranges, + *features + ) + ) +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index 0b41a3f8b..bcd5005c4 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -33,7 +33,7 @@ public fun UnivariateIntegrand( public typealias UnivariateIntegrator = Integrator> @JvmInline -public value class IntegrationRange>(public val range: ClosedRange) : IntegrandFeature +public value class IntegrationRange(public val range: ClosedRange) : IntegrandFeature public val UnivariateIntegrand.value: T? get() = getFeature>()?.value From 86818f6864ac722ebd5b32f2274c9eb6afb06ca0 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 19 Apr 2021 09:31:56 +0300 Subject: [PATCH 116/211] Replace dl4j with nd4j dependency --- kmath-nd4j/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 17232b44f..c7d891206 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -13,7 +13,7 @@ plugins { dependencies { api(project(":kmath-core")) api("org.nd4j:nd4j-api:1.0.0-beta7") - testImplementation("org.deeplearning4j:deeplearning4j-core:1.0.0-beta7") + testImplementation("org.nd4j:nd4j-native:1.0.0-beta7") testImplementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") testImplementation("org.slf4j:slf4j-simple:1.7.30") } From fd4108b74fbd012796fa12f913675ed55d8eae62 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 19 Apr 2021 11:26:06 +0300 Subject: [PATCH 117/211] fix segmented integral --- .../space/kscience/kmath/integration/GaussIntegrator.kt | 2 +- .../space/kscience/kmath/integration/GaussIntegralTest.kt | 4 ++-- .../kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index 749f3cc72..ae82a40be 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -102,7 +102,7 @@ public fun Field.integrate( require(intervals > 0) { "Number of intervals must be positive" } val rangeSize = (range.endInclusive - range.start) / intervals val ranges = UnivariateIntegrandRanges( - (0 until intervals).map { i -> (rangeSize * i)..(rangeSize * i + 1) to order } + (0 until intervals).map { i -> (rangeSize * i)..(rangeSize * (i + 1)) to order } ) return GaussIntegrator(this).integrate( UnivariateIntegrand( diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 509821e61..195711452 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -24,14 +24,14 @@ class GaussIntegralTest { @Test fun gaussUniform() { - val res = DoubleField.integrate(0.0..100.0,300) { x -> + val res = DoubleField.integrate(0.0..100.0) { x -> if(x in 30.0..50.0){ 1.0 } else { 0.0 } } - assertEquals(20.0, res.value!!, 1.0) + assertEquals(20.0, res.value!!, 0.5) } diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt index b9aa251d2..79db86fcc 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt @@ -20,8 +20,7 @@ public sealed class Nd4jArrayStructure : MutableStructureND { */ public abstract val ndArray: INDArray - public override val shape: IntArray - get() = ndArray.shape().toIntArray() + public override val shape: IntArray get() = ndArray.shape().toIntArray() internal abstract fun elementsIterator(): Iterator> internal fun indicesIterator(): Iterator = ndArray.indicesIterator() From 84fa878ee328f1c6f2ad828a77b83b325df222eb Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 20 Apr 2021 19:14:59 +0700 Subject: [PATCH 118/211] Update dependencies --- kmath-ast/build.gradle.kts | 30 ++++++------------- .../kotlin/space/kscience/kmath/ast/parser.kt | 2 -- 2 files changed, 9 insertions(+), 23 deletions(-) rename kmath-ast/src/{jvmMain => commonMain}/kotlin/space/kscience/kmath/ast/parser.kt (98%) diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 3f309b67c..f2080d0b2 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -27,6 +27,7 @@ kotlin.js { kotlin.sourceSets { commonMain { dependencies { + api("com.github.h0tk3y.betterParse:better-parse:0.4.2") api(project(":kmath-core")) } } @@ -39,13 +40,12 @@ kotlin.sourceSets { jsMain { dependencies { - implementation(npm("astring", "1.7.0")) + implementation(npm("astring", "1.7.4")) } } jvmMain { dependencies { - api("com.github.h0tk3y.betterParse:better-parse:0.4.1") implementation("org.ow2.asm:asm:9.1") implementation("org.ow2.asm:asm-commons:9.1") } @@ -64,25 +64,7 @@ readme { feature( id = "expression-language", description = "Expression language and its parser", - ref = "src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt" - ) - - feature( - id = "mst", - description = "MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation", - ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt" - ) - - feature( - id = "mst-building", - description = "MST building algebraic structure", - ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt" - ) - - feature( - id = "mst-interpreter", - description = "MST interpreter", - ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt" ) feature( @@ -96,4 +78,10 @@ readme { description = "Dynamic MST to JS compiler", ref = "src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt" ) + + feature( + id = "rendering", + description = "Extendable MST rendering", + ref = "src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt" + ) } diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt similarity index 98% rename from kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt rename to kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt index 025f4984c..d2e92c37f 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -// TODO move to common when https://github.com/h0tk3y/better-parse/pull/37 is merged - package space.kscience.kmath.ast import com.github.h0tk3y.betterParse.combinators.* From 9c353f4a0d3e0d2c09d8551b9efdc492fc43dbab Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 20 Apr 2021 22:48:09 +0300 Subject: [PATCH 119/211] Make ND4J float algebra extended --- CHANGELOG.md | 1 + .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 46 +++++++++++++++++-- .../kmath/nd4j/Nd4jArrayAlgebraTest.kt | 14 ++++++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1d33a75a..7464695ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Blocking chains and Statistics - Multiplatform integration - Integration for any Field element +- Extendend operations for ND4J fields ### Changed - Exponential operations merged with hyperbolic functions diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index f2c69adee..0205f1c87 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -6,7 +6,10 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray +import org.nd4j.linalg.api.ops.impl.scalar.Pow +import org.nd4j.linalg.api.ops.impl.transforms.strict.* import org.nd4j.linalg.factory.Nd4j +import org.nd4j.linalg.ops.transforms.Transforms import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* @@ -207,7 +210,8 @@ public interface Nd4jArrayField> : FieldND, Nd4jArrayRing< /** * Represents [FieldND] over [Nd4jArrayDoubleStructure]. */ -public class DoubleNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField { +public class DoubleNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField, + ExtendedField> { public override val elementContext: DoubleField get() = DoubleField public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asDoubleStructure() @@ -239,14 +243,31 @@ public class DoubleNd4jArrayField(public override val shape: IntArray) : Nd4jArr public override operator fun Double.minus(arg: StructureND): Nd4jArrayStructure { return arg.ndArray.rsub(this).wrap() } + + override fun sin(arg: StructureND): StructureND = Transforms.sin(arg.ndArray).wrap() + + override fun cos(arg: StructureND): StructureND = Transforms.cos(arg.ndArray).wrap() + + override fun asin(arg: StructureND): StructureND = Transforms.asin(arg.ndArray).wrap() + + override fun acos(arg: StructureND): StructureND = Transforms.acos(arg.ndArray).wrap() + + override fun atan(arg: StructureND): StructureND = Transforms.atan(arg.ndArray).wrap() + + override fun power(arg: StructureND, pow: Number): StructureND = + Transforms.pow(arg.ndArray,pow).wrap() + + override fun exp(arg: StructureND): StructureND = Transforms.exp(arg.ndArray).wrap() + + override fun ln(arg: StructureND): StructureND = Transforms.log(arg.ndArray).wrap() } /** * Represents [FieldND] over [Nd4jArrayStructure] of [Float]. */ -public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField { - public override val elementContext: FloatField - get() = FloatField +public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField, + ExtendedField> { + public override val elementContext: FloatField get() = FloatField public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asFloatStructure() @@ -270,6 +291,23 @@ public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArra public override operator fun Float.minus(arg: StructureND): Nd4jArrayStructure = arg.ndArray.rsub(this).wrap() + + override fun sin(arg: StructureND): StructureND = Sin(arg.ndArray).z().wrap() + + override fun cos(arg: StructureND): StructureND = Cos(arg.ndArray).z().wrap() + + override fun asin(arg: StructureND): StructureND = ASin(arg.ndArray).z().wrap() + + override fun acos(arg: StructureND): StructureND = ACos(arg.ndArray).z().wrap() + + override fun atan(arg: StructureND): StructureND = ATan(arg.ndArray).z().wrap() + + override fun power(arg: StructureND, pow: Number): StructureND = + Pow(arg.ndArray, pow.toDouble()).z().wrap() + + override fun exp(arg: StructureND): StructureND = Exp(arg.ndArray).z().wrap() + + override fun ln(arg: StructureND): StructureND = Log(arg.ndArray).z().wrap() } /** diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt index c3874b249..b6c524cc6 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt @@ -6,8 +6,12 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.factory.Nd4j +import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.operations.invoke +import kotlin.math.PI import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertTrue import kotlin.test.fail internal class Nd4jArrayAlgebraTest { @@ -43,4 +47,14 @@ internal class Nd4jArrayAlgebraTest { expected[intArrayOf(1, 1)] = 26 assertEquals(expected, res) } + + @Test + fun testSin() = DoubleNd4jArrayField(intArrayOf(2, 2)).invoke { + val initial = produce { (i, j) -> if (i == j) PI/2 else 0.0 } + val transformed = sin(initial) + val expected = produce { (i, j) -> if (i == j) 1.0 else 0.0 } + + println(transformed) + assertTrue { StructureND.contentEquals(transformed, expected) } + } } From 6aa5b547b57092f12a6a2defbfd94b65c5d4f3e9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 21 Apr 2021 12:48:11 +0300 Subject: [PATCH 120/211] cleanup --- CHANGELOG.md | 1 + kmath-core/api/kmath-core.api | 12 ++--- .../kmath/expressions/SymbolIndexer.kt | 4 +- .../kmath/expressions/expressionBuilders.kt | 45 ------------------- .../space/kscience/kmath/misc/Symbol.kt | 25 ++++++++++- .../kscience/kmath/operations/Algebra.kt | 4 +- .../kmath/operations/NumericAlgebra.kt | 6 +-- .../kscience/kmath/operations/numbers.kt | 6 --- 8 files changed, 35 insertions(+), 68 deletions(-) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 7464695ec..c41eda374 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ - Number multiplication and division in main Algebra chain - `contentEquals` from Buffer. It moved to the companion. - MSTExpression +- Expression algebra builders ### Fixed - Ring inherits RingOperations, not GroupOperations diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 6b300123c..efb626c12 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -45,13 +45,6 @@ public abstract interface class space/kscience/kmath/expressions/ExpressionAlgeb public abstract fun const (Ljava/lang/Object;)Ljava/lang/Object; } -public final class space/kscience/kmath/expressions/ExpressionBuildersKt { - public static final fun extendedFieldExpression (Lspace/kscience/kmath/operations/ExtendedField;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; - public static final fun fieldExpression (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; - public static final fun ringExpression (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; - public static final fun spaceExpression (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; -} - public final class space/kscience/kmath/expressions/ExpressionKt { public static final fun binding (Lspace/kscience/kmath/expressions/ExpressionAlgebra;)Lkotlin/properties/ReadOnlyProperty; public static final fun callByString (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object; @@ -705,7 +698,11 @@ public final class space/kscience/kmath/misc/Symbol$Companion { } public final class space/kscience/kmath/misc/SymbolKt { + public static final fun get (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object; + public static final fun get (Ljava/util/Map;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; public static final fun getSymbol ()Lkotlin/properties/ReadOnlyProperty; + public static final fun set (Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)V + public static final fun set (Ljava/util/Map;Lspace/kscience/kmath/misc/Symbol;Ljava/lang/Object;)V } public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation { @@ -1209,7 +1206,6 @@ public abstract interface class space/kscience/kmath/operations/ExtendedField : public fun acosh (Ljava/lang/Object;)Ljava/lang/Object; public fun asinh (Ljava/lang/Object;)Ljava/lang/Object; public fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun sinh (Ljava/lang/Object;)Ljava/lang/Object; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt index 886008983..738156975 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt @@ -33,12 +33,12 @@ public interface SymbolIndexer { public operator fun DoubleArray.get(symbol: Symbol): Double { require(size == symbols.size) { "The input array size for indexer should be ${symbols.size} but $size found" } - return get(this@SymbolIndexer.indexOf(symbol)) + return get(indexOf(symbol)) } public operator fun Point.get(symbol: Symbol): T { require(size == symbols.size) { "The input buffer size for indexer should be ${symbols.size} but $size found" } - return get(this@SymbolIndexer.indexOf(symbol)) + return get(indexOf(symbol)) } public fun DoubleArray.toMap(): Map { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt deleted file mode 100644 index 142194070..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.expressions - -import space.kscience.kmath.operations.ExtendedField -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.Ring -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - - -/** - * Creates a functional expression with this [Ring]. - */ -public inline fun Ring.spaceExpression(block: FunctionalExpressionGroup>.() -> Expression): Expression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return FunctionalExpressionGroup(this).block() -} - -/** - * Creates a functional expression with this [Ring]. - */ -public inline fun Ring.ringExpression(block: FunctionalExpressionRing>.() -> Expression): Expression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return FunctionalExpressionRing(this).block() -} - -/** - * Creates a functional expression with this [Field]. - */ -public inline fun Field.fieldExpression(block: FunctionalExpressionField>.() -> Expression): Expression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return FunctionalExpressionField(this).block() -} - -/** - * Creates a functional expression with this [ExtendedField]. - */ -public inline fun ExtendedField.extendedFieldExpression(block: FunctionalExpressionExtendedField>.() -> Expression): Expression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return FunctionalExpressionExtendedField(this).block() -} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt index 737acc025..b9fb6879a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt @@ -32,10 +32,33 @@ public value class StringSymbol(override val identity: String) : Symbol { override fun toString(): String = identity } - /** * A delegate to create a symbol with a string identity in this scope */ public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> StringSymbol(property.name) } + +/** + * Ger a value from a [String]-keyed map by a [Symbol] + */ +public operator fun Map.get(symbol: Symbol): T? = get(symbol.identity) + +/** + * Set a value of [String]-keyed map by a [Symbol] + */ +public operator fun MutableMap.set(symbol: Symbol, value: T){ + set(symbol.identity, value) +} + +/** + * Get a value from a [Symbol]-keyed map by a [String] + */ +public operator fun Map.get(string: String): T? = get(StringSymbol(string)) + +/** + * Set a value of [String]-keyed map by a [Symbol] + */ +public operator fun MutableMap.set(string: String, value: T){ + set(StringSymbol(string), value) +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 0334e0466..c994580bd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -44,9 +44,9 @@ public interface Algebra { /** * Dynamically dispatches an unary operation with the certain name. * - * This function must follow two properties: + * This function must has two features: * - * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 1. In case operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. * 2. This function is symmetric with second `unaryOperation` overload: * i.e. `unaryOperationFunction(a)(b) == unaryOperation(a, b)`. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt index 6a35828ee..deeb07e0e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt @@ -97,14 +97,12 @@ public interface NumericAlgebra : Algebra { /** * The π mathematical constant. */ -public val NumericAlgebra.pi: T - get() = bindSymbolOrNull("pi") ?: number(PI) +public val NumericAlgebra.pi: T get() = bindSymbolOrNull("pi") ?: number(PI) /** * The *e* mathematical constant. */ -public val NumericAlgebra.e: T - get() = number(E) +public val NumericAlgebra.e: T get() = number(E) /** * Scale by scalar operations diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt index 3b0abf657..0d6d9e98d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt @@ -49,12 +49,6 @@ public interface ExtendedField : ExtendedFieldOperations, Field, Numeri public override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one))) public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2.0 - public override fun bindSymbol(value: String): T = when (value) { - "pi" -> pi - "e" -> e - else -> super.bindSymbol(value) - } - public override fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T = when (operation) { PowerOperations.POW_OPERATION -> ::power From b6a57dbfd03e4eae9232891bc6fa00e3647b77ce Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 20 Apr 2021 21:39:45 +0700 Subject: [PATCH 121/211] MST compilation to WebAssembly with Binaryen, reorganize internal JS bindings, tests refactor --- README.md | 16 +- benchmarks/build.gradle.kts | 40 +- .../ExpressionsInterpretersBenchmark.kt | 59 +- build.gradle.kts | 10 +- examples/build.gradle.kts | 7 +- .../kscience/kmath/ast/kotlingradSupport.kt | 2 +- kmath-ast/README.md | 54 +- kmath-ast/build.gradle.kts | 7 +- kmath-ast/docs/README-TEMPLATE.md | 40 +- .../space/kscisnce/kmath/ast/InterpretTest.kt | 27 - .../kmath/ast/ParserPrecedenceTest.kt | 15 +- .../space/kscisnce}/kmath/ast/ParserTest.kt | 25 +- .../space/kscience/kmath/estree/estree.kt | 2 +- .../kmath/estree/internal/ESTreeBuilder.kt | 9 +- .../kmath/estree/internal/stream/stream.kt | 12 - .../{estree => }/internal/astring/astring.kt | 4 +- .../internal/astring/astring.typealises.kt | 3 + .../kscience/kmath/internal/base64/base64.kt | 49 + .../kmath/internal/binaryen/index.binaryen.kt | 2234 +++++++++++++++++ .../binaryen/index.binaryen.typealiases.kt | 11 + .../{estree => }/internal/emitter/emitter.kt | 2 +- .../internal/estree/estree.extensions.kt | 2 +- .../{estree => }/internal/estree/estree.kt | 2 +- .../kscience/kmath/internal/stream/stream.kt | 7 + .../internal/tsstdlib/lib.es2015.iterable.kt | 2 +- .../{estree => }/internal/tsstdlib/lib.es5.kt | 11 +- .../lib.dom.WebAssembly.module_dukat.kt | 231 ++ .../nonDeclarations.WebAssembly.kt | 22 + .../kmath/wasm/internal/WasmBuilder.kt | 155 ++ .../wasm/internal/f64StandardFunctions.kt | 8 + .../kotlin/space/kscience/kmath/wasm/wasm.kt | 77 + .../kscience/kmath/ast/TestExecutionTime.kt | 67 + .../TestESTreeConsistencyWithInterpreter.kt | 35 +- .../estree/TestESTreeOperationsSupport.kt | 27 +- .../kmath/estree/TestESTreeSpecialization.kt | 43 +- .../kmath/estree/TestESTreeVariables.kt | 12 +- .../TestWasmConsistencyWithInterpreter.kt | 60 + .../kmath/wasm/TestWasmOperationsSupport.kt | 42 + .../kmath/wasm/TestWasmSpecialization.kt | 76 + .../kscience/kmath/wasm/TestWasmSpecific.kt | 48 + .../kscience/kmath/wasm/TestWasmVariables.kt | 34 + .../asm/TestAsmConsistencyWithInterpreter.kt | 19 +- .../kmath/asm/TestAsmOperationsSupport.kt | 25 +- .../kmath/asm/TestAsmSpecialization.kt | 43 +- .../kscience/kmath/asm/TestAsmVariables.kt | 12 +- .../kmath/ast/rendering/TestFeatures.kt | 100 - .../kscience/kmath/ast/rendering/TestLatex.kt | 73 - .../kmath/ast/rendering/TestMathML.kt | 92 - .../kmath/ast/rendering/TestStages.kt | 33 - .../kscience/kmath/ast/rendering/TestUtils.kt | 46 - kmath-complex/README.md | 6 +- kmath-complex/build.gradle.kts | 4 +- kmath-core/README.md | 6 +- kmath-core/build.gradle.kts | 4 +- .../kmath/expressions/InterpretTest.kt | 18 + kmath-coroutines/build.gradle.kts | 4 +- kmath-ejml/README.md | 6 +- kmath-for-real/README.md | 6 +- kmath-functions/README.md | 6 +- kmath-geometry/build.gradle.kts | 4 +- kmath-histograms/build.gradle.kts | 4 +- .../kmath/kotlingrad/AdaptingTests.kt | 25 +- kmath-nd4j/README.md | 6 +- kmath-nd4j/build.gradle.kts | 4 +- kmath-stat/build.gradle.kts | 4 +- kmath-viktor/build.gradle.kts | 4 +- 66 files changed, 3451 insertions(+), 692 deletions(-) delete mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt rename kmath-ast/src/{jvmTest/kotlin/space/kscience => commonTest/kotlin/space/kscisnce}/kmath/ast/ParserPrecedenceTest.kt (75%) rename kmath-ast/src/{jvmTest/kotlin/space/kscience => commonTest/kotlin/space/kscisnce}/kmath/ast/ParserTest.kt (67%) delete mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/stream/stream.kt rename kmath-ast/src/jsMain/kotlin/space/kscience/kmath/{estree => }/internal/astring/astring.kt (90%) create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt rename kmath-ast/src/jsMain/kotlin/space/kscience/kmath/{estree => }/internal/emitter/emitter.kt (91%) rename kmath-ast/src/jsMain/kotlin/space/kscience/kmath/{estree => }/internal/estree/estree.extensions.kt (97%) rename kmath-ast/src/jsMain/kotlin/space/kscience/kmath/{estree => }/internal/estree/estree.kt (99%) create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt rename kmath-ast/src/jsMain/kotlin/space/kscience/kmath/{estree => }/internal/tsstdlib/lib.es2015.iterable.kt (94%) rename kmath-ast/src/jsMain/kotlin/space/kscience/kmath/{estree => }/internal/tsstdlib/lib.es5.kt (88%) create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt diff --git a/README.md b/README.md index 0210b4caf..773eb6398 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,12 @@ KMath is a modular library. Different modules provide different features with di
+* ### [benchmarks](benchmarks) +> +> +> **Maturity**: EXPERIMENTAL +
+ * ### [examples](examples) > > @@ -88,12 +94,10 @@ KMath is a modular library. Different modules provide different features with di > **Maturity**: PROTOTYPE > > **Features:** -> - [expression-language](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser -> - [mst](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation -> - [mst-building](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure -> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter +> - [expression-language](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser > - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler > - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler +> - [rendering](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt) : Extendable MST rendering
@@ -266,8 +270,8 @@ repositories { } dependencies { - api("space.kscience:kmath-core:0.3.0-dev-6") - // api("space.kscience:kmath-core-jvm:0.3.0-dev-6") for jvm-specific version + api("space.kscience:kmath-core:0.3.0-dev-7") + // api("space.kscience:kmath-core-jvm:0.3.0-dev-7") for jvm-specific version } ``` diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index f8e85395b..d6796ed46 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") kotlin("plugin.allopen") @@ -14,8 +12,6 @@ plugins { allOpen.annotation("org.openjdk.jmh.annotations.State") sourceSets.register("benchmarks") - - repositories { mavenCentral() jcenter() @@ -77,43 +73,35 @@ benchmark { register("jvm") } + fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() { + warmups = 1 + iterations = 5 + iterationTime = 1000 + iterationTimeUnit = "ms" + } + configurations.register("buffer") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + commonConfiguration() include("BufferBenchmark") } configurations.register("dot") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + commonConfiguration() include("DotBenchmark") } configurations.register("expressions") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + commonConfiguration() include("ExpressionsInterpretersBenchmark") } configurations.register("matrixInverse") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + commonConfiguration() include("MatrixInverseBenchmark") } configurations.register("bigInt") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + commonConfiguration() include("BigIntBenchmark") } } @@ -121,7 +109,7 @@ benchmark { // Fix kotlinx-benchmarks bug afterEvaluate { val jvmBenchmarkJar by tasks.getting(org.gradle.jvm.tasks.Jar::class) { - duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.EXCLUDE + duplicatesStrategy = DuplicatesStrategy.EXCLUDE } } @@ -143,5 +131,5 @@ tasks.withType { readme { - maturity = Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index d6fde8398..942fba308 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -11,6 +11,7 @@ import kotlinx.benchmark.Scope import kotlinx.benchmark.State import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.expressions.* +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol @@ -20,50 +21,22 @@ import kotlin.random.Random @State(Scope.Benchmark) internal class ExpressionsInterpretersBenchmark { @Benchmark - fun functionalExpression(blackhole: Blackhole) { - val expr = algebra.expressionInField { - val x = bindSymbol(x) - x * const(2.0) + const(2.0) / x - const(16.0) - } - - invokeAndSum(expr, blackhole) - } + fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole) @Benchmark - fun mstExpression(blackhole: Blackhole) { - val expr = MstField { - val x = bindSymbol(x) - x * 2.0 + number(2.0) / x - 16.0 - }.toExpression(algebra) - - invokeAndSum(expr, blackhole) - } + fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole) @Benchmark - fun asmExpression(blackhole: Blackhole) { - val expr = MstField { - val x = bindSymbol(x) - x * 2.0 + number(2.0) / x - 16.0 - }.compileToExpression(algebra) - - invokeAndSum(expr, blackhole) - } + fun asmExpression(blackhole: Blackhole) = invokeAndSum(asm, blackhole) @Benchmark - fun rawExpression(blackhole: Blackhole) { - val expr = Expression { args -> - val x = args.getValue(x) - x * 2.0 + 2.0 / x - 16.0 - } - - invokeAndSum(expr, blackhole) - } + fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole) private fun invokeAndSum(expr: Expression, blackhole: Blackhole) { val random = Random(0) var sum = 0.0 - repeat(1000000) { + repeat(times) { sum += expr(x to random.nextDouble()) } @@ -71,7 +44,23 @@ internal class ExpressionsInterpretersBenchmark { } private companion object { - private val algebra = DoubleField - private val x by symbol + private val x: Symbol by symbol + private val algebra: DoubleField = DoubleField + private const val times = 1_000_000 + + private val functional: Expression = DoubleField.expressionInExtendedField { + bindSymbol(x) * number(2.0) + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x)) + } + + private val node = MstExtendedField { + bindSymbol(x) * 2.0 + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x)) + } + + private val mst: Expression = node.toExpression(DoubleField) + private val asm: Expression = node.compileToExpression(DoubleField) + + private val raw: Expression = Expression { args -> + args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 / kotlin.math.sin(args.getValue(x)) + } } } diff --git a/build.gradle.kts b/build.gradle.kts index aeb4a6061..a7c9144a7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,9 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import org.jetbrains.dokka.gradle.DokkaTask -import java.net.URL - plugins { id("ru.mipt.npm.gradle.project") } @@ -17,8 +14,7 @@ allprojects { maven("https://dl.bintray.com/egor-bogomolov/astminer/") maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://jitpack.io") - maven{ - setUrl("http://logicrunch.research.it.uu.se/maven/") + maven("http://logicrunch.research.it.uu.se/maven/") { isAllowInsecureProtocol = true } mavenCentral() @@ -32,7 +28,7 @@ subprojects { if (name.startsWith("kmath")) apply() afterEvaluate { - tasks.withType { + tasks.withType { dokkaSourceSets.all { val readmeFile = File(this@subprojects.projectDir, "./README.md") if (readmeFile.exists()) @@ -42,7 +38,7 @@ subprojects { "http://ejml.org/javadoc/", "https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/", "https://deeplearning4j.org/api/latest/" - ).map { URL("${it}package-list") to URL(it) }.forEach { (a, b) -> + ).map { java.net.URL("${it}package-list") to java.net.URL(it) }.forEach { (a, b) -> externalDocumentationLink { packageListUrl.set(a) url.set(b) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 8bd9423fe..67fe9853a 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -3,9 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("jvm") } @@ -64,7 +61,7 @@ kotlin.sourceSets.all { } } -tasks.withType { +tasks.withType { kotlinOptions{ jvmTarget = "11" freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" @@ -72,5 +69,5 @@ tasks.withType { } readme { - maturity = Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt index 4a31f33a3..25f42f5a9 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt @@ -25,5 +25,5 @@ fun main() { val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField) - assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0)) + assert(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0)) } diff --git a/kmath-ast/README.md b/kmath-ast/README.md index b1ef9c7d3..eedba16fa 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -2,17 +2,15 @@ Abstract syntax tree expression representation and related optimizations. - - [expression-language](src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser - - [mst](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation - - [mst-building](src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure - - [mst-interpreter](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter + - [expression-language](src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser - [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler - [mst-js-codegen](src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler + - [rendering](src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt) : Extendable MST rendering ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-7`. **Gradle:** ```gradle @@ -23,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0-dev-6' + implementation 'space.kscience:kmath-ast:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -35,7 +33,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0-dev-6") + implementation("space.kscience:kmath-ast:0.3.0-dev-7") } ``` @@ -49,10 +47,10 @@ a special implementation of `Expression` with implemented `invoke` function. For example, the following builder: ```kotlin -DoubleField.mstInField { symbol("x") + 2 }.compile() +MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -… leads to generation of bytecode, which can be decompiled to the following Java class: +… leads to generation of bytecode, which can be decompiled to the following Java class: ```java package space.kscience.kmath.asm.generated; @@ -77,15 +75,6 @@ public final class AsmCompiledExpression_45045_0 implements Expression { ``` -### Example Usage - -This API extends MST and MstExpression, so you may optimize as both of them: - -```kotlin -DoubleField.mstInField { symbol("x") + 2 }.compile() -DoubleField.expression("x+2".parseMath()) -``` - #### Known issues - The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid @@ -97,7 +86,7 @@ DoubleField.expression("x+2".parseMath()) A similar feature is also available on JS. ```kotlin -DoubleField.mstInField { symbol("x") + 2 }.compile() +MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` The code above returns expression implemented with such a JS function: @@ -108,13 +97,32 @@ var executable = function (constants, arguments) { }; ``` + +```kotlin +import space.kscience.kmath.wasm.* + +MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) +``` + +An example of emitted WASM IR in the form of WAT: + +```lisp +(func $executable (param $0 f64) (result f64) + (f64.add + (local.get $0) + (f64.const 2) + ) +) +``` + #### Known issues -- This feature uses `eval` which can be unavailable in several environments. +- ESTree expression compilation uses `eval` which can be unavailable in several environments. +- WebAssembly isn't supported by old versions of browsers (see https://webassembly.org/roadmap/). ## Rendering expressions -kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax. +kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax. Example usage: @@ -135,7 +143,7 @@ public fun main() { } ``` -Result LaTeX: +Result LaTeX: ![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D) @@ -145,5 +153,5 @@ Result MathML (embedding MathML is not allowed by GitHub Markdown): ex-sin-12x2×1010+x3-12 ``` -It is also possible to create custom algorithms of render, and even add support of other markup languages +It is also possible to create custom algorithms of render, and even add support of other markup languages (see API reference). diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index f2080d0b2..15357b2d5 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -41,6 +39,9 @@ kotlin.sourceSets { jsMain { dependencies { implementation(npm("astring", "1.7.4")) + implementation(npm("binaryen", "100.0")) + implementation(npm("js-base64", "3.6.0")) + implementation(npm("webassembly", "0.11.0")) } } @@ -58,7 +59,7 @@ tasks.dokkaHtml { } readme { - maturity = Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index 9ed44d584..b38311ea1 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -16,7 +16,7 @@ a special implementation of `Expression` with implemented `invoke` function. For example, the following builder: ```kotlin -DoubleField.mstInField { symbol("x") + 2 }.compile() +MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` … leads to generation of bytecode, which can be decompiled to the following Java class: @@ -44,15 +44,6 @@ public final class AsmCompiledExpression_45045_0 implements Expression { ``` -### Example Usage - -This API extends MST and MstExpression, so you may optimize as both of them: - -```kotlin -DoubleField.mstInField { symbol("x") + 2 }.compile() -DoubleField.expression("x+2".parseMath()) -``` - #### Known issues - The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid @@ -64,7 +55,7 @@ DoubleField.expression("x+2".parseMath()) A similar feature is also available on JS. ```kotlin -DoubleField.mstInField { symbol("x") + 2 }.compile() +MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` The code above returns expression implemented with such a JS function: @@ -75,13 +66,32 @@ var executable = function (constants, arguments) { }; ``` + +```kotlin +import space.kscience.kmath.wasm.* + +MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) +``` + +An example of emitted WASM IR in the form of WAT: + +```lisp +(func \$executable (param \$0 f64) (result f64) + (f64.add + (local.get \$0) + (f64.const 2) + ) +) +``` + #### Known issues -- This feature uses `eval` which can be unavailable in several environments. +- ESTree expression compilation uses `eval` which can be unavailable in several environments. +- WebAssembly isn't supported by old versions of browsers (see https://webassembly.org/roadmap/). ## Rendering expressions -kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax. +kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax. Example usage: @@ -102,7 +112,7 @@ public fun main() { } ``` -Result LaTeX: +Result LaTeX: ![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D) @@ -112,5 +122,5 @@ Result MathML (embedding MathML is not allowed by GitHub Markdown): ex-sin-12x2×1010+x3-12 ``` -It is also possible to create custom algorithms of render, and even add support of other markup languages +It is also possible to create custom algorithms of render, and even add support of other markup languages (see API reference). diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt deleted file mode 100644 index 93fde5aab..000000000 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.kscisnce.kmath.ast - -import space.kscience.kmath.expressions.MstField -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.expressions.toExpression -import space.kscience.kmath.misc.Symbol.Companion.x -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test - -class InterpretTest { - - @Test - fun interpretation(){ - val expr = MstField { - val x = bindSymbol(x) - x * 2.0 + number(2.0) / x - 16.0 - }.toExpression(DoubleField) - expr(x to 2.2) - } -} \ No newline at end of file diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt similarity index 75% rename from kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt index 6273eff27..509f87d98 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt @@ -1,19 +1,12 @@ -/* - * 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.ast +package space.kscisnce.kmath.ast +import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.evaluate import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.Field import kotlin.test.Test import kotlin.test.assertEquals internal class ParserPrecedenceTest { - private val f: Field = DoubleField - @Test fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath())) @@ -37,4 +30,8 @@ internal class ParserPrecedenceTest { @Test fun test8(): Unit = assertEquals(18.0, f.evaluate("2*2^3+2".parseMath())) + + private companion object { + private val f = DoubleField + } } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt similarity index 67% rename from kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt index 53afaa674..13f5b3290 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt @@ -1,37 +1,24 @@ -/* - * 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.ast +package space.kscisnce.kmath.ast +import space.kscience.kmath.ast.parseMath import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.ComplexField -import space.kscience.kmath.expressions.MstField import space.kscience.kmath.expressions.evaluate -import space.kscience.kmath.expressions.interpret import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals internal class ParserTest { @Test - fun `evaluate MST`() { + fun evaluateParsedMst() { val mst = "2+2*(2+2)".parseMath() val res = ComplexField.evaluate(mst) assertEquals(Complex(10.0, 0.0), res) } @Test - fun `evaluate MSTExpression`() { - val res = MstField.invoke { number(2) + number(2) * (number(2) + number(2)) }.interpret(ComplexField) - assertEquals(Complex(10.0, 0.0), res) - } - - @Test - fun `evaluate MST with singular`() { + fun evaluateMstSymbol() { val mst = "i".parseMath() val res = ComplexField.evaluate(mst) assertEquals(ComplexField.i, res) @@ -39,14 +26,14 @@ internal class ParserTest { @Test - fun `evaluate MST with unary function`() { + fun evaluateMstUnary() { val mst = "sin(0)".parseMath() val res = DoubleField.evaluate(mst) assertEquals(0.0, res) } @Test - fun `evaluate MST with binary function`() { + fun evaluateMstBinary() { val magicalAlgebra = object : Algebra { override fun bindSymbolOrNull(value: String): String = value diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt index 83914f3ec..40468f5ab 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt @@ -6,11 +6,11 @@ package space.kscience.kmath.estree import space.kscience.kmath.estree.internal.ESTreeBuilder -import space.kscience.kmath.estree.internal.estree.BaseExpression import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MST.* import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.internal.estree.BaseExpression import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.NumericAlgebra diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt index 6f917a24c..ac20484a4 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -5,9 +5,14 @@ package space.kscience.kmath.estree.internal -import space.kscience.kmath.estree.internal.astring.generate -import space.kscience.kmath.estree.internal.estree.* import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.internal.astring.generate +import space.kscience.kmath.internal.estree.* +import space.kscience.kmath.internal.estree.BaseExpression +import space.kscience.kmath.internal.estree.BlockStatement +import space.kscience.kmath.internal.estree.Program +import space.kscience.kmath.internal.estree.VariableDeclaration +import space.kscience.kmath.internal.estree.VariableDeclarator import space.kscience.kmath.misc.Symbol internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExpression) { diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/stream/stream.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/stream/stream.kt deleted file mode 100644 index 4bdeeea0b..000000000 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/stream/stream.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * 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.estree.internal.stream - -import space.kscience.kmath.estree.internal.emitter.Emitter - -internal open external class Stream : Emitter { - open fun pipe(dest: Any, options: Any): Any -} diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt similarity index 90% rename from kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.kt rename to kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt index 354757b83..cca2d83af 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt @@ -6,9 +6,9 @@ @file:JsModule("astring") @file:JsNonModule -package space.kscience.kmath.estree.internal.astring +package space.kscience.kmath.internal.astring -import space.kscience.kmath.estree.internal.estree.BaseNode +import space.kscience.kmath.internal.estree.BaseNode internal external interface Options { var indent: String? diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt new file mode 100644 index 000000000..1f6a5f04d --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt @@ -0,0 +1,3 @@ +package space.kscience.kmath.internal.astring + +internal typealias Generator = Any diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt new file mode 100644 index 000000000..a0c7cb6ee --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt @@ -0,0 +1,49 @@ +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", + "OVERRIDING_FINAL_MEMBER", + "RETURN_TYPE_MISMATCH_ON_OVERRIDE", + "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", + "ObjectPropertyName", + "ClassName", +) +@file:JsNonModule +@file:JsModule("js-base64") + +package space.kscience.kmath.internal.base64 + +import org.khronos.webgl.Uint8Array + +internal external var version: Any + +internal external var VERSION: Any + +internal external var btoaPolyfill: (bin: String) -> String + +internal external var _btoa: (bin: String) -> String + +internal external var fromUint8Array: (u8a: Uint8Array, urlsafe: Boolean) -> String + +internal external var utob: (u: String) -> String + +internal external var encode: (src: String, urlsafe: Boolean) -> String + +internal external var encodeURI: (src: String) -> String + +internal external var btou: (b: String) -> String + +internal external var atobPolyfill: (asc: String) -> String + +internal external var _atob: (asc: String) -> String + +internal external var toUint8Array: (a: String) -> Uint8Array + +internal external var decode: (src: String) -> String + +internal external var isValid: (src: Any) -> Boolean + +internal external var extendString: () -> Unit + +internal external var extendUint8Array: () -> Unit + +internal external var extendBuiltins: () -> Unit diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt new file mode 100644 index 000000000..d3e3539c6 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt @@ -0,0 +1,2234 @@ +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", + "OVERRIDING_FINAL_MEMBER", + "RETURN_TYPE_MISMATCH_ON_OVERRIDE", + "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", + "PropertyName", + "ClassName", +) + +@file:JsModule("binaryen") +@file:JsNonModule + +package space.kscience.kmath.internal.binaryen + +import org.khronos.webgl.Uint8Array +import kotlin.js.Promise + +internal external var isReady: Boolean + +internal external var ready: Promise + +internal external var none: Type + +internal external var i32: Type + +internal external var i64: Type + +internal external var f32: Type + +internal external var f64: Type + +internal external var v128: Type + +internal external var funcref: Type + +internal external var anyref: Type + +internal external var nullref: Type + +internal external var exnref: Type + +internal external var unreachable: Type + +internal external var auto: Type + +internal external fun createType(types: Array): Type + +internal external fun expandType(type: Type): Array + +internal external enum class ExpressionIds { + Invalid, + Block, + If, + Loop, + Break, + Switch, + Call, + CallIndirect, + LocalGet, + LocalSet, + GlobalGet, + GlobalSet, + Load, + Store, + Const, + Unary, + Binary, + Select, + Drop, + Return, + Host, + Nop, + Unreachable, + AtomicCmpxchg, + AtomicRMW, + AtomicWait, + AtomicNotify, + AtomicFence, + SIMDExtract, + SIMDReplace, + SIMDShuffle, + SIMDTernary, + SIMDShift, + SIMDLoad, + MemoryInit, + DataDrop, + MemoryCopy, + MemoryFill, + RefNull, + RefIsNull, + RefFunc, + Try, + Throw, + Rethrow, + BrOnExn, + TupleMake, + TupleExtract, + Push, + Pop +} + +internal external var InvalidId: ExpressionIds + +internal external var BlockId: ExpressionIds + +internal external var IfId: ExpressionIds + +internal external var LoopId: ExpressionIds + +internal external var BreakId: ExpressionIds + +internal external var SwitchId: ExpressionIds + +internal external var CallId: ExpressionIds + +internal external var CallIndirectId: ExpressionIds + +internal external var LocalGetId: ExpressionIds + +internal external var LocalSetId: ExpressionIds + +internal external var GlobalGetId: ExpressionIds + +internal external var GlobalSetId: ExpressionIds + +internal external var LoadId: ExpressionIds + +internal external var StoreId: ExpressionIds + +internal external var ConstId: ExpressionIds + +internal external var UnaryId: ExpressionIds + +internal external var BinaryId: ExpressionIds + +internal external var SelectId: ExpressionIds + +internal external var DropId: ExpressionIds + +internal external var ReturnId: ExpressionIds + +internal external var HostId: ExpressionIds + +internal external var NopId: ExpressionIds + +internal external var UnreachableId: ExpressionIds + +internal external var AtomicCmpxchgId: ExpressionIds + +internal external var AtomicRMWId: ExpressionIds + +internal external var AtomicWaitId: ExpressionIds + +internal external var AtomicNotifyId: ExpressionIds + +internal external var AtomicFenceId: ExpressionIds + +internal external var SIMDExtractId: ExpressionIds + +internal external var SIMDReplaceId: ExpressionIds + +internal external var SIMDShuffleId: ExpressionIds + +internal external var SIMDTernaryId: ExpressionIds + +internal external var SIMDShiftId: ExpressionIds + +internal external var SIMDLoadId: ExpressionIds + +internal external var MemoryInitId: ExpressionIds + +internal external var DataDropId: ExpressionIds + +internal external var MemoryCopyId: ExpressionIds + +internal external var MemoryFillId: ExpressionIds + +internal external var RefNullId: ExpressionIds + +internal external var RefIsNullId: ExpressionIds + +internal external var RefFuncId: ExpressionIds + +internal external var TryId: ExpressionIds + +internal external var ThrowId: ExpressionIds + +internal external var RethrowId: ExpressionIds + +internal external var BrOnExnId: ExpressionIds + +internal external var TupleMakeId: ExpressionIds + +internal external var TupleExtractId: ExpressionIds + +internal external var PushId: ExpressionIds + +internal external var PopId: ExpressionIds + +internal external enum class ExternalKinds { + Function, + Table, + Memory, + Global, + Event +} + +internal external var ExternalFunction: ExternalKinds + +internal external var ExternalTable: ExternalKinds + +internal external var ExternalMemory: ExternalKinds + +internal external var ExternalGlobal: ExternalKinds + +internal external var ExternalEvent: ExternalKinds + +internal external enum class Features { + MVP, + Atomics, + MutableGlobals, + TruncSat, + SIMD, + BulkMemory, + SignExt, + ExceptionHandling, + TailCall, + ReferenceTypes, + Multivalue, + GC, + Memory64, + All +} + +internal external enum class Operations { + ClzInt32, + CtzInt32, + PopcntInt32, + NegFloat32, + AbsFloat32, + CeilFloat32, + FloorFloat32, + TruncFloat32, + NearestFloat32, + SqrtFloat32, + EqZInt32, + ClzInt64, + CtzInt64, + PopcntInt64, + NegFloat64, + AbsFloat64, + CeilFloat64, + FloorFloat64, + TruncFloat64, + NearestFloat64, + SqrtFloat64, + EqZInt64, + ExtendSInt32, + ExtendUInt32, + WrapInt64, + TruncSFloat32ToInt32, + TruncSFloat32ToInt64, + TruncUFloat32ToInt32, + TruncUFloat32ToInt64, + TruncSFloat64ToInt32, + TruncSFloat64ToInt64, + TruncUFloat64ToInt32, + TruncUFloat64ToInt64, + TruncSatSFloat32ToInt32, + TruncSatSFloat32ToInt64, + TruncSatUFloat32ToInt32, + TruncSatUFloat32ToInt64, + TruncSatSFloat64ToInt32, + TruncSatSFloat64ToInt64, + TruncSatUFloat64ToInt32, + TruncSatUFloat64ToInt64, + ReinterpretFloat32, + ReinterpretFloat64, + ConvertSInt32ToFloat32, + ConvertSInt32ToFloat64, + ConvertUInt32ToFloat32, + ConvertUInt32ToFloat64, + ConvertSInt64ToFloat32, + ConvertSInt64ToFloat64, + ConvertUInt64ToFloat32, + ConvertUInt64ToFloat64, + PromoteFloat32, + DemoteFloat64, + ReinterpretInt32, + ReinterpretInt64, + ExtendS8Int32, + ExtendS16Int32, + ExtendS8Int64, + ExtendS16Int64, + ExtendS32Int64, + AddInt32, + SubInt32, + MulInt32, + DivSInt32, + DivUInt32, + RemSInt32, + RemUInt32, + AndInt32, + OrInt32, + XorInt32, + ShlInt32, + ShrUInt32, + ShrSInt32, + RotLInt32, + RotRInt32, + EqInt32, + NeInt32, + LtSInt32, + LtUInt32, + LeSInt32, + LeUInt32, + GtSInt32, + GtUInt32, + GeSInt32, + GeUInt32, + AddInt64, + SubInt64, + MulInt64, + DivSInt64, + DivUInt64, + RemSInt64, + RemUInt64, + AndInt64, + OrInt64, + XorInt64, + ShlInt64, + ShrUInt64, + ShrSInt64, + RotLInt64, + RotRInt64, + EqInt64, + NeInt64, + LtSInt64, + LtUInt64, + LeSInt64, + LeUInt64, + GtSInt64, + GtUInt64, + GeSInt64, + GeUInt64, + AddFloat32, + SubFloat32, + MulFloat32, + DivFloat32, + CopySignFloat32, + MinFloat32, + MaxFloat32, + EqFloat32, + NeFloat32, + LtFloat32, + LeFloat32, + GtFloat32, + GeFloat32, + AddFloat64, + SubFloat64, + MulFloat64, + DivFloat64, + CopySignFloat64, + MinFloat64, + MaxFloat64, + EqFloat64, + NeFloat64, + LtFloat64, + LeFloat64, + GtFloat64, + GeFloat64, + MemorySize, + MemoryGrow, + AtomicRMWAdd, + AtomicRMWSub, + AtomicRMWAnd, + AtomicRMWOr, + AtomicRMWXor, + AtomicRMWXchg, + SplatVecI8x16, + ExtractLaneSVecI8x16, + ExtractLaneUVecI8x16, + ReplaceLaneVecI8x16, + SplatVecI16x8, + ExtractLaneSVecI16x8, + ExtractLaneUVecI16x8, + ReplaceLaneVecI16x8, + SplatVecI32x4, + ExtractLaneVecI32x4, + ReplaceLaneVecI32x4, + SplatVecI64x2, + ExtractLaneVecI64x2, + ReplaceLaneVecI64x2, + SplatVecF32x4, + ExtractLaneVecF32x4, + ReplaceLaneVecF32x4, + SplatVecF64x2, + ExtractLaneVecF64x2, + ReplaceLaneVecF64x2, + EqVecI8x16, + NeVecI8x16, + LtSVecI8x16, + LtUVecI8x16, + GtSVecI8x16, + GtUVecI8x16, + LeSVecI8x16, + LeUVecI8x16, + GeSVecI8x16, + GeUVecI8x16, + EqVecI16x8, + NeVecI16x8, + LtSVecI16x8, + LtUVecI16x8, + GtSVecI16x8, + GtUVecI16x8, + LeSVecI16x8, + LeUVecI16x8, + GeSVecI16x8, + GeUVecI16x8, + EqVecI32x4, + NeVecI32x4, + LtSVecI32x4, + LtUVecI32x4, + GtSVecI32x4, + GtUVecI32x4, + LeSVecI32x4, + LeUVecI32x4, + GeSVecI32x4, + GeUVecI32x4, + EqVecF32x4, + NeVecF32x4, + LtVecF32x4, + GtVecF32x4, + LeVecF32x4, + GeVecF32x4, + EqVecF64x2, + NeVecF64x2, + LtVecF64x2, + GtVecF64x2, + LeVecF64x2, + GeVecF64x2, + NotVec128, + AndVec128, + OrVec128, + XorVec128, + AndNotVec128, + BitselectVec128, + NegVecI8x16, + AnyTrueVecI8x16, + AllTrueVecI8x16, + ShlVecI8x16, + ShrSVecI8x16, + ShrUVecI8x16, + AddVecI8x16, + AddSatSVecI8x16, + AddSatUVecI8x16, + SubVecI8x16, + SubSatSVecI8x16, + SubSatUVecI8x16, + MulVecI8x16, + MinSVecI8x16, + MinUVecI8x16, + MaxSVecI8x16, + MaxUVecI8x16, + NegVecI16x8, + AnyTrueVecI16x8, + AllTrueVecI16x8, + ShlVecI16x8, + ShrSVecI16x8, + ShrUVecI16x8, + AddVecI16x8, + AddSatSVecI16x8, + AddSatUVecI16x8, + SubVecI16x8, + SubSatSVecI16x8, + SubSatUVecI16x8, + MulVecI16x8, + MinSVecI16x8, + MinUVecI16x8, + MaxSVecI16x8, + MaxUVecI16x8, + DotSVecI16x8ToVecI32x4, + NegVecI32x4, + AnyTrueVecI32x4, + AllTrueVecI32x4, + ShlVecI32x4, + ShrSVecI32x4, + ShrUVecI32x4, + AddVecI32x4, + SubVecI32x4, + MulVecI32x4, + MinSVecI32x4, + MinUVecI32x4, + MaxSVecI32x4, + MaxUVecI32x4, + NegVecI64x2, + AnyTrueVecI64x2, + AllTrueVecI64x2, + ShlVecI64x2, + ShrSVecI64x2, + ShrUVecI64x2, + AddVecI64x2, + SubVecI64x2, + AbsVecF32x4, + NegVecF32x4, + SqrtVecF32x4, + QFMAVecF32x4, + QFMSVecF32x4, + AddVecF32x4, + SubVecF32x4, + MulVecF32x4, + DivVecF32x4, + MinVecF32x4, + MaxVecF32x4, + AbsVecF64x2, + NegVecF64x2, + SqrtVecF64x2, + QFMAVecF64x2, + QFMSVecF64x2, + AddVecF64x2, + SubVecF64x2, + MulVecF64x2, + DivVecF64x2, + MinVecF64x2, + MaxVecF64x2, + TruncSatSVecF32x4ToVecI32x4, + TruncSatUVecF32x4ToVecI32x4, + TruncSatSVecF64x2ToVecI64x2, + TruncSatUVecF64x2ToVecI64x2, + ConvertSVecI32x4ToVecF32x4, + ConvertUVecI32x4ToVecF32x4, + ConvertSVecI64x2ToVecF64x2, + ConvertUVecI64x2ToVecF64x2, + LoadSplatVec8x16, + LoadSplatVec16x8, + LoadSplatVec32x4, + LoadSplatVec64x2, + LoadExtSVec8x8ToVecI16x8, + LoadExtUVec8x8ToVecI16x8, + LoadExtSVec16x4ToVecI32x4, + LoadExtUVec16x4ToVecI32x4, + LoadExtSVec32x2ToVecI64x2, + LoadExtUVec32x2ToVecI64x2, + NarrowSVecI16x8ToVecI8x16, + NarrowUVecI16x8ToVecI8x16, + NarrowSVecI32x4ToVecI16x8, + NarrowUVecI32x4ToVecI16x8, + WidenLowSVecI8x16ToVecI16x8, + WidenHighSVecI8x16ToVecI16x8, + WidenLowUVecI8x16ToVecI16x8, + WidenHighUVecI8x16ToVecI16x8, + WidenLowSVecI16x8ToVecI32x4, + WidenHighSVecI16x8ToVecI32x4, + WidenLowUVecI16x8ToVecI32x4, + WidenHighUVecI16x8ToVecI32x4, + SwizzleVec8x16 +} + +internal external var ClzInt32: Operations + +internal external var CtzInt32: Operations + +internal external var PopcntInt32: Operations + +internal external var NegFloat32: Operations + +internal external var AbsFloat32: Operations + +internal external var CeilFloat32: Operations + +internal external var FloorFloat32: Operations + +internal external var TruncFloat32: Operations + +internal external var NearestFloat32: Operations + +internal external var SqrtFloat32: Operations + +internal external var EqZInt32: Operations + +internal external var ClzInt64: Operations + +internal external var CtzInt64: Operations + +internal external var PopcntInt64: Operations + +internal external var NegFloat64: Operations + +internal external var AbsFloat64: Operations + +internal external var CeilFloat64: Operations + +internal external var FloorFloat64: Operations + +internal external var TruncFloat64: Operations + +internal external var NearestFloat64: Operations + +internal external var SqrtFloat64: Operations + +internal external var EqZInt64: Operations + +internal external var ExtendSInt32: Operations + +internal external var ExtendUInt32: Operations + +internal external var WrapInt64: Operations + +internal external var TruncSFloat32ToInt32: Operations + +internal external var TruncSFloat32ToInt64: Operations + +internal external var TruncUFloat32ToInt32: Operations + +internal external var TruncUFloat32ToInt64: Operations + +internal external var TruncSFloat64ToInt32: Operations + +internal external var TruncSFloat64ToInt64: Operations + +internal external var TruncUFloat64ToInt32: Operations + +internal external var TruncUFloat64ToInt64: Operations + +internal external var TruncSatSFloat32ToInt32: Operations + +internal external var TruncSatSFloat32ToInt64: Operations + +internal external var TruncSatUFloat32ToInt32: Operations + +internal external var TruncSatUFloat32ToInt64: Operations + +internal external var TruncSatSFloat64ToInt32: Operations + +internal external var TruncSatSFloat64ToInt64: Operations + +internal external var TruncSatUFloat64ToInt32: Operations + +internal external var TruncSatUFloat64ToInt64: Operations + +internal external var ReinterpretFloat32: Operations + +internal external var ReinterpretFloat64: Operations + +internal external var ConvertSInt32ToFloat32: Operations + +internal external var ConvertSInt32ToFloat64: Operations + +internal external var ConvertUInt32ToFloat32: Operations + +internal external var ConvertUInt32ToFloat64: Operations + +internal external var ConvertSInt64ToFloat32: Operations + +internal external var ConvertSInt64ToFloat64: Operations + +internal external var ConvertUInt64ToFloat32: Operations + +internal external var ConvertUInt64ToFloat64: Operations + +internal external var PromoteFloat32: Operations + +internal external var DemoteFloat64: Operations + +internal external var ReinterpretInt32: Operations + +internal external var ReinterpretInt64: Operations + +internal external var ExtendS8Int32: Operations + +internal external var ExtendS16Int32: Operations + +internal external var ExtendS8Int64: Operations + +internal external var ExtendS16Int64: Operations + +internal external var ExtendS32Int64: Operations + +internal external var AddInt32: Operations + +internal external var SubInt32: Operations + +internal external var MulInt32: Operations + +internal external var DivSInt32: Operations + +internal external var DivUInt32: Operations + +internal external var RemSInt32: Operations + +internal external var RemUInt32: Operations + +internal external var AndInt32: Operations + +internal external var OrInt32: Operations + +internal external var XorInt32: Operations + +internal external var ShlInt32: Operations + +internal external var ShrUInt32: Operations + +internal external var ShrSInt32: Operations + +internal external var RotLInt32: Operations + +internal external var RotRInt32: Operations + +internal external var EqInt32: Operations + +internal external var NeInt32: Operations + +internal external var LtSInt32: Operations + +internal external var LtUInt32: Operations + +internal external var LeSInt32: Operations + +internal external var LeUInt32: Operations + +internal external var GtSInt32: Operations + +internal external var GtUInt32: Operations + +internal external var GeSInt32: Operations + +internal external var GeUInt32: Operations + +internal external var AddInt64: Operations + +internal external var SubInt64: Operations + +internal external var MulInt64: Operations + +internal external var DivSInt64: Operations + +internal external var DivUInt64: Operations + +internal external var RemSInt64: Operations + +internal external var RemUInt64: Operations + +internal external var AndInt64: Operations + +internal external var OrInt64: Operations + +internal external var XorInt64: Operations + +internal external var ShlInt64: Operations + +internal external var ShrUInt64: Operations + +internal external var ShrSInt64: Operations + +internal external var RotLInt64: Operations + +internal external var RotRInt64: Operations + +internal external var EqInt64: Operations + +internal external var NeInt64: Operations + +internal external var LtSInt64: Operations + +internal external var LtUInt64: Operations + +internal external var LeSInt64: Operations + +internal external var LeUInt64: Operations + +internal external var GtSInt64: Operations + +internal external var GtUInt64: Operations + +internal external var GeSInt64: Operations + +internal external var GeUInt64: Operations + +internal external var AddFloat32: Operations + +internal external var SubFloat32: Operations + +internal external var MulFloat32: Operations + +internal external var DivFloat32: Operations + +internal external var CopySignFloat32: Operations + +internal external var MinFloat32: Operations + +internal external var MaxFloat32: Operations + +internal external var EqFloat32: Operations + +internal external var NeFloat32: Operations + +internal external var LtFloat32: Operations + +internal external var LeFloat32: Operations + +internal external var GtFloat32: Operations + +internal external var GeFloat32: Operations + +internal external var AddFloat64: Operations + +internal external var SubFloat64: Operations + +internal external var MulFloat64: Operations + +internal external var DivFloat64: Operations + +internal external var CopySignFloat64: Operations + +internal external var MinFloat64: Operations + +internal external var MaxFloat64: Operations + +internal external var EqFloat64: Operations + +internal external var NeFloat64: Operations + +internal external var LtFloat64: Operations + +internal external var LeFloat64: Operations + +internal external var GtFloat64: Operations + +internal external var GeFloat64: Operations + +internal external var MemorySize: Operations + +internal external var MemoryGrow: Operations + +internal external var AtomicRMWAdd: Operations + +internal external var AtomicRMWSub: Operations + +internal external var AtomicRMWAnd: Operations + +internal external var AtomicRMWOr: Operations + +internal external var AtomicRMWXor: Operations + +internal external var AtomicRMWXchg: Operations + +internal external var SplatVecI8x16: Operations + +internal external var ExtractLaneSVecI8x16: Operations + +internal external var ExtractLaneUVecI8x16: Operations + +internal external var ReplaceLaneVecI8x16: Operations + +internal external var SplatVecI16x8: Operations + +internal external var ExtractLaneSVecI16x8: Operations + +internal external var ExtractLaneUVecI16x8: Operations + +internal external var ReplaceLaneVecI16x8: Operations + +internal external var SplatVecI32x4: Operations + +internal external var ExtractLaneVecI32x4: Operations + +internal external var ReplaceLaneVecI32x4: Operations + +internal external var SplatVecI64x2: Operations + +internal external var ExtractLaneVecI64x2: Operations + +internal external var ReplaceLaneVecI64x2: Operations + +internal external var SplatVecF32x4: Operations + +internal external var ExtractLaneVecF32x4: Operations + +internal external var ReplaceLaneVecF32x4: Operations + +internal external var SplatVecF64x2: Operations + +internal external var ExtractLaneVecF64x2: Operations + +internal external var ReplaceLaneVecF64x2: Operations + +internal external var EqVecI8x16: Operations + +internal external var NeVecI8x16: Operations + +internal external var LtSVecI8x16: Operations + +internal external var LtUVecI8x16: Operations + +internal external var GtSVecI8x16: Operations + +internal external var GtUVecI8x16: Operations + +internal external var LeSVecI8x16: Operations + +internal external var LeUVecI8x16: Operations + +internal external var GeSVecI8x16: Operations + +internal external var GeUVecI8x16: Operations + +internal external var EqVecI16x8: Operations + +internal external var NeVecI16x8: Operations + +internal external var LtSVecI16x8: Operations + +internal external var LtUVecI16x8: Operations + +internal external var GtSVecI16x8: Operations + +internal external var GtUVecI16x8: Operations + +internal external var LeSVecI16x8: Operations + +internal external var LeUVecI16x8: Operations + +internal external var GeSVecI16x8: Operations + +internal external var GeUVecI16x8: Operations + +internal external var EqVecI32x4: Operations + +internal external var NeVecI32x4: Operations + +internal external var LtSVecI32x4: Operations + +internal external var LtUVecI32x4: Operations + +internal external var GtSVecI32x4: Operations + +internal external var GtUVecI32x4: Operations + +internal external var LeSVecI32x4: Operations + +internal external var LeUVecI32x4: Operations + +internal external var GeSVecI32x4: Operations + +internal external var GeUVecI32x4: Operations + +internal external var EqVecF32x4: Operations + +internal external var NeVecF32x4: Operations + +internal external var LtVecF32x4: Operations + +internal external var GtVecF32x4: Operations + +internal external var LeVecF32x4: Operations + +internal external var GeVecF32x4: Operations + +internal external var EqVecF64x2: Operations + +internal external var NeVecF64x2: Operations + +internal external var LtVecF64x2: Operations + +internal external var GtVecF64x2: Operations + +internal external var LeVecF64x2: Operations + +internal external var GeVecF64x2: Operations + +internal external var NotVec128: Operations + +internal external var AndVec128: Operations + +internal external var OrVec128: Operations + +internal external var XorVec128: Operations + +internal external var AndNotVec128: Operations + +internal external var BitselectVec128: Operations + +internal external var NegVecI8x16: Operations + +internal external var AnyTrueVecI8x16: Operations + +internal external var AllTrueVecI8x16: Operations + +internal external var ShlVecI8x16: Operations + +internal external var ShrSVecI8x16: Operations + +internal external var ShrUVecI8x16: Operations + +internal external var AddVecI8x16: Operations + +internal external var AddSatSVecI8x16: Operations + +internal external var AddSatUVecI8x16: Operations + +internal external var SubVecI8x16: Operations + +internal external var SubSatSVecI8x16: Operations + +internal external var SubSatUVecI8x16: Operations + +internal external var MulVecI8x16: Operations + +internal external var MinSVecI8x16: Operations + +internal external var MinUVecI8x16: Operations + +internal external var MaxSVecI8x16: Operations + +internal external var MaxUVecI8x16: Operations + +internal external var NegVecI16x8: Operations + +internal external var AnyTrueVecI16x8: Operations + +internal external var AllTrueVecI16x8: Operations + +internal external var ShlVecI16x8: Operations + +internal external var ShrSVecI16x8: Operations + +internal external var ShrUVecI16x8: Operations + +internal external var AddVecI16x8: Operations + +internal external var AddSatSVecI16x8: Operations + +internal external var AddSatUVecI16x8: Operations + +internal external var SubVecI16x8: Operations + +internal external var SubSatSVecI16x8: Operations + +internal external var SubSatUVecI16x8: Operations + +internal external var MulVecI16x8: Operations + +internal external var MinSVecI16x8: Operations + +internal external var MinUVecI16x8: Operations + +internal external var MaxSVecI16x8: Operations + +internal external var MaxUVecI16x8: Operations + +internal external var DotSVecI16x8ToVecI32x4: Operations + +internal external var NegVecI32x4: Operations + +internal external var AnyTrueVecI32x4: Operations + +internal external var AllTrueVecI32x4: Operations + +internal external var ShlVecI32x4: Operations + +internal external var ShrSVecI32x4: Operations + +internal external var ShrUVecI32x4: Operations + +internal external var AddVecI32x4: Operations + +internal external var SubVecI32x4: Operations + +internal external var MulVecI32x4: Operations + +internal external var MinSVecI32x4: Operations + +internal external var MinUVecI32x4: Operations + +internal external var MaxSVecI32x4: Operations + +internal external var MaxUVecI32x4: Operations + +internal external var NegVecI64x2: Operations + +internal external var AnyTrueVecI64x2: Operations + +internal external var AllTrueVecI64x2: Operations + +internal external var ShlVecI64x2: Operations + +internal external var ShrSVecI64x2: Operations + +internal external var ShrUVecI64x2: Operations + +internal external var AddVecI64x2: Operations + +internal external var SubVecI64x2: Operations + +internal external var AbsVecF32x4: Operations + +internal external var NegVecF32x4: Operations + +internal external var SqrtVecF32x4: Operations + +internal external var QFMAVecF32x4: Operations + +internal external var QFMSVecF32x4: Operations + +internal external var AddVecF32x4: Operations + +internal external var SubVecF32x4: Operations + +internal external var MulVecF32x4: Operations + +internal external var DivVecF32x4: Operations + +internal external var MinVecF32x4: Operations + +internal external var MaxVecF32x4: Operations + +internal external var AbsVecF64x2: Operations + +internal external var NegVecF64x2: Operations + +internal external var SqrtVecF64x2: Operations + +internal external var QFMAVecF64x2: Operations + +internal external var QFMSVecF64x2: Operations + +internal external var AddVecF64x2: Operations + +internal external var SubVecF64x2: Operations + +internal external var MulVecF64x2: Operations + +internal external var DivVecF64x2: Operations + +internal external var MinVecF64x2: Operations + +internal external var MaxVecF64x2: Operations + +internal external var TruncSatSVecF32x4ToVecI32x4: Operations + +internal external var TruncSatUVecF32x4ToVecI32x4: Operations + +internal external var TruncSatSVecF64x2ToVecI64x2: Operations + +internal external var TruncSatUVecF64x2ToVecI64x2: Operations + +internal external var ConvertSVecI32x4ToVecF32x4: Operations + +internal external var ConvertUVecI32x4ToVecF32x4: Operations + +internal external var ConvertSVecI64x2ToVecF64x2: Operations + +internal external var ConvertUVecI64x2ToVecF64x2: Operations + +internal external var LoadSplatVec8x16: Operations + +internal external var LoadSplatVec16x8: Operations + +internal external var LoadSplatVec32x4: Operations + +internal external var LoadSplatVec64x2: Operations + +internal external var LoadExtSVec8x8ToVecI16x8: Operations + +internal external var LoadExtUVec8x8ToVecI16x8: Operations + +internal external var LoadExtSVec16x4ToVecI32x4: Operations + +internal external var LoadExtUVec16x4ToVecI32x4: Operations + +internal external var LoadExtSVec32x2ToVecI64x2: Operations + +internal external var LoadExtUVec32x2ToVecI64x2: Operations + +internal external var NarrowSVecI16x8ToVecI8x16: Operations + +internal external var NarrowUVecI16x8ToVecI8x16: Operations + +internal external var NarrowSVecI32x4ToVecI16x8: Operations + +internal external var NarrowUVecI32x4ToVecI16x8: Operations + +internal external var WidenLowSVecI8x16ToVecI16x8: Operations + +internal external var WidenHighSVecI8x16ToVecI16x8: Operations + +internal external var WidenLowUVecI8x16ToVecI16x8: Operations + +internal external var WidenHighUVecI8x16ToVecI16x8: Operations + +internal external var WidenLowSVecI16x8ToVecI32x4: Operations + +internal external var WidenHighSVecI16x8ToVecI32x4: Operations + +internal external var WidenLowUVecI16x8ToVecI32x4: Operations + +internal external var WidenHighUVecI16x8ToVecI32x4: Operations + +internal external var SwizzleVec8x16: Operations + +internal external interface `T$2` { + fun get(index: Number, type: Type): ExpressionRef + fun set(index: Number, value: ExpressionRef): ExpressionRef + fun tee(index: Number, value: ExpressionRef, type: Type): ExpressionRef +} + +internal external interface `T$3` { + fun get(name: String, type: Type): ExpressionRef + fun set(name: String, value: ExpressionRef): ExpressionRef +} + +internal external interface `T$4` { + fun size(): ExpressionRef + fun grow(value: ExpressionRef): ExpressionRef + fun init(segment: Number, dest: ExpressionRef, offset: ExpressionRef, size: ExpressionRef): ExpressionRef + fun copy(dest: ExpressionRef, source: ExpressionRef, size: ExpressionRef): ExpressionRef + fun fill(dest: ExpressionRef, value: ExpressionRef, size: ExpressionRef): ExpressionRef +} + +internal external interface `T$5` { + fun drop(segment: Number): ExpressionRef +} + +internal external interface `T$6` { + fun f32(value: ExpressionRef): ExpressionRef + fun f64(value: ExpressionRef): ExpressionRef +} + +internal external interface `T$7` { + fun add(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun sub(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun and(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun or(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun xor(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun xchg(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun cmpxchg(offset: Number, ptr: ExpressionRef, expected: ExpressionRef, replacement: ExpressionRef): ExpressionRef +} + +internal external interface `T$8` { + fun load(offset: Number, ptr: ExpressionRef): ExpressionRef + fun load8_u(offset: Number, ptr: ExpressionRef): ExpressionRef + fun load16_u(offset: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store8(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store16(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + var rmw: `T$7` + var rmw8_u: `T$7` + var rmw16_u: `T$7` + fun wait(ptr: ExpressionRef, expected: ExpressionRef, timeout: ExpressionRef): ExpressionRef +} + +internal external interface `T$9` { + fun load(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load8_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load8_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load16_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load16_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store8(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store16(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun const(value: Number): ExpressionRef + fun clz(value: ExpressionRef): ExpressionRef + fun ctz(value: ExpressionRef): ExpressionRef + fun popcnt(value: ExpressionRef): ExpressionRef + fun eqz(value: ExpressionRef): ExpressionRef + var trunc_s: `T$6` + var trunc_u: `T$6` + var trunc_s_sat: `T$6` + var trunc_u_sat: `T$6` + fun reinterpret(value: ExpressionRef): ExpressionRef + fun extend8_s(value: ExpressionRef): ExpressionRef + fun extend16_s(value: ExpressionRef): ExpressionRef + fun wrap(value: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rem_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rem_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun and(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun or(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun xor(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun shl(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun shr_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun shr_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rotl(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rotr(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + var atomic: `T$8` + fun pop(): ExpressionRef +} + +internal external interface `T$10` { + fun load(offset: Number, ptr: ExpressionRef): ExpressionRef + fun load8_u(offset: Number, ptr: ExpressionRef): ExpressionRef + fun load16_u(offset: Number, ptr: ExpressionRef): ExpressionRef + fun load32_u(offset: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store8(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store16(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store32(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + var rmw: `T$7` + var rmw8_u: `T$7` + var rmw16_u: `T$7` + var rmw32_u: `T$7` + fun wait(ptr: ExpressionRef, expected: ExpressionRef, timeout: ExpressionRef): ExpressionRef +} + +internal external interface `T$11` { + fun load(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load8_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load8_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load16_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load16_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load32_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load32_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store8(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store16(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store32(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun const(low: Number, high: Number): ExpressionRef + fun clz(value: ExpressionRef): ExpressionRef + fun ctz(value: ExpressionRef): ExpressionRef + fun popcnt(value: ExpressionRef): ExpressionRef + fun eqz(value: ExpressionRef): ExpressionRef + var trunc_s: `T$6` + var trunc_u: `T$6` + var trunc_s_sat: `T$6` + var trunc_u_sat: `T$6` + fun reinterpret(value: ExpressionRef): ExpressionRef + fun extend8_s(value: ExpressionRef): ExpressionRef + fun extend16_s(value: ExpressionRef): ExpressionRef + fun extend32_s(value: ExpressionRef): ExpressionRef + fun extend_s(value: ExpressionRef): ExpressionRef + fun extend_u(value: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rem_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rem_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun and(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun or(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun xor(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun shl(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun shr_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun shr_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rotl(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rotr(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + var atomic: `T$10` + fun pop(): ExpressionRef +} + +internal external interface `T$12` { + fun load(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun const(value: Number): ExpressionRef + fun const_bits(value: Number): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun abs(value: ExpressionRef): ExpressionRef + fun ceil(value: ExpressionRef): ExpressionRef + fun floor(value: ExpressionRef): ExpressionRef + fun trunc(value: ExpressionRef): ExpressionRef + fun nearest(value: ExpressionRef): ExpressionRef + fun sqrt(value: ExpressionRef): ExpressionRef + fun reinterpret(value: ExpressionRef): ExpressionRef + var convert_s: `T$6` + var convert_u: `T$6` + fun demote(value: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun copysign(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun pop(): ExpressionRef +} + +internal external interface `T$13` { + fun load(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun const(value: Number): ExpressionRef + fun const_bits(low: Number, high: Number): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun abs(value: ExpressionRef): ExpressionRef + fun ceil(value: ExpressionRef): ExpressionRef + fun floor(value: ExpressionRef): ExpressionRef + fun trunc(value: ExpressionRef): ExpressionRef + fun nearest(value: ExpressionRef): ExpressionRef + fun sqrt(value: ExpressionRef): ExpressionRef + fun reinterpret(value: ExpressionRef): ExpressionRef + var convert_s: `T$6` + var convert_u: `T$6` + fun promote(value: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun copysign(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun pop(): ExpressionRef +} + +internal external interface `T$14` { + fun load(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun const(value: Number): ExpressionRef + fun not(value: ExpressionRef): ExpressionRef + fun and(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun or(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun xor(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun andnot(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun bitselect(left: ExpressionRef, right: ExpressionRef, cond: ExpressionRef): ExpressionRef + fun pop(): ExpressionRef +} + +internal external interface `T$15` { + fun splat(value: ExpressionRef): ExpressionRef + fun extract_lane_s(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun extract_lane_u(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun replace_lane(vec: ExpressionRef, index: ExpressionRef, value: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun any_true(value: ExpressionRef): ExpressionRef + fun all_true(value: ExpressionRef): ExpressionRef + fun shl(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_s(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_u(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun add_saturate_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun add_saturate_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub_saturate_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub_saturate_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun avgr_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun narrow_i16x8_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun narrow_i16x8_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef +} + +internal external interface `T$16` { + fun splat(value: ExpressionRef): ExpressionRef + fun extract_lane_s(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun extract_lane_u(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun replace_lane(vec: ExpressionRef, index: ExpressionRef, value: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun any_true(value: ExpressionRef): ExpressionRef + fun all_true(value: ExpressionRef): ExpressionRef + fun shl(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_s(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_u(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun add_saturate_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun add_saturate_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub_saturate_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub_saturate_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun avgr_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun narrow_i32x4_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun narrow_i32x4_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun widen_low_i8x16_s(value: ExpressionRef): ExpressionRef + fun widen_high_i8x16_s(value: ExpressionRef): ExpressionRef + fun widen_low_i8x16_u(value: ExpressionRef): ExpressionRef + fun widen_high_i8x16_u(value: ExpressionRef): ExpressionRef + fun load8x8_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load8x8_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef +} + +internal external interface `T$17` { + fun splat(value: ExpressionRef): ExpressionRef + fun extract_lane(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun replace_lane(vec: ExpressionRef, index: ExpressionRef, value: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun any_true(value: ExpressionRef): ExpressionRef + fun all_true(value: ExpressionRef): ExpressionRef + fun shl(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_s(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_u(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun trunc_sat_f32x4_s(value: ExpressionRef): ExpressionRef + fun trunc_sat_f32x4_u(value: ExpressionRef): ExpressionRef + fun widen_low_i16x8_s(value: ExpressionRef): ExpressionRef + fun widen_high_i16x8_s(value: ExpressionRef): ExpressionRef + fun widen_low_i16x8_u(value: ExpressionRef): ExpressionRef + fun widen_high_i16x8_u(value: ExpressionRef): ExpressionRef + fun load16x4_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load16x4_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef +} + +internal external interface `T$18` { + fun splat(value: ExpressionRef): ExpressionRef + fun extract_lane(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun replace_lane(vec: ExpressionRef, index: ExpressionRef, value: ExpressionRef): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun any_true(value: ExpressionRef): ExpressionRef + fun all_true(value: ExpressionRef): ExpressionRef + fun shl(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_s(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_u(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun trunc_sat_f64x2_s(value: ExpressionRef): ExpressionRef + fun trunc_sat_f64x2_u(value: ExpressionRef): ExpressionRef + fun load32x2_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load32x2_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef +} + +internal external interface `T$19` { + fun splat(value: ExpressionRef): ExpressionRef + fun extract_lane(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun replace_lane(vec: ExpressionRef, index: ExpressionRef, value: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun abs(value: ExpressionRef): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun sqrt(value: ExpressionRef): ExpressionRef + fun qfma(a: ExpressionRef, b: ExpressionRef, c: ExpressionRef): ExpressionRef + fun qfms(a: ExpressionRef, b: ExpressionRef, c: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun convert_i32x4_s(value: ExpressionRef): ExpressionRef + fun convert_i32x4_u(value: ExpressionRef): ExpressionRef +} + +internal external interface `T$20` { + fun shuffle(left: ExpressionRef, right: ExpressionRef, mask: Array): ExpressionRef + fun swizzle(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun load_splat(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef +} + +internal external interface `T$21` { + fun load_splat(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef +} + +internal external interface `T$22` { + fun pop(): ExpressionRef +} + +internal external interface `T$23` { + fun `null`(): ExpressionRef + fun is_null(value: ExpressionRef): ExpressionRef + fun func(name: String): ExpressionRef +} + +internal external interface `T$24` { + fun notify(ptr: ExpressionRef, notifyCount: ExpressionRef): ExpressionRef + fun fence(): ExpressionRef +} + +internal external interface `T$25` { + fun make(elements: Array): ExpressionRef + fun extract(tuple: ExpressionRef, index: Number): ExpressionRef +} + +internal external interface `T$26` { + var imported: Boolean + var segments: Array +} + +internal external interface `T$27` { + var binary: Uint8Array + var sourceMap: String? +} + +internal open external class Module { + open var ptr: Number + open fun block(label: String, children: Array, resultType: Type = definedExternally): ExpressionRef + open fun `if`( + condition: ExpressionRef, + ifTrue: ExpressionRef, + ifFalse: ExpressionRef = definedExternally + ): ExpressionRef + + open fun loop(label: String, body: ExpressionRef): ExpressionRef + open fun br( + label: String, + condition: ExpressionRef = definedExternally, + value: ExpressionRef = definedExternally + ): ExpressionRef + + open fun br_if( + label: String, + condition: ExpressionRef = definedExternally, + value: ExpressionRef = definedExternally + ): ExpressionRef + + open fun switch( + labels: Array, + defaultLabel: String, + condition: ExpressionRef, + value: ExpressionRef = definedExternally + ): ExpressionRef + + open fun call(name: String, operands: Array, returnType: Type): ExpressionRef + open fun return_call(name: String, operands: Array, returnType: Type): ExpressionRef + open fun call_indirect( + target: ExpressionRef, + operands: Array, + params: Type, + results: Type + ): ExpressionRef + + open fun return_call_indirect( + target: ExpressionRef, + operands: Array, + params: Type, + results: Type + ): ExpressionRef + + open var local: `T$2` + open var global: `T$3` + open var memory: `T$4` + open var data: `T$5` + open var i32: `T$9` + open var i64: `T$11` + open var f32: `T$12` + open var f64: `T$13` + open var v128: `T$14` + open var i8x16: `T$15` + open var i16x8: `T$16` + open var i32x4: `T$17` + open var i64x2: `T$18` + open var f32x4: `T$19` + open var f64x2: `T$19` + open var v8x16: `T$20` + open var v16x8: `T$21` + open var v32x4: `T$21` + open var v64x2: `T$21` + open var funcref: `T$22` + open var anyref: `T$22` + open var nullref: `T$22` + open var exnref: `T$22` + open var ref: `T$23` + open var atomic: `T$24` + open var tuple: `T$25` + open fun `try`(body: ExpressionRef, catchBody: ExpressionRef): ExpressionRef + open fun `throw`(event: String, operands: Array): ExpressionRef + open fun rethrow(exnref: ExpressionRef): ExpressionRef + open fun br_on_exn(label: String, event: String, exnref: ExpressionRef): ExpressionRef + open fun push(value: ExpressionRef): ExpressionRef + open fun select( + condition: ExpressionRef, + ifTrue: ExpressionRef, + ifFalse: ExpressionRef, + type: Type = definedExternally + ): ExpressionRef + + open fun drop(value: ExpressionRef): ExpressionRef + open fun `return`(value: ExpressionRef = definedExternally): ExpressionRef + open fun host(op: Operations, name: String, operands: Array): ExpressionRef + open fun nop(): ExpressionRef + open fun unreachable(): ExpressionRef + open fun addFunction(name: String, params: Type, results: Type, vars: Array, body: ExpressionRef): FunctionRef + open fun getFunction(name: String): FunctionRef + open fun removeFunction(name: String) + open fun getNumFunctions(): Number + open fun getFunctionByIndex(index: Number): FunctionRef + open fun addGlobal(name: String, type: Type, mutable: Boolean, init: ExpressionRef): GlobalRef + open fun getGlobal(name: String): GlobalRef + open fun removeGlobal(name: String) + open fun addEvent(name: String, attribute: Number, params: Type, results: Type): EventRef + open fun getEvent(name: String): EventRef + open fun removeEvent(name: String) + open fun addFunctionImport( + internalName: String, + externalModuleName: String, + externalBaseName: String, + params: Type, + results: Type + ) + + open fun addTableImport(internalName: String, externalModuleName: String, externalBaseName: String) + open fun addMemoryImport(internalName: String, externalModuleName: String, externalBaseName: String) + open fun addGlobalImport( + internalName: String, + externalModuleName: String, + externalBaseName: String, + globalType: Type + ) + + open fun addEventImport( + internalName: String, + externalModuleName: String, + externalBaseName: String, + attribute: Number, + params: Type, + results: Type + ) + + open fun addFunctionExport(internalName: String, externalName: String): ExportRef + open fun addTableExport(internalName: String, externalName: String): ExportRef + open fun addMemoryExport(internalName: String, externalName: String): ExportRef + open fun addGlobalExport(internalName: String, externalName: String): ExportRef + open fun removeExport(externalName: String) + open fun getNumExports(): Number + open fun getExportByIndex(index: Number): ExportRef + open fun setFunctionTable( + initial: Number, + maximum: Number, + funcNames: Array, + offset: ExpressionRef = definedExternally + ) + + open fun getFunctionTable(): `T$26` + open fun setMemory( + initial: Number, + maximum: Number, + exportName: String? = definedExternally, + segments: Array? = definedExternally, + flags: Array? = definedExternally, + shared: Boolean = definedExternally + ) + + open fun getNumMemorySegments(): Number + open fun getMemorySegmentInfoByIndex(index: Number): MemorySegmentInfo + open fun setStart(start: FunctionRef) + open fun getFeatures(): Features + open fun setFeatures(features: Features) + open fun addCustomSection(name: String, contents: Uint8Array) + open fun emitText(): String + open fun emitStackIR(optimize: Boolean = definedExternally): String + open fun emitAsmjs(): String + open fun validate(): Number + open fun optimize() + open fun optimizeFunction(func: String) + open fun optimizeFunction(func: FunctionRef) + open fun runPasses(passes: Array) + open fun runPassesOnFunction(func: String, passes: Array) + open fun runPassesOnFunction(func: FunctionRef, passes: Array) + open fun autoDrop() + open fun dispose() + open fun emitBinary(): Uint8Array + open fun emitBinary(sourceMapUrl: String?): `T$27` + open fun interpret() + open fun addDebugInfoFileName(filename: String): Number + open fun getDebugInfoFileName(index: Number): String? + open fun setDebugLocation( + func: FunctionRef, + expr: ExpressionRef, + fileIndex: Number, + lineNumber: Number, + columnNumber: Number + ) + + open fun copyExpression(expr: ExpressionRef): ExpressionRef +} + +internal external interface MemorySegment { + var offset: ExpressionRef + var data: Uint8Array + var passive: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +internal external interface TableElement { + var offset: ExpressionRef + var names: Array +} + +internal external fun wrapModule(ptr: Number): Module + +internal external fun getExpressionId(expression: ExpressionRef): Number + +internal external fun getExpressionType(expression: ExpressionRef): Type + +internal external fun getExpressionInfo(expression: ExpressionRef): ExpressionInfo + +internal external interface MemorySegmentInfo { + var offset: ExpressionRef + var data: Uint8Array + var passive: Boolean +} + +internal external interface ExpressionInfo { + var id: ExpressionIds + var type: Type +} + +internal external interface BlockInfo : ExpressionInfo { + var name: String + var children: Array +} + +internal external interface IfInfo : ExpressionInfo { + var condition: ExpressionRef + var ifTrue: ExpressionRef + var ifFalse: ExpressionRef +} + +internal external interface LoopInfo : ExpressionInfo { + var name: String + var body: ExpressionRef +} + +internal external interface BreakInfo : ExpressionInfo { + var name: String + var condition: ExpressionRef + var value: ExpressionRef +} + +internal external interface SwitchInfo : ExpressionInfo { + var names: Array + var defaultName: String? + var condition: ExpressionRef + var value: ExpressionRef +} + +internal external interface CallInfo : ExpressionInfo { + var isReturn: Boolean + var target: String + var operands: Array +} + +internal external interface CallIndirectInfo : ExpressionInfo { + var isReturn: Boolean + var target: ExpressionRef + var operands: Array +} + +internal external interface LocalGetInfo : ExpressionInfo { + var index: Number +} + +internal external interface LocalSetInfo : ExpressionInfo { + var isTee: Boolean + var index: Number + var value: ExpressionRef +} + +internal external interface GlobalGetInfo : ExpressionInfo { + var name: String +} + +internal external interface GlobalSetInfo : ExpressionInfo { + var name: String + var value: ExpressionRef +} + +internal external interface LoadInfo : ExpressionInfo { + var isAtomic: Boolean + var isSigned: Boolean + var offset: Number + var bytes: Number + var align: Number + var ptr: ExpressionRef +} + +internal external interface StoreInfo : ExpressionInfo { + var isAtomic: Boolean + var offset: Number + var bytes: Number + var align: Number + var ptr: ExpressionRef + var value: ExpressionRef +} + +internal external interface `T$28` { + var low: Number + var high: Number +} + +internal external interface ConstInfo : ExpressionInfo { + var value: dynamic /* Number | `T$28` */ + get() = definedExternally + set(value) = definedExternally +} + +internal external interface UnaryInfo : ExpressionInfo { + var op: Operations + var value: ExpressionRef +} + +internal external interface BinaryInfo : ExpressionInfo { + var op: Operations + var left: ExpressionRef + var right: ExpressionRef +} + +internal external interface SelectInfo : ExpressionInfo { + var ifTrue: ExpressionRef + var ifFalse: ExpressionRef + var condition: ExpressionRef +} + +internal external interface DropInfo : ExpressionInfo { + var value: ExpressionRef +} + +internal external interface ReturnInfo : ExpressionInfo { + var value: ExpressionRef +} + +internal external interface NopInfo : ExpressionInfo + +internal external interface UnreachableInfo : ExpressionInfo + +internal external interface HostInfo : ExpressionInfo { + var op: Operations + var nameOperand: String? + var operands: Array +} + +internal external interface AtomicRMWInfo : ExpressionInfo { + var op: Operations + var bytes: Number + var offset: Number + var ptr: ExpressionRef + var value: ExpressionRef +} + +internal external interface AtomicCmpxchgInfo : ExpressionInfo { + var bytes: Number + var offset: Number + var ptr: ExpressionRef + var expected: ExpressionRef + var replacement: ExpressionRef +} + +internal external interface AtomicWaitInfo : ExpressionInfo { + var ptr: ExpressionRef + var expected: ExpressionRef + var timeout: ExpressionRef + var expectedType: Type +} + +internal external interface AtomicNotifyInfo : ExpressionInfo { + var ptr: ExpressionRef + var notifyCount: ExpressionRef +} + +internal external interface AtomicFenceInfo : ExpressionInfo { + var order: Number +} + +internal external interface SIMDExtractInfo : ExpressionInfo { + var op: Operations + var vec: ExpressionRef + var index: ExpressionRef +} + +internal external interface SIMDReplaceInfo : ExpressionInfo { + var op: Operations + var vec: ExpressionRef + var index: ExpressionRef + var value: ExpressionRef +} + +internal external interface SIMDShuffleInfo : ExpressionInfo { + var left: ExpressionRef + var right: ExpressionRef + var mask: Array +} + +internal external interface SIMDTernaryInfo : ExpressionInfo { + var op: Operations + var a: ExpressionRef + var b: ExpressionRef + var c: ExpressionRef +} + +internal external interface SIMDShiftInfo : ExpressionInfo { + var op: Operations + var vec: ExpressionRef + var shift: ExpressionRef +} + +internal external interface SIMDLoadInfo : ExpressionInfo { + var op: Operations + var offset: Number + var align: Number + var ptr: ExpressionRef +} + +internal external interface MemoryInitInfo : ExpressionInfo { + var segment: Number + var dest: ExpressionRef + var offset: ExpressionRef + var size: ExpressionRef +} + +internal external interface MemoryDropInfo : ExpressionInfo { + var segment: Number +} + +internal external interface MemoryCopyInfo : ExpressionInfo { + var dest: ExpressionRef + var source: ExpressionRef + var size: ExpressionRef +} + +internal external interface MemoryFillInfo : ExpressionInfo { + var dest: ExpressionRef + var value: ExpressionRef + var size: ExpressionRef +} + +internal external interface RefNullInfo : ExpressionInfo + +internal external interface RefIsNullInfo : ExpressionInfo { + var value: ExpressionRef +} + +internal external interface RefFuncInfo : ExpressionInfo { + var func: String +} + +internal external interface TryInfo : ExpressionInfo { + var body: ExpressionRef + var catchBody: ExpressionRef +} + +internal external interface ThrowInfo : ExpressionInfo { + var event: String + var operands: Array +} + +internal external interface RethrowInfo : ExpressionInfo { + var exnref: ExpressionRef +} + +internal external interface BrOnExnInfo : ExpressionInfo { + var name: String + var event: String + var exnref: ExpressionRef +} + +internal external interface PopInfo : ExpressionInfo + +internal external interface PushInfo : ExpressionInfo { + var value: ExpressionRef +} + +internal external fun getFunctionInfo(func: FunctionRef): FunctionInfo + +internal external interface FunctionInfo { + var name: String + var module: String? + var base: String? + var params: Type + var results: Type + var vars: Array + var body: ExpressionRef +} + +internal external fun getGlobalInfo(global: GlobalRef): GlobalInfo + +internal external interface GlobalInfo { + var name: String + var module: String? + var base: String? + var type: Type + var mutable: Boolean + var init: ExpressionRef +} + +internal external fun getExportInfo(export_: ExportRef): ExportInfo + +internal external interface ExportInfo { + var kind: ExternalKinds + var name: String + var value: String +} + +internal external fun getEventInfo(event: EventRef): EventInfo + +internal external interface EventInfo { + var name: String + var module: String? + var base: String? + var attribute: Number + var params: Type + var results: Type +} + +internal external fun getSideEffects(expr: ExpressionRef, features: Features): SideEffects + +internal external enum class SideEffects { + None, + Branches, + Calls, + ReadsLocal, + WritesLocal, + ReadsGlobal, + WritesGlobal, + ReadsMemory, + WritesMemory, + ImplicitTrap, + IsAtomic, + Throws, + Any +} + +internal external fun emitText(expression: ExpressionRef): String + +internal external fun emitText(expression: Module): String + +internal external fun readBinary(data: Uint8Array): Module + +internal external fun parseText(text: String): Module + +internal external fun getOptimizeLevel(): Number + +internal external fun setOptimizeLevel(level: Number): Number + +internal external fun getShrinkLevel(): Number + +internal external fun setShrinkLevel(level: Number): Number + +internal external fun getDebugInfo(): Boolean + +internal external fun setDebugInfo(on: Boolean) + +internal external fun getLowMemoryUnused(): Boolean + +internal external fun setLowMemoryUnused(on: Boolean) + +internal external fun getPassArgument(key: String): String? + +internal external fun setPassArgument(key: String, value: String?) + +internal external fun clearPassArguments() + +internal external fun getAlwaysInlineMaxSize(): Number + +internal external fun setAlwaysInlineMaxSize(size: Number) + +internal external fun getFlexibleInlineMaxSize(): Number + +internal external fun setFlexibleInlineMaxSize(size: Number) + +internal external fun getOneCallerInlineMaxSize(): Number + +internal external fun setOneCallerInlineMaxSize(size: Number) + +internal external fun exit(status: Number) + +internal open external class Relooper(module: Module) { + open fun addBlock(expression: ExpressionRef): RelooperBlockRef + open fun addBranch(from: RelooperBlockRef, to: RelooperBlockRef, condition: ExpressionRef, code: ExpressionRef) + open fun addBlockWithSwitch(code: ExpressionRef, condition: ExpressionRef): RelooperBlockRef + open fun addBranchForSwitch( + from: RelooperBlockRef, + to: RelooperBlockRef, + indexes: Array, + code: ExpressionRef + ) + + open fun renderAndDispose(entry: RelooperBlockRef, labelHelper: Number): ExpressionRef +} diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt new file mode 100644 index 000000000..f89db20e2 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt @@ -0,0 +1,11 @@ +@file:Suppress("PackageDirectoryMismatch", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation") + +package space.kscience.kmath.internal.binaryen + +internal typealias Type = Number +internal typealias ExpressionRef = Number +internal typealias FunctionRef = Number +internal typealias GlobalRef = Number +internal typealias ExportRef = Number +internal typealias EventRef = Number +internal typealias RelooperBlockRef = Number diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/emitter/emitter.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt similarity index 91% rename from kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/emitter/emitter.kt rename to kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt index 7707f53a2..1f7b09af8 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/emitter/emitter.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt @@ -3,7 +3,7 @@ * 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.estree.internal.emitter +package space.kscience.kmath.internal.emitter internal open external class Emitter { constructor(obj: Any) diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.extensions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt similarity index 97% rename from kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.extensions.kt rename to kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt index 9ba11e085..3aa31f921 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.extensions.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt @@ -3,7 +3,7 @@ * 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.estree.internal.estree +package space.kscience.kmath.internal.estree internal fun Program(sourceType: String, vararg body: dynamic) = object : Program { override var type = "Program" diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt similarity index 99% rename from kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.kt rename to kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt index a0e42db5d..e5254013e 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt @@ -3,7 +3,7 @@ * 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.estree.internal.estree +package space.kscience.kmath.internal.estree import kotlin.js.RegExp diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt new file mode 100644 index 000000000..ae6c7eb35 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt @@ -0,0 +1,7 @@ +package space.kscience.kmath.internal.stream + +import space.kscience.kmath.internal.emitter.Emitter + +internal open external class Stream : Emitter { + open fun pipe(dest: Any, options: Any): Any +} diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt similarity index 94% rename from kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt rename to kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt index a3c721ed4..9c012e3a3 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt @@ -3,7 +3,7 @@ * 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.estree.internal.tsstdlib +package space.kscience.kmath.internal.tsstdlib internal external interface IteratorYieldResult { var done: Boolean? diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt similarity index 88% rename from kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt rename to kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt index d2413b3e3..0cd395f2c 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt @@ -5,7 +5,7 @@ @file:Suppress("UNUSED_TYPEALIAS_PARAMETER", "DEPRECATION") -package space.kscience.kmath.estree.internal.tsstdlib +package space.kscience.kmath.internal.tsstdlib import kotlin.js.RegExp @@ -38,6 +38,8 @@ internal external interface RegExpConstructor { var lastMatch: String } +internal typealias Record = Any + internal external interface ConcatArray { var length: Number @@ -85,3 +87,10 @@ internal external interface ArrayLike { } internal typealias Extract = Any + +internal external interface PromiseLike { + fun then( + onfulfilled: ((value: T) -> Any?)? = definedExternally, + onrejected: ((reason: Any) -> Any?)? = definedExternally + ): PromiseLike +} diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt new file mode 100644 index 000000000..322a2fa7b --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt @@ -0,0 +1,231 @@ +@file:JsQualifier("WebAssembly") + +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", + "OVERRIDING_FINAL_MEMBER", + "RETURN_TYPE_MISMATCH_ON_OVERRIDE", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", + "ClassName", +) + +package space.kscience.kmath.internal.webassembly + +import space.kscience.kmath.internal.tsstdlib.PromiseLike +import org.khronos.webgl.ArrayBuffer +import org.khronos.webgl.ArrayBufferView +import org.khronos.webgl.Uint8Array +import org.w3c.fetch.Response +import kotlin.js.Promise + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +internal external interface CompileError { + companion object { + var prototype: CompileError + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +internal external interface Global { + var value: Any + fun valueOf(): Any + + companion object { + var prototype: Global + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +@JsName("Instance") +internal external interface Instance1 { + var exports: Exports + + companion object { + var prototype: Instance + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +internal external interface LinkError { + companion object { + var prototype: LinkError + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +internal external interface Memory { + var buffer: ArrayBuffer + fun grow(delta: Number): Number + + companion object { + var prototype: Memory + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +@JsName("Module") +internal external interface Module1 { + companion object { + var prototype: Module + fun customSections(moduleObject: Module, sectionName: String): Array + fun exports(moduleObject: Module): Array + fun imports(moduleObject: Module): Array + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +internal external interface RuntimeError { + companion object { + var prototype: RuntimeError + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +internal external interface Table { + var length: Number + fun get(index: Number): Function<*>? + fun grow(delta: Number): Number + fun set(index: Number, value: Function<*>?) + + companion object { + var prototype: Table + } +} + +internal external interface GlobalDescriptor { + var mutable: Boolean? + get() = definedExternally + set(value) = definedExternally + var value: String /* "f32" | "f64" | "i32" | "i64" */ +} + +internal external interface MemoryDescriptor { + var initial: Number + var maximum: Number? + get() = definedExternally + set(value) = definedExternally +} + +internal external interface ModuleExportDescriptor { + var kind: String /* "function" | "global" | "memory" | "table" */ + var name: String +} + +internal external interface ModuleImportDescriptor { + var kind: String /* "function" | "global" | "memory" | "table" */ + var module: String + var name: String +} + +internal external interface TableDescriptor { + var element: String /* "anyfunc" */ + var initial: Number + var maximum: Number? + get() = definedExternally + set(value) = definedExternally +} + +internal external interface WebAssemblyInstantiatedSource { + var instance: Instance + var module: Module +} + +internal external fun compile(bytes: ArrayBufferView): Promise + +internal external fun compile(bytes: ArrayBuffer): Promise + +internal external fun compileStreaming(source: Response): Promise + +internal external fun compileStreaming(source: Promise): Promise + +internal external fun instantiate( + bytes: ArrayBufferView, + importObject: Imports = definedExternally, +): Promise + +internal external fun instantiate(bytes: ArrayBufferView): Promise + +internal external fun instantiate( + bytes: ArrayBuffer, + importObject: Imports = definedExternally, +): dynamic /* Promise | Promise */ + +internal external fun instantiate(bytes: ArrayBuffer): dynamic /* Promise | Promise */ + +internal external fun instantiate(moduleObject: Module, importObject: Imports = definedExternally): Promise + +internal external fun instantiate(moduleObject: Module): Promise + +internal external fun instantiateStreaming( + response: Response, + importObject: Imports = definedExternally, +): Promise + +internal external fun instantiateStreaming(response: Response): Promise + +internal external fun instantiateStreaming( + response: PromiseLike, + importObject: Imports = definedExternally, +): Promise + +internal external fun instantiateStreaming(response: PromiseLike): Promise + +internal external fun validate(bytes: ArrayBufferView): Boolean + +internal external fun validate(bytes: ArrayBuffer): Boolean + +internal external interface `T$0` { + var name: String + var kind: String +} + +internal external interface `T$1` { + var module: String + var name: String + var kind: String +} + +internal open external class Module { + constructor(bufferSource: ArrayBuffer) + constructor(bufferSource: Uint8Array) + + companion object { + fun customSections(module: Module, sectionName: String): Array + fun exports(module: Module): Array<`T$0`> + fun imports(module: Module): Array<`T$1`> + } +} + +@JsName("Instance") +internal open external class Instance(module: Module, importObject: Any = definedExternally) { + open var exports: Any +} + +@JsName("Memory") +internal open external class Memory1(memoryDescriptor: MemoryDescriptor) { + open var buffer: ArrayBuffer + open fun grow(numPages: Number): Number +} + +@JsName("Table") +internal open external class Table1(tableDescriptor: TableDescriptor) { + open var length: Number + open fun get(index: Number): Function<*> + open fun grow(numElements: Number): Number + open fun set(index: Number, value: Function<*>) +} + +internal external fun compile(bufferSource: Uint8Array): Promise + +internal external interface ResultObject { + var module: Module + var instance: Instance +} + +internal external fun instantiate( + bufferSource: Uint8Array, + importObject: Any = definedExternally, +): Promise + +internal external fun instantiate(bufferSource: Uint8Array): Promise + +internal external fun validate(bufferSource: Uint8Array): Boolean diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt new file mode 100644 index 000000000..095e46140 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt @@ -0,0 +1,22 @@ +@file:Suppress("INTERFACE_WITH_SUPERCLASS", + "OVERRIDING_FINAL_MEMBER", + "RETURN_TYPE_MISMATCH_ON_OVERRIDE", + "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", +) + +package space.kscience.kmath.internal.webassembly + +import space.kscience.kmath.internal.tsstdlib.Record + +internal typealias Exports = Record | Global | Memory | Table */> + +internal typealias ModuleImports = Record | Global | Memory | Table | Number */> + +internal typealias Imports = Record + +internal typealias CompileError1 = Error + +internal typealias LinkError1 = Error + +internal typealias RuntimeError1 = Error diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt new file mode 100644 index 000000000..a031a4de4 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -0,0 +1,155 @@ +package space.kscience.kmath.wasm.internal + +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.MST.* +import space.kscience.kmath.internal.binaryen.* +import space.kscience.kmath.internal.webassembly.Instance +import space.kscience.kmath.misc.StringSymbol +import space.kscience.kmath.operations.* +import space.kscience.kmath.internal.binaryen.Module as BinaryenModule +import space.kscience.kmath.internal.webassembly.Module as WasmModule + +private val spreader = eval("(obj, args) => obj(...args)") + +@Suppress("UnsafeCastFromDynamic") +internal sealed class WasmBuilder( + val binaryenType: Type, + val algebra: Algebra, + val target: MST, +) where T : Number { + val keys: MutableList = mutableListOf() + lateinit var ctx: BinaryenModule + + open fun visitSymbolic(mst: MST.Symbolic): ExpressionRef { + try { + algebra.bindSymbol(mst.value) + } catch (ignored: Throwable) { + null + }?.let { return visitNumeric(Numeric(it)) } + + var idx = keys.indexOf(mst.value) + + if (idx == -1) { + keys += mst.value + idx = keys.lastIndex + } + + return ctx.local.get(idx, binaryenType) + } + + abstract fun visitNumeric(mst: Numeric): ExpressionRef + + open fun visitUnary(mst: Unary): ExpressionRef = + error("Unary operation ${mst.operation} not defined in $this") + + open fun visitBinary(mst: Binary): ExpressionRef = + error("Binary operation ${mst.operation} not defined in $this") + + open fun createModule(): BinaryenModule = js("new \$module\$binaryen.Module()") + + fun visit(mst: MST): ExpressionRef = when (mst) { + is Symbolic -> visitSymbolic(mst) + is Numeric -> visitNumeric(mst) + + is Unary -> when { + algebra is NumericAlgebra && mst.value is Numeric -> visitNumeric( + Numeric(algebra.unaryOperationFunction(mst.operation)(algebra.number((mst.value as Numeric).value)))) + + else -> visitUnary(mst) + } + + is Binary -> when { + algebra is NumericAlgebra && mst.left is Numeric && mst.right is Numeric -> visitNumeric(Numeric( + algebra.binaryOperationFunction(mst.operation) + .invoke(algebra.number((mst.left as Numeric).value), algebra.number((mst.right as Numeric).value)) + )) + + else -> visitBinary(mst) + } + } + + val instance by lazy { + val c = WasmModule(with(createModule()) { + ctx = this + val expr = visit(target) + + addFunction( + "executable", + createType(Array(keys.size) { binaryenType }), + binaryenType, + arrayOf(), + expr + ) + + setOptimizeLevel(3) + optimizeFunction("executable") + addFunctionExport("executable", "executable") + val res = emitBinary() + dispose() + res + }) + + val i = Instance(c, js("{}") as Any) + val symbols = keys.map(::StringSymbol) + keys.clear() + + Expression { args -> + val params = symbols.map(args::getValue).toTypedArray() + spreader(i.exports.asDynamic().executable, params) as T + } + } +} + +internal class DoubleWasmBuilder(target: MST) : WasmBuilder(f64, DoubleField, target) { + override fun createModule(): BinaryenModule = readBinary(f64StandardFunctions) + + override fun visitNumeric(mst: Numeric): ExpressionRef = ctx.f64.const(mst.value) + + override fun visitUnary(mst: Unary): ExpressionRef = when (mst.operation) { + GroupOperations.MINUS_OPERATION -> ctx.f64.neg(visit(mst.value)) + GroupOperations.PLUS_OPERATION -> visit(mst.value) + PowerOperations.SQRT_OPERATION -> ctx.f64.sqrt(visit(mst.value)) + TrigonometricOperations.SIN_OPERATION -> ctx.call("sin", arrayOf(visit(mst.value)), f64) + TrigonometricOperations.COS_OPERATION -> ctx.call("cos", arrayOf(visit(mst.value)), f64) + TrigonometricOperations.TAN_OPERATION -> ctx.call("tan", arrayOf(visit(mst.value)), f64) + TrigonometricOperations.ASIN_OPERATION -> ctx.call("asin", arrayOf(visit(mst.value)), f64) + TrigonometricOperations.ACOS_OPERATION -> ctx.call("acos", arrayOf(visit(mst.value)), f64) + TrigonometricOperations.ATAN_OPERATION -> ctx.call("atan", arrayOf(visit(mst.value)), f64) + ExponentialOperations.SINH_OPERATION -> ctx.call("sinh", arrayOf(visit(mst.value)), f64) + ExponentialOperations.COSH_OPERATION -> ctx.call("cosh", arrayOf(visit(mst.value)), f64) + ExponentialOperations.TANH_OPERATION -> ctx.call("tanh", arrayOf(visit(mst.value)), f64) + ExponentialOperations.ASINH_OPERATION -> ctx.call("asinh", arrayOf(visit(mst.value)), f64) + ExponentialOperations.ACOSH_OPERATION -> ctx.call("acosh", arrayOf(visit(mst.value)), f64) + ExponentialOperations.ATANH_OPERATION -> ctx.call("atanh", arrayOf(visit(mst.value)), f64) + ExponentialOperations.EXP_OPERATION -> ctx.call("exp", arrayOf(visit(mst.value)), f64) + ExponentialOperations.LN_OPERATION -> ctx.call("log", arrayOf(visit(mst.value)), f64) + else -> super.visitUnary(mst) + } + + override fun visitBinary(mst: Binary): ExpressionRef = when (mst.operation) { + GroupOperations.PLUS_OPERATION -> ctx.f64.add(visit(mst.left), visit(mst.right)) + GroupOperations.MINUS_OPERATION -> ctx.f64.sub(visit(mst.left), visit(mst.right)) + RingOperations.TIMES_OPERATION -> ctx.f64.mul(visit(mst.left), visit(mst.right)) + FieldOperations.DIV_OPERATION -> ctx.f64.div(visit(mst.left), visit(mst.right)) + PowerOperations.POW_OPERATION -> ctx.call("pow", arrayOf(visit(mst.left), visit(mst.right)), f64) + else -> super.visitBinary(mst) + } +} + +internal class IntWasmBuilder(target: MST) : WasmBuilder(i32, IntRing, target) { + override fun visitNumeric(mst: Numeric): ExpressionRef = ctx.i32.const(mst.value) + + override fun visitUnary(mst: Unary): ExpressionRef = when (mst.operation) { + GroupOperations.MINUS_OPERATION -> ctx.i32.sub(ctx.i32.const(0), visit(mst.value)) + GroupOperations.PLUS_OPERATION -> visit(mst.value) + else -> super.visitUnary(mst) + } + + override fun visitBinary(mst: Binary): ExpressionRef = when (mst.operation) { + GroupOperations.PLUS_OPERATION -> ctx.i32.add(visit(mst.left), visit(mst.right)) + GroupOperations.MINUS_OPERATION -> ctx.i32.sub(visit(mst.left), visit(mst.right)) + RingOperations.TIMES_OPERATION -> ctx.i32.mul(visit(mst.left), visit(mst.right)) + else -> super.visitBinary(mst) + } +} diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt new file mode 100644 index 000000000..cb0d71ad5 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt @@ -0,0 +1,8 @@ +package space.kscience.kmath.wasm.internal + +import space.kscience.kmath.internal.base64.toUint8Array + +internal val f64StandardFunctions by lazy { toUint8Array(B) } + +private const val B = + "AGFzbQEAAAABMghgAABgAXwBfGACfHwBfGAFf39/f38Bf2ACfH8Bf2ADfHx/AXxgAnx/AXxgA39/fwF/AxsaAAEBAQEBAQIDBAUBAQEBAQEBAgYBAQUBAQcEBQFwAQEBBQMBAAIGFQN/AUGgnwQLfwBBoJ8EC38AQaAfCwclAwZtZW1vcnkCAAtfX2hlYXBfYmFzZQMBCl9fZGF0YV9lbmQDAgrpaxoCAAvPBQMBfgF/AnwCQAJAAkAgAL0iAUIgiKdB/////wdxIgJBgIDA/wNJDQAgAkGAgMCAfGogAadyRQ0BRAAAAAAAAAAAIAAgAKGjDwsCQAJAIAJB/////gNLDQBEGC1EVPsh+T8hAyACQYGAgOMDSQ0BRAdcFDMmppE8IAAgAKIiAyADIAMgAyADIANECff9DeE9Aj+iRIiyAXXg70k/oKJEO49otSiCpL+gokRVRIgOVcHJP6CiRH1v6wMS1tS/oKJEVVVVVVVVxT+goiADIAMgAyADRIKSLrHFuLM/okRZAY0bbAbmv6CiRMiKWZzlKgBAoKJESy2KHCc6A8CgokQAAAAAAADwP6CjIACioSAAoUQYLURU+yH5P6APCyABQn9XDQJEAAAAAAAA8D8gAKFEAAAAAAAA4D+iIgAgAJ8iBL1CgICAgHCDvyIDIAOioSAEIAOgoyAEIAAgACAAIAAgACAARAn3/Q3hPQI/okSIsgF14O9JP6CiRDuPaLUogqS/oKJEVUSIDlXByT+gokR9b+sDEtbUv6CiRFVVVVVVVcU/oKIgACAAIAAgAESCki6xxbizP6JEWQGNG2wG5r+gokTIilmc5SoAQKCiREstihwnOgPAoKJEAAAAAAAA8D+go6KgIAOgIgAgAKAhAwsgAw8LRBgtRFT7IQlARAAAAAAAAAAAIAFCAFMbDwtEGC1EVPsh+T8gAEQAAAAAAADwP6BEAAAAAAAA4D+iIgCfIgMgAyAAIAAgACAAIAAgAEQJ9/0N4T0CP6JEiLIBdeDvST+gokQ7j2i1KIKkv6CiRFVEiA5Vwck/oKJEfW/rAxLW1L+gokRVVVVVVVXFP6CiIAAgACAAIABEgpIuscW4sz+iRFkBjRtsBua/oKJEyIpZnOUqAECgokRLLYocJzoDwKCiRAAAAAAAAPA/oKOiRAdcFDMmppG8oKChIgAgAKALdwEBfwJAIAC9QjSIp0H/D3EiAUH/B0sNACAARAAAAAAAAPC/oCIAIAAgAKIgACAAoKCfoBARDwsCQCABQZgISw0AIAAgAKBEAAAAAAAA8L8gACAAokQAAAAAAADwv6CfIACgo6AQEA8LIAAQEETvOfr+Qi7mP6AL0gQDAX4BfwN8AkACQAJAAkACQCAAvSIBQiCIp0H/////B3EiAkGAgMD/A0kNACACQYCAwIB8aiABp3JFDQFEAAAAAAAAAAAgACAAoaMPCwJAIAJB/////gNLDQAgAkGAgEBqQYCAgPIDTw0CIAAPC0QAAAAAAADwPyAAmaFEAAAAAAAA4D+iIgAgACAAIAAgACAARAn3/Q3hPQI/okSIsgF14O9JP6CiRDuPaLUogqS/oKJEVUSIDlXByT+gokR9b+sDEtbUv6CiRFVVVVVVVcU/oKIgACAAIAAgAESCki6xxbizP6JEWQGNG2wG5r+gokTIilmc5SoAQKCiREstihwnOgPAoKJEAAAAAAAA8D+goyEDIACfIQQgAkGz5rz/A0kNAkQYLURU+yH5PyAEIAQgA6KgIgAgAKBEB1wUMyamkbygoSEADAMLIABEGC1EVPsh+T+iRAAAAAAAAHA4oA8LIAAgAKIiBCAEIAQgBCAEIARECff9DeE9Aj+iRIiyAXXg70k/oKJEO49otSiCpL+gokRVRIgOVcHJP6CiRH1v6wMS1tS/oKJEVVVVVVVVxT+goiAEIAQgBCAERIKSLrHFuLM/okRZAY0bbAbmv6CiRMiKWZzlKgBAoKJESy2KHCc6A8CgokQAAAAAAADwP6CjIACiIACgDwtEGC1EVPsh6T8gBL1CgICAgHCDvyIFIAWgoSAEIASgIAOiRAdcFDMmppE8IAAgBSAFoqEgBCAFoKMiACAAoKGhoUQYLURU+yHpP6AhAAsgAJogACABQgBTGwvbAQQBfwF+AX8BfCMAQRBrIgEkACAAvSICQv///////////wCDvyEAAkACQCACQjSIp0H/D3EiA0GZCEkNACAAEBBE7zn6/kIu5j+gIQAMAQsCQCADQYAISQ0AIAAgAKBEAAAAAAAA8D8gACAAokQAAAAAAADwP6CfIACgo6AQECEADAELAkAgA0HlB0kNACAAIACiIgQgBEQAAAAAAADwP6CfRAAAAAAAAPA/oKMgAKAQESEADAELIAEgAEQAAAAAAABwR6A5AwgLIAFBEGokACAAmiAAIAJCAFMbC6gEBAF/AX4DfwJ8IwBBEGshASAAvSICQj+IpyEDAkACQAJAIAJCIIinQf////8HcSIEQYCAwKAESQ0AIAJC////////////AINCgICAgICAgPj/AFYNAUQYLURU+yH5v0QYLURU+yH5PyADGw8LAkACQCAEQf//7/4DSw0AQX8hBSAEQf////EDSw0BIARB//8/Sw0CIAEgALY4AgwgAA8LIACZIQACQAJAAkAgBEH//8v/A0sNACAEQf//l/8DSw0BIAAgAKBEAAAAAAAA8L+gIABEAAAAAAAAAECgoyEAQQAhBQwDCyAEQf//jYAESw0BIABEAAAAAAAA+L+gIABEAAAAAAAA+D+iRAAAAAAAAPA/oKMhAEECIQUMAgsgAEQAAAAAAADwv6AgAEQAAAAAAADwP6CjIQBBASEFDAELRAAAAAAAAPC/IACjIQBBAyEFCyAAIAAgAKIiBiAGoiIHIAcgByAHIAdEL2xqLES0or+iRJr93lIt3q2/oKJEbZp0r/Kws7+gokRxFiP+xnG8v6CiRMTrmJmZmcm/oKIgBiAHIAcgByAHIAdEEdoi4zqtkD+iROsNdiRLe6k/oKJEUT3QoGYNsT+gokRuIEzFzUW3P6CiRP+DAJIkScI/oKJEDVVVVVVV1T+goqCiIQcgBUF/TA0BIAVBA3QiBEGACGorAwAgByAEQaAIaisDAKEgAKGhIgCaIAAgAxshAAsgAA8LIAAgB6ELtgEEAX8BfgF/AXwjAEEQayIBJAAgAL0iAkL///////////8Ag78hAAJAAkACQCACQjSIp0H/D3EiA0H9B0sNACADQd4HSw0BIAMNAiABIAC2OAIMDAILIABEAAAAAAAA8D8gAKGjIgAgAKAQEUQAAAAAAADgP6IhAAwBCyAAIACgIgQgBCAAokQAAAAAAADwPyAAoaOgEBFEAAAAAAAA4D+iIQALIAFBEGokACAAmiAAIAJCAFMbC5IBAQN8RAAAAAAAAPA/IAAgAKIiAkQAAAAAAADgP6IiA6EiBEQAAAAAAADwPyAEoSADoSACIAIgAiACRJAVyxmgAfo+okR3UcEWbMFWv6CiRExVVVVVVaU/oKIgAiACoiIDIAOiIAIgAkTUOIi+6fqovaJExLG0vZ7uIT6gokStUpyAT36SvqCioKIgACABoqGgoAuEFgYHfwF8Cn8BfAN/AnwjAEGwBGsiBSQAIAIgAkF9akEYbSIGQQAgBkEAShsiB0FobGohCAJAIARBAnRBwAhqKAIAIgkgA0F/aiICakEASA0AIAkgA2ohCiAHIAJrIQIgB0EBaiADa0ECdEHQCGohCyAFQcACaiEGA0ACQAJAIAJBAEgNACALKAIAtyEMDAELRAAAAAAAAAAAIQwLIAYgDDkDACAGQQhqIQYgC0EEaiELIAJBAWohAiAKQX9qIgoNAAsLIAhBaGohDQJAAkAgA0EBSA0AIAVBwAJqIANBA3RqQXhqIQ5BACEKA0BEAAAAAAAAAAAhDCAAIQIgAyELIA4hBgNAIAwgAisDACAGKwMAoqAhDCACQQhqIQIgBkF4aiEGIAtBf2oiCw0ACyAFIApBA3RqIAw5AwAgDkEIaiEOIAogCUghAiAKQQFqIQogAg0ADAILCyAFQQAgCUEAIAlBAEobQQN0QQhqEBkaC0EXIA1rIQ9BGCANayEQIAVB4ANqIAlBAnRqQXxqIREgBUHgA2pBfGohEiAFQXhqIRMgBUEIciEUIAkhBgN/IAUgBkEDdCIVaisDACEMAkAgBkEBSCIWDQAgEyAVaiECIAVB4ANqIQsgBiEKA0ACQAJAIAxEAAAAAAAAcD6iIheZRAAAAAAAAOBBYw0AQYCAgIB4IQ4MAQsgF6ohDgsCQAJAIAwgDrciF0QAAAAAAABwwaKgIgyZRAAAAAAAAOBBYw0AQYCAgIB4IQ4MAQsgDKohDgsgCyAONgIAIAtBBGohCyACKwMAIBegIQwgAkF4aiECIApBf2oiCg0ACwsCQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAMIA0QEyIMIAxEAAAAAAAAwD+inEQAAAAAAAAgwKKgIgyZRAAAAAAAAOBBYw0AQYCAgIB4IRggDEGAgICAeLehIQwgDUEBSCIZRQ0BDAILIAwgDKoiGLehIQwgDUEBSCIZDQELIAVB4ANqIAZBAnRqQXxqIgIgAigCACICIAIgEHUiAiAQdGsiCzYCACACIBhqIRggCyAPdSIaQQFIDQIMAQsCQCANRQ0AQQIhGiAMRAAAAAAAAOA/ZkEBc0UNAUEAIRogDEQAAAAAAAAAAGENAwwECyAFQeADaiAGQQJ0akF8aigCAEEXdSIaQQFIDQELAkACQCAWDQBBACEWIAVB4ANqIQIgBiEOA0AgAigCACELQf///wchCgJAAkAgFg0AIAtFDQFBASEWQYCAgAghCgsgAiAKIAtrNgIAIAJBBGohAiAOQX9qIg4NAQwDC0EAIRYgAkEEaiECIA5Bf2oiDg0ADAILC0EAIRYLAkACQAJAIBkNACANQQJGDQEgDUEBRw0AIAVB4ANqIAZBAnRqQXxqIgIgAigCAEH///8DcTYCAAsgGEEBaiEYIBpBAkcNAgwBCyAFQeADaiAGQQJ0akF8aiICIAIoAgBB////AXE2AgAgGEEBaiEYIBpBAkcNAQtEAAAAAAAA8D8gDKEhDEECIRogFkUNACAMRAAAAAAAAPA/IA0QE6EiDEQAAAAAAAAAAGENAQwCCyAMRAAAAAAAAAAAYg0BCwJAIAYgCUwNACASIAZBAnRqIQJBACELIAYhCgNAIAIoAgAgC3IhCyACQXxqIQIgCkF/aiIKIAlKDQALIAsNAgsgESECIAYhDgNAIA5BAWohDiACKAIAIQsgAkF8aiECIAtFDQALIAZBAWohAgJAIANBAUgNACAFQcACaiADIAZqQQN0aiEWA0AgBUHAAmogBiADakEDdGogAiIKIAdqQQJ0QdAIaigCALc5AwBEAAAAAAAAAAAhDCAAIQIgFiEGIAMhCwNAIAwgAisDACAGKwMAoqAhDCACQQhqIQIgBkF4aiEGIAtBf2oiCw0ACyAFIApBA3RqIAw5AwAgFkEIaiEWIApBAWohAiAKIQYgCiAOSA0ADAsLCyAUIBVqQQAgDiACIA4gAkobIAZrQQN0EBkaIAcgBmpBAnRB1AhqIQIgBUHAAmogAyAGakEDdGohCwNAIAsgAigCALc5AwAgAkEEaiECIAtBCGohCyAGQQFqIgYgDkgNAAsgDiEGDAoLAkAgDEEAIA1rEBMiDEQAAAAAAABwQWZBAXNFDQAgDJlEAAAAAAAA4EFjDQJBgICAgHghAgwDCyAGQQJ0IQsgDEQAAAAAAABwPqIiF5lEAAAAAAAA4EFjDQNBgICAgHghAgwECyAFQeADaiAGQQJ0akF8aiECIA0hCANAIAZBf2ohBiAIQWhqIQggAigCACELIAJBfGohAiALRQ0AC0EAIQ4gBkEATg0FDAYLIAyqIQILIA0hCAwCCyAXqiECCyAFQeADaiALaiELAkACQCAMIAK3RAAAAAAAAHDBoqAiDJlEAAAAAAAA4EFjDQBBgICAgHghCgwBCyAMqiEKCyALIAo2AgAgBkEBaiEGCyAFQeADaiAGQQJ0aiACNgIAQQAhDiAGQQBIDQELIAZBAWohCkQAAAAAAADwPyAIEBMhDCAFQeADaiAGQQJ0aiECIAUgBkEDdGohCwNAIAsgDCACKAIAt6I5AwAgAkF8aiECIAtBeGohCyAMRAAAAAAAAHA+oiEMIApBf2oiCiAOSg0ACyAGQQBIDQAgBSAGQQN0aiEOIAYhAgNAIAYgAiIDayEWRAAAAAAAAAAAIQxBACECQQAhCwJAA0AgDCACQaAeaisDACAOIAJqKwMAoqAhDCALIAlODQEgAkEIaiECIAsgFkkhCiALQQFqIQsgCg0ACwsgBUGgAWogFkEDdGogDDkDACAOQXhqIQ4gA0F/aiECIANBAEoNAAsLAkACQAJAAkACQAJAAkACQCAEQX9qQQJJDQAgBEUNASAEQQNHDQdEAAAAAAAAAAAhGwJAIAZBAUgNACAFQaABaiAGQQN0aiILQXhqIQIgCysDACEMIAYhCwNAIAIgAisDACIcIAygIhc5AwAgAkEIaiAMIBwgF6GgOQMAIAJBeGohAiAXIQwgC0F/aiILQQBKDQALIAZBAkgNACAFQaABaiAGQQN0aiILQXhqIQIgCysDACEMIAYhCwNAIAIgAisDACIcIAygIhc5AwAgAkEIaiAMIBwgF6GgOQMAIAJBeGohAiAXIQwgC0F/aiILQQFKDQALIAZBAkgNACAFQaABaiAGQQN0aiECRAAAAAAAAAAAIRsDQCAbIAIrAwCgIRsgAkF4aiECIAZBf2oiBkEBSg0ACwsgBSsDoAEhDCAaRQ0EIAEgDJo5AwAgASAFKwOoAZo5AwggASAbmjkDEAwHCyAGQQBIDQEgBkEBaiELIAVBoAFqIAZBA3RqIQJEAAAAAAAAAAAhDANAIAwgAisDAKAhDCACQXhqIQIgC0F/aiILQQBKDQAMAwsLIAZBAEgNAyAGQQFqIQsgBUGgAWogBkEDdGohAkQAAAAAAAAAACEMA0AgDCACKwMAoCEMIAJBeGohAiALQX9qIgtBAEoNAAwFCwtEAAAAAAAAAAAhDAsgASAMmiAMIBobOQMAIAUrA6ABIAyhIQwCQCAGQQFIDQAgBUGgAWpBCHIhAgNAIAwgAisDAKAhDCACQQhqIQIgBkF/aiIGDQALCyABIAyaIAwgGhs5AwgMAwsgASAMOQMAIAEgBSkDqAE3AwggASAbOQMQDAILRAAAAAAAAAAAIQwLIAEgDJogDCAaGzkDAAsgBUGwBGokACAYQQdxDwsgDiEGDAALC8MKBgF/AX4DfwN8AX8BfCMAQTBrIgIkACAAvSIDQj+IpyEEAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCADQiCIpyIFQf////8HcSIGQfrUvYAESw0AIAVB//8/cUH7wyRGDQMgBkH8souABEsNASAERQ0GIAEgAEQAAEBU+yH5P6AiAEQxY2IaYbTQPaAiBzkDACABIAAgB6FEMWNiGmG00D2gOQMIIAJBMGokAEF/DwsCQCAGQbuM8YAESw0AIAZBvPvXgARLDQIgBkH8ssuABEYNAyAERQ0KIAEgAEQAADB/fNkSQKAiAETKlJOnkQ7pPaAiBzkDACABIAAgB6FEypSTp5EO6T2gOQMIIAJBMGokAEF9DwsgBkH6w+SJBE0NAiAGQYCAwP8HSQ0DIAEgACAAoSIAOQMAIAEgADkDCCACQTBqJABBAA8LIARFDQUgASAARAAAQFT7IQlAoCIARDFjYhphtOA9oCIHOQMAIAEgACAHoUQxY2IaYbTgPaA5AwggAkEwaiQAQX4PCyAGQfvD5IAERw0CCyABIAAgAESDyMltMF/kP6JEAAAAAAAAOEOgRAAAAAAAADjDoCIHRAAAQFT7Ifm/oqAiCCAHRDFjYhphtNA9oiIJoSIAOQMAIAZBFHYiCiAAvUI0iKdB/w9xa0ERSCEFAkACQAJAIAeZRAAAAAAAAOBBYw0AQYCAgIB4IQYgBUUNAQwCCyAHqiEGIAUNAQsgASAIIAdEAABgGmG00D2iIgChIgsgB0RzcAMuihmjO6IgCCALoSAAoaEiCaEiADkDAAJAIAogAL1CNIinQf8PcWtBMkgNACABIAsgB0QAAAAuihmjO6IiAKEiCCAHRMFJICWag3s5oiALIAihIAChoSIJoSIAOQMADAELIAshCAsgASAIIAChIAmhOQMIIAJBMGokACAGDwsgA0L/////////B4NCgICAgICAgLDBAIS/IgCZRAAAAAAAAOBBYw0DQYCAgIB4IQUMBAsgBEUNBSABIABEAABAVPshGUCgIgBEMWNiGmG08D2gIgc5AwAgASAAIAehRDFjYhphtPA9oDkDCCACQTBqJABBfA8LIAEgAEQAAEBU+yH5v6AiAEQxY2IaYbTQvaAiBzkDACABIAAgB6FEMWNiGmG00L2gOQMIIAJBMGokAEEBDwsgASAARAAAQFT7IQnAoCIARDFjYhphtOC9oCIHOQMAIAEgACAHoUQxY2IaYbTgvaA5AwggAkEwaiQAQQIPCyAAqiEFCyACIAW3Igc5AxACQAJAIAAgB6FEAAAAAAAAcEGiIgCZRAAAAAAAAOBBYw0AQYCAgIB4IQUMAQsgAKohBQsgAiAFtyIHOQMYIAIgACAHoUQAAAAAAABwQaIiADkDICAARAAAAAAAAAAAYg0CIAJBEGpBCHIhBUECIQoDQCAKQX9qIQogBSsDACEAIAVBeGohBSAARAAAAAAAAAAAYQ0ADAQLCyABIABEAAAwf3zZEsCgIgBEypSTp5EO6b2gIgc5AwAgASAAIAehRMqUk6eRDum9oDkDCCACQTBqJABBAw8LIAEgAEQAAEBU+yEZwKAiAEQxY2IaYbTwvaAiBzkDACABIAAgB6FEMWNiGmG08L2gOQMIIAJBMGokAEEEDwtBAiEKCyACQRBqIAIgBkEUdkHqd2ogCkEBakEBEAghBSACKwMAIQACQCAERQ0AIAEgAJo5AwAgASACKwMImjkDCCACQTBqJABBACAFaw8LIAEgADkDACABIAIpAwg3AwggAkEwaiQAIAULmwEBA3wgACAAoiIDIAMgA6KiIANEfNXPWjrZ5T2iROucK4rm5Vq+oKIgAyADRH3+sVfjHcc+okTVYcEZoAEqv6CiRKb4EBEREYE/oKAhBCADIACiIQUCQCACRQ0AIAAgBURJVVVVVVXFP6IgAyABRAAAAAAAAOA/oiAFIASioaIgAaGgoQ8LIAUgAyAEokRJVVVVVVXFv6CiIACgC5ICAgJ/AXwjAEEQayIBJAACQAJAAkAgAL1CIIinQf////8HcSICQfvDpP8DSw0AIAJBncGa8gNLDQEgASAARAAAAAAAAHBHoDkDACABQRBqJABEAAAAAAAA8D8PCyACQYCAwP8HSQ0BIAFBEGokACAAIAChDwsgAEQAAAAAAAAAABAHIQAgAUEQaiQAIAAPCyAAIAEQCSECIAErAwghACABKwMAIQMCQAJAAkAgAkEDcSICQQJGDQAgAkEBRg0BIAINAiADIAAQByEAIAFBEGokACAADwsgAyAAEAchACABQRBqJAAgAJoPCyADIABBARAKIQAgAUEQaiQAIACaDwsgAyAAQQEQCiEAIAFBEGokACAACyQAIABEi90aFWYglsCgEA5EAAAAAAAAwH+iRAAAAAAAAMB/ogvaAQMBfwF+AX8jAEEQayIBJAAgAL1C////////////AIMiAr8hAAJAAkACQCACQiCIpyIDQcHcmP8DSw0AIANB//+/8gNLDQEgASAARAAAAAAAAHBHoDkDCCABQRBqJABEAAAAAAAA8D8PCyADQcHcmIQESw0BIAAQDiEAIAFBEGokACAARAAAAAAAAPA/IACjoEQAAAAAAADgP6IPCyABQRBqJAAgABAPIgAgAKIgAEQAAAAAAADwP6AiACAAoKNEAAAAAAAA8D+gDwsgABAMIQAgAUEQaiQAIAALoAQEAX8BfgJ/A3wjAEEQayIBJAAgAL0iAkI/iKchAwJAAkACQAJAAkACQAJAAkACQAJAIAJCIIinQf////8HcSIEQavGmIQESQ0AIAJC////////////AINCgICAgICAgPj/AFgNASABQRBqJAAgAA8LIARBw9zY/gNJDQEgBEGyxcL/A08NAyADQQFzIANrIQQMBgsgAETvOfr+Qi6GQGRBAXMNASABQRBqJAAgAEQAAAAAAADgf6IPCyAEQYCAwPEDTQ0CQQAhBEQAAAAAAAAAACEFIAAhBgwFCyAARNK8et0rI4bAY0EBcw0AIAFEAAAAAAAAoLYgAKO2OAIMRAAAAAAAAAAAIQcgAERRMC3VEEmHwGMNBQsgAET+gitlRxX3P6IgA0EDdEHgHmorAwCgIgeZRAAAAAAAAOBBYw0BQYCAgIB4IQQMAgsgASAARAAAAAAAAOB/oDkDACABQRBqJAAgAEQAAAAAAADwP6APCyAHqiEECyAAIAS3IgdEAADg/kIu5r+ioCIAIAdEdjx5Ne856j2iIgWhIQYLIAAgBiAGIAYgBqIiByAHIAcgByAHRNCkvnJpN2Y+okTxa9LFQb27vqCiRCzeJa9qVhE/oKJEk72+FmzBZr+gokQ+VVVVVVXFP6CioSIHokQAAAAAAAAAQCAHoaMgBaGgRAAAAAAAAPA/oCEHIARFDQAgByAEEBMhBwsgAUEQaiQAIAcL2QYEAX8BfgJ/BHwjAEEQayEBIAC9IgJCP4inIQMCQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCACQiCIp0H/////B3EiBEH60I2CBEkNACACQv///////////wCDQoCAgICAgID4/wBYDQEgAA8LIARBw9zY/gNJDQEgBEGxxcL/A0sNAiADRQ0GIABEAADg/kIu5j+gIQVBfyEERHY8eTXvOeq9IQYMCgsgA0UNA0QAAAAAAADwvw8LIARB//+/5ANLDQEgBEH//z9LDQMgASAAtjgCDCAADwsgAET+gitlRxX3P6IhBkQAAAAAAADgvyEFIAMNBgwFC0EAIQQMBwsgAETvOfr+Qi6GQGRFDQIgAEQAAAAAAADgf6IPCyAADwsgAEQAAOD+Qi7mv6AhBUEBIQREdjx5Ne856j0hBgwDCyAARP6CK2VHFfc/oiEGC0QAAAAAAADgPyEFCwJAAkAgBiAFoCIFmUQAAAAAAADgQWMNAEGAgICAeCEEDAELIAWqIQQLIAS3IgVEdjx5Ne856j2iIQYgACAFRAAA4P5CLua/oqAhBQsgBSAFIAahIgChIAahIQYLIAAgAEQAAAAAAADgP6IiB6IiBSAFIAUgBSAFIAVELcMJbrf9ir6iRDlS5obKz9A+oKJEt9uqnhnOFL+gokSFVf4ZoAFaP6CiRPQQEREREaG/oKJEAAAAAAAA8D+gIghEAAAAAAAACEAgByAIoqEiB6FEAAAAAAAAGEAgACAHoqGjoiEHAkACQAJAAkACQCAERQ0AIAAgByAGoaIgBqEgBaEhBSAEQQFGDQEgBEF/Rw0CIAAgBaFEAAAAAAAA4D+iRAAAAAAAAOC/oA8LIAAgACAHoiAFoaEPCyAARAAAAAAAANC/Y0EBcw0BIAUgAEQAAAAAAADgP6ChRAAAAAAAAADAog8LIARB/wdqrUI0hr8hBiAEQTlJDQEgACAFoUQAAAAAAADwP6AiACAAoEQAAAAAAADgf6IgACAGoiAEQYAIRhtEAAAAAAAA8L+gDwsgACAFoSIAIACgRAAAAAAAAPA/oA8LRAAAAAAAAPA/Qf8HIARrrUI0hr8iB6EgACAFIAegoSAEQRRIIgQbIAAgBaFEAAAAAAAA8D8gBBugIAaiC6IDAwF+A38CfAJAAkACQAJAAkAgAL0iAUIAUw0AIAFCIIinIgJB//8/TQ0AIAJB//+//wdLDQNBgIDA/wMhA0GBeCEEIAJBgIDA/wNHDQEgAacNAkQAAAAAAAAAAA8LAkAgAUL///////////8Ag0IAUQ0AIAFCf1cNBCAARAAAAAAAAFBDor0iAUIgiKchA0HLdyEEDAILRAAAAAAAAPC/IAAgAKKjDwsgAiEDCyAEIANB4r4laiICQRR2arciBUQAAOD+Qi7mP6IgAkH//z9xQZ7Bmv8Daq1CIIYgAUL/////D4OEv0QAAAAAAADwv6AiACAFRHY8eTXvOeo9oiAAIABEAAAAAAAAAECgoyIFIAAgAEQAAAAAAADgP6KiIgYgBSAFoiIFIAWiIgAgACAARJ/GeNAJmsM/okSveI4dxXHMP6CiRAT6l5mZmdk/oKIgBSAAIAAgAEREUj7fEvHCP6JE3gPLlmRGxz+gokRZkyKUJEnSP6CiRJNVVVVVVeU/oKKgoKKgIAahoKAhAAsgAA8LIAAgAKFEAAAAAAAAAACjC4kEBAF/AX4BfwN8IwBBEGshASAAvSICQiCIpyEDAkACQAJAAkACQCACQgBTDQAgA0H5hOr+A00NACADQf//v/8HTQ0BIAAPCwJAIANBgIDA/3tJDQAgAEQAAAAAAADwv2INA0QAAAAAAADw/w8LAkAgA0EBdEH////JB0sNACADQYCAwP8HcUUNBCAADwtEAAAAAAAAAAAhBCADQcX9yv57Tw0ARAAAAAAAAAAAIQUMAQtEAAAAAAAAAAAhBAJAIABEAAAAAAAA8D+gIgW9IgJCIIinQeK+JWoiAUEUdkGBeGoiA0E1Sg0AIAAgBaFEAAAAAAAA8D+gIAAgBUQAAAAAAADwv6ChIANBAUobIAWjIQQLIAFB//8/cUGewZr/A2qtQiCGIAJC/////w+DhL9EAAAAAAAA8L+gIQAgA7chBQsgBUQAAOD+Qi7mP6IgACAEIAVEdjx5Ne856j2ioCAAIABEAAAAAAAAAECgoyIFIAAgAEQAAAAAAADgP6KiIgYgBSAFoiIEIASiIgUgBSAFRJ/GeNAJmsM/okSveI4dxXHMP6CiRAT6l5mZmdk/oKIgBCAFIAUgBUREUj7fEvHCP6JE3gPLlmRGxz+gokRZkyKUJEnSP6CiRJNVVVVVVeU/oKKgoKKgIAahoKAPCyAAIAChRAAAAAAAAAAAow8LIAEgALY4AgwgAAvHEAYBfAF+A38BfgV/CHxEAAAAAAAA8D8hAgJAIAG9IgNCIIinIgRB/////wdxIgUgA6ciBnJFDQAgAL0iB0IgiKchCAJAIAenIgkNACAIQYCAwP8DRg0BCwJAAkAgCEH/////B3EiCkGAgMD/B0sNACAJQQBHIApBgIDA/wdGcQ0AIAVBgIDA/wdLDQAgBkUNASAFQYCAwP8HRw0BCyAAIAGgDwtBACELAkACQAJAAkAgCEF/Sg0AQQIhCyAFQf///5kESw0AQQAhCyAFQYCAwP8DSQ0AIAVBFHYhDCAFQYCAgIoESQ0BQQIgBkGzCCAMayILdiIMQQFxa0EAIAwgC3QgBkYbIQsLIAZFDQEMAgtBACELIAYNAUECIAVBkwggDGsiBnYiC0EBcWtBACALIAZ0IAVGGyELCwJAAkACQAJAIAVBgIDA/wdHDQAgCkGAgMCAfGogCXJFDQUgCkGAgMD/A0kNASABRAAAAAAAAAAAIARBf0obDwsCQCAFQYCAwP8DRw0AIARBf0wNAyAADwsgBEGAgICABEcNASAAIACiDwtEAAAAAAAAAAAgAZogBEF/ShsPCyAIQQBIDQEgBEGAgID/A0cNASAAnw8LRAAAAAAAAPA/IACjDwsgAJkhAgJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAkNACAKRQ0BIApBgICAgARyQYCAwP8HRg0BC0QAAAAAAADwPyENIAhBf0oNAyALQQFGDQEgCw0DIAAgAKEiASABow8LRAAAAAAAAPA/IAKjIAIgBEEASBshAiAIQX9KDQsgCyAKQYCAwIB8anJFDQEgApogAiALQQFGGw8LRAAAAAAAAPC/IQ0gBUGBgICPBE8NAgwDCyACIAKhIgEgAaMPCyAFQYGAgI8ESQ0BCwJAIAVBgYDAnwRJDQAgCkH//7//A0sNAkQAAAAAAADwf0QAAAAAAAAAACAEQQBIGw8LIApB/v+//wNLDQIgDUScdQCIPOQ3fqJEnHUAiDzkN36iIA1EWfP4wh9upQGiRFnz+MIfbqUBoiAEQQBIGw8LQQAhBQJAAkAgCkH//z9LDQAgAkQAAAAAAABAQ6IiAr1CIIinIQpBSyEEDAELQQAhBAsgCkH//z9xIgZBgIDA/wNyIQggCkEUdSAEakGBeGohBCAGQY+xDkkNAyAGQfrsLk8NAkEBIQUMAwtEAAAAAAAA8H9EAAAAAAAAAAAgBEEAShsPCyAKQYGAwP8DSQ0CIA1EnHUAiDzkN36iRJx1AIg85Dd+oiANRFnz+MIfbqUBokRZ8/jCH26lAaIgBEEAShsPCyAIQYCAQGohCCAEQQFqIQQLIAVBA3QiBkGQH2orAwAiDiAIrUIghiACvUL/////D4OEvyIPIAZB8B5qKwMAIhChIhFEAAAAAAAA8D8gECAPoKMiEqIiAr1CgICAgHCDvyIAIAAgAKIiE0QAAAAAAAAIQKAgAiAAoCASIBEgACAIQQF1QYCAgIACciAFQRJ0akGAgCBqrUIghr8iFKKhIAAgDyAUIBChoaKhoiIPoiACIAKiIgAgAKIgACAAIAAgACAARO9ORUoofso/okRl28mTSobNP6CiRAFBHalgdNE/oKJETSaPUVVV1T+gokT/q2/btm3bP6CiRAMzMzMzM+M/oKKgIhCgvUKAgICAcIO/IgCiIhEgDyAAoiACIBAgAEQAAAAAAAAIwKAgE6GhoqAiAqC9QoCAgIBwg78iAEQAAADgCcfuP6IiDyAGQYAfaisDACACIAAgEaGhRP0DOtwJx+4/oiAARPUBWxTgLz6+oqCgIhCgoCAEtyICoL1CgICAgHCDvyIAIAKhIA6hIA+hIQ4MAQsgAkQAAAAAAADwv6AiAEQAAABgRxX3P6IiAiAARETfXfgLrlQ+oiAAIACiRAAAAAAAAOA/IAAgAEQAAAAAAADQv6JEVVVVVVVV1T+goqGiRP6CK2VHFfe/oqAiEKC9QoCAgIBwg78iACACoSEOCyAAIANCgICAgHCDvyIPoiICIBAgDqEgAaIgASAPoSAAoqAiAaAiAL0iA6chBQJAAkACQAJAAkAgA0IgiKciCEGAgMCEBEgNACAIQYCAwPt7aiAFckUNASANRJx1AIg85Dd+okScdQCIPOQ3fqIPCyAIQYD4//8HcUGAmMOEBEkNAiAIQYDovPsDaiAFckUNASANRFnz+MIfbqUBokRZ8/jCH26lAaIPCyABRP6CK2VHFZc8oCAAIAKhZEEBcw0BIA1EnHUAiDzkN36iRJx1AIg85Dd+og8LIAEgACACoWVBAXNFDQELQQAhBQJAIAhB/////wdxIgZBgYCA/wNJDQBBAEGAgMAAIAZBFHZBgnhqdiAIaiIGQf//P3FBgIDAAHJBkwggBkEUdkH/D3EiBGt2IgVrIAUgCEEASBshBSABIAJBgIBAIARBgXhqdSAGca1CIIa/oSICoL0hAwsCQCAFQRR0IANCgICAgHCDvyIARAAAAABDLuY/oiIPIAEgACACoaFE7zn6/kIu5j+iIABEOWyoDGFcIL6ioCICoCIBIAEgASABIAGiIgAgACAAIAAgAETQpL5yaTdmPqJE8WvSxUG9u76gokQs3iWvalYRP6CiRJO9vhZswWa/oKJEPlVVVVVVxT+goqEiAKIgAEQAAAAAAAAAwKCjIAIgASAPoaEiACABIACioKGhRAAAAAAAAPA/oCIBvSIDQiCIp2oiCEH//z9KDQAgDSABIAUQE6IPCyANIAitQiCGIANC/////w+DhL+iDwsgDURZ8/jCH26lAaJEWfP4wh9upQGiDwsgAgu4AQEBfwJAAkACQAJAIAFBgAhIDQAgAEQAAAAAAADgf6IhACABQYF4aiICQYAISA0BIAFBgnBqIgFB/wcgAUH/B0gbIQEgAEQAAAAAAADgf6IhAAwDCyABQYF4Sg0CIABEAAAAAAAAYAOiIQAgAUHJB2oiAkGBeEoNASABQZIPaiIBQYJ4IAFBgnhKGyEBIABEAAAAAAAAYAOiIQAMAgsgAiEBDAELIAIhAQsgACABQf8Haq1CNIa/oguiAgICfwF8IwBBEGsiASQAAkACQAJAIAC9QiCIp0H/////B3EiAkH7w6T/A0sNACACQf//v/IDSw0BIAEgAEQAAAAAAABwOKIgAEQAAAAAAABwR6AgAkGAgMAASRs5AwAgAUEQaiQAIAAPCyACQYCAwP8HSQ0BIAFBEGokACAAIAChDwsgAEQAAAAAAAAAAEEAEAohACABQRBqJAAgAA8LIAAgARAJIQIgASsDCCEAIAErAwAhAwJAAkACQCACQQNxIgJBAkYNACACQQFGDQEgAg0CIAMgAEEBEAohACABQRBqJAAgAA8LIAMgAEEBEAohACABQRBqJAAgAJoPCyADIAAQByEAIAFBEGokACAADwsgAyAAEAchACABQRBqJAAgAJoLrgEDAX4CfAF/RAAAAAAAAOC/RAAAAAAAAOA/IAC9IgFCAFMbIQIgAUL///////////8AgyIBvyEDAkACQAJAIAFCIIinIgRBwdyYhARLDQAgAxAPIQMgBEH//7//A0sNAiAEQYCAwPIDSQ0BIAIgAyADoCADIAOiIANEAAAAAAAA8D+go6GiDwsgAiACoCADEAyiIQALIAAPCyACIAMgAyADRAAAAAAAAPA/oKOgoguwAwMBfgJ/A3wCQAJAIAC9IgNCgICAgID/////AINCgYCAgPCE5fI/VCIEDQBEGC1EVPsh6T8gAJogACADQj+IpyIFG6FEB1wUMyamgTwgAZogASAFG6GgIQBEAAAAAAAAAAAhAQwBCwsgACAAIAAgAKIiBqIiB0RjVVVVVVXVP6IgASAGIAEgByAGIAaiIgggCCAIIAggCERzU2Dby3XzvqJEppI3oIh+FD+gokQBZfLy2ERDP6CiRCgDVskibW0/oKJEN9YGhPRklj+gokR6/hARERHBP6AgBiAIIAggCCAIIAhE1Hq/dHAq+z6iROmn8DIPuBI/oKJEaBCNGvcmMD+gokQVg+D+yNtXP6CiRJOEbunjJoI/oKJE/kGzG7qhqz+goqCioKKgoCIGoCEIAkAgBA0AQQEgAkEBdGu3IgEgACAGIAggCKIgCCABoKOhoCIIIAigoSIImiAIIAUbDwsCQCACRQ0ARAAAAAAAAPC/IAijIgEgCL1CgICAgHCDvyIHIAG9QoCAgIBwg78iCKJEAAAAAAAA8D+gIAYgByAAoaEgCKKgoiAIoCEICyAIC8EBAQJ/IwBBEGsiASQAAkACQAJAIAC9QiCIp0H/////B3EiAkH7w6T/A0sNACACQf////EDSw0BIAEgAEQAAAAAAABwOKIgAEQAAAAAAABwR6AgAkGAgMAASRs5AwAgAUEQaiQAIAAPCyACQYCAwP8HSQ0BIAFBEGokACAAIAChDwsgAEQAAAAAAAAAAEEAEBYhACABQRBqJAAgAA8LIAAgARAJIQIgASsDACABKwMIIAJBAXEQFiEAIAFBEGokACAAC4ACAwF/An4BfyMAQRBrIgEkACAAvSICQv///////////wCDIgO/IQACQAJAAkACQCADQiCIpyIEQeunhv8DSQ0AIARBgYDQgQRJDQFEAAAAAAAAAIAgAKNEAAAAAAAA8D+gIQAMAwsgBEGvscH+A0kNASAAIACgEA8iACAARAAAAAAAAABAoKMhAAwCC0QAAAAAAADwP0QAAAAAAAAAQCAAIACgEA9EAAAAAAAAAECgo6EhAAwBCwJAIARBgIDAAEkNACAARAAAAAAAAADAohAPIgCaIABEAAAAAAAAAECgoyEADAELIAEgALY4AgwLIAFBEGokACAAmiAAIAJCAFMbC/wCAgN/AX4CQCACRQ0AIAAgAToAACAAIAJqIgNBf2ogAToAACACQQNJDQAgACABOgACIAAgAToAASADQX1qIAE6AAAgA0F+aiABOgAAIAJBB0kNACAAIAE6AAMgA0F8aiABOgAAIAJBCUkNACAAQQAgAGtBA3EiBGoiAyABQf8BcUGBgoQIbCIBNgIAIAMgAiAEa0F8cSIEaiICQXxqIAE2AgAgBEEJSQ0AIAMgATYCCCADIAE2AgQgAkF4aiABNgIAIAJBdGogATYCACAEQRlJDQAgAyABNgIQIAMgATYCDCADIAE2AhQgAyABNgIYIAJBaGogATYCACACQWRqIAE2AgAgAkFsaiABNgIAIAJBcGogATYCACAEIANBBHFBGHIiBWsiAkEgSQ0AIAGtIgZCIIYgBoQhBiADIAVqIQEDQCABIAY3AwAgAUEIaiAGNwMAIAFBEGogBjcDACABQRhqIAY3AwAgAUEgaiEBIAJBYGoiAkEfSw0ACwsgAAsLqBcBAEGACAugF0+7YQVnrN0/GC1EVPsh6T+b9oHSC3PvPxgtRFT7Ifk/4mUvIn8rejwHXBQzJqaBPL3L8HqIB3A8B1wUMyamkTwDAAAABAAAAAQAAAAGAAAAg/miAERObgD8KRUA0VcnAN009QBi28AAPJmVAEGQQwBjUf4Au96rALdhxQA6biQA0k1CAEkG4AAJ6i4AHJLRAOsd/gApsRwA6D6nAPU1ggBEuy4AnOmEALQmcABBfl8A1pE5AFODOQCc9DkAi1+EACj5vQD4HzsA3v+XAA+YBQARL+8AClqLAG0fbQDPfjYACcsnAEZPtwCeZj8ALepfALondQDl68cAPXvxAPc5BwCSUooA+2vqAB+xXwAIXY0AMANWAHv8RgDwq2sAILzPADb0mgDjqR0AXmGRAAgb5gCFmWUAoBRfAI1AaACA2P8AJ3NNAAYGMQDKVhUAyahzAHviYABrjMAAGcRHAM1nwwAJ6NwAWYMqAIt2xACmHJYARK/dABlX0QClPgUABQf/ADN+PwDCMugAmE/eALt9MgAmPcMAHmvvAJ/4XgA1HzoAf/LKAPGHHQB8kCEAaiR8ANVu+gAwLXcAFTtDALUUxgDDGZ0ArcTCACxNQQAMAF0Ahn1GAONxLQCbxpoAM2IAALTSfAC0p5cAN1XVANc+9gCjEBgATXb8AGSdKgBw16sAY3z4AHqwVwAXFecAwElWADvW2QCnhDgAJCPLANaKdwBaVCMAAB+5APEKGwAZzt8AnzH/AGYeagCZV2EArPtHAH5/2AAiZbcAMuiJAOa/YADvxM0AbDYJAF0/1AAW3tcAWDveAN6bkgDSIigAKIboAOJYTQDGyjIACOMWAOB9ywAXwFAA8x2nABjgWwAuEzQAgxJiAINIAQD1jlsArbB/AB7p8gBISkMAEGfTAKrd2ACuX0IAamHOAAoopADTmbQABqbyAFx3fwCjwoMAYTyIAIpzeACvjFoAb9e9AC2mYwD0v8sAjYHvACbBZwBVykUAytk2ACio0gDCYY0AEsl3AAQmFAASRpsAxFnEAMjFRABNspEAABfzANRDrQApSeUA/dUQAAC+/AAelMwAcM7uABM+9QDs8YAAs+fDAMf4KACTBZQAwXE+AC4JswALRfMAiBKcAKsgewAutZ8AR5LCAHsyLwAMVW0AcqeQAGvnHwAxy5YAeRZKAEF54gD034kA6JSXAOLmhACZMZcAiO1rAF9fNgC7/Q4ASJq0AGekbABxckIAjV0yAJ8VuAC85QkAjTElAPd0OQAwBRwADQwBAEsIaAAs7lgAR6qQAHTnAgC91iQA932mAG5IcgCfFu8AjpSmALSR9gDRU1EAzwryACCYMwD1S34AsmNoAN0+XwBAXQMAhYl/AFVSKQA3ZMAAbdgQADJIMgBbTHUATnHUAEVUbgALCcEAKvVpABRm1QAnB50AXQRQALQ72wDqdsUAh/kXAElrfQAdJ7oAlmkpAMbMrACtFFQAkOJqAIjZiQAsclAABKS+AHcHlADzMHAAAPwnAOpxqABmwkkAZOA9AJfdgwCjP5cAQ5T9AA2GjAAxQd4AkjmdAN1wjAAXt+cACN87ABU3KwBcgKAAWoCTABARkgAP6NgAbICvANv/SwA4kA8AWRh2AGKlFQBhy7sAx4m5ABBAvQDS8gQASXUnAOu29gDbIrsAChSqAIkmLwBkg3YACTszAA6UGgBROqoAHaPCAK/trgBcJhIAbcJNAC16nADAVpcAAz+DAAnw9gArQIwAbTGZADm0BwAMIBUA2MNbAPWSxADGrUsATsqlAKc3zQDmqTYAq5KUAN1CaAAZY94AdozvAGiLUgD82zcArqGrAN8VMQAArqEADPvaAGRNZgDtBbcAKWUwAFdWvwBH/zoAavm5AHW+8wAok98Aq4AwAGaM9gAEyxUA+iIGANnkHQA9s6QAVxuPADbNCQBOQukAE76kADMjtQDwqhoAT2WoANLBpQALPw8AW3jNACP5dgB7iwQAiRdyAMamUwBvbuIA7+sAAJtKWADE2rcAqma6AHbPzwDRAh0AsfEtAIyZwQDDrXcAhkjaAPddoADGgPQArPAvAN3smgA/XLwA0N5tAJDHHwAq27YAoyU6AACvmgCtU5MAtlcEACkttABLgH4A2genAHaqDgB7WaEAFhIqANy3LQD65f0Aidv+AIm+/QDkdmwABqn8AD6AcACFbhUA/Yf/ACg+BwBhZzMAKhiGAE296gCz568Aj21uAJVnOQAxv1sAhNdIADDfFgDHLUMAJWE1AMlwzgAwy7gAv2z9AKQAogAFbOQAWt2gACFvRwBiEtIAuVyEAHBhSQBrVuAAmVIBAFBVNwAe1bcAM/HEABNuXwBdMOQAhS6pAB2ywwChMjYACLekAOqx1AAW9yEAj2nkACf/dwAMA4AAjUAtAE/NoAAgpZkAs6LTAC9dCgC0+UIAEdrLAH2+0ACb28EAqxe9AMqigQAIalwALlUXACcAVQB/FPAA4QeGABQLZACWQY0Ah77eANr9KgBrJbYAe4k0AAXz/gC5v54AaGpPAEoqqABPxFoALfi8ANdamAD0x5UADU2NACA6pgCkV18AFD+xAIA4lQDMIAEAcd2GAMnetgC/YPUATWURAAEHawCMsKwAssDQAFFVSAAe+w4AlXLDAKMGOwDAQDUABtx7AOBFzABOKfoA1srIAOjzQQB8ZN4Am2TYANm+MQCkl8MAd1jUAGnjxQDw2hMAujo8AEYYRgBVdV8A0r31AG6SxgCsLl0ADkTtABw+QgBhxIcAKf3pAOfW8wAifMoAb5E1AAjgxQD/140AbmriALD9xgCTCMEAfF10AGutsgDNbp0APnJ7AMYRagD3z6kAKXPfALXJugC3AFEA4rINAHS6JADlfWAAdNiKAA0VLACBGAwAfmaUAAEpFgCfenYA/f2+AFZF7wDZfjYA7NkTAIu6uQDEl/wAMagnAPFuwwCUxTYA2KhWALSotQDPzA4AEoktAG9XNAAsVokAmc7jANYguQBrXqoAPiqcABFfzAD9C0oA4fT7AI47bQDihiwA6dSEAPy0qQDv7tEALjXJAC85YQA4IUQAG9nIAIH8CgD7SmoALxzYAFO0hABOmYwAVCLMACpV3ADAxtYACxmWABpwuABplWQAJlpgAD9S7gB/EQ8A9LURAPzL9QA0vC0ANLzuAOhdzADdXmAAZ46bAJIz7wDJF7gAYVibAOFXvABRg8YA2D4QAN1xSAAtHN0ArxihACEsRgBZ89cA2XqYAJ5UwABPhvoAVgb8AOV5rgCJIjYAOK0iAGeT3ABV6KoAgiY4AMrnmwBRDaQAmTOxAKnXDgBpBUgAZbLwAH+IpwCITJcA+dE2ACGSswB7gkoAmM8hAECf3ADcR1UA4XQ6AGfrQgD+nd8AXtRfAHtnpAC6rHoAVfaiACuIIwBBulUAWW4IACEqhgA5R4MAiePmAOWe1ABJ+0AA/1bpABwPygDFWYoAlPorANPBxQAPxc8A21quAEfFhgCFQ2IAIYY7ACx5lAAQYYcAKkx7AIAsGgBDvxIAiCaQAHg8iQCoxOQA5dt7AMQ6wgAm9OoA92eKAA2SvwBloysAPZOxAL18CwCkUdwAJ91jAGnh3QCalBkAqCmVAGjOKAAJ7bQARJ8gAE6YygBwgmMAfnwjAA+5MgCn9Y4AFFbnACHxCAC1nSoAb35NAKUZUQC1+asAgt/WAJbdYQAWNgIAxDqfAIOioQBy7W0AOY16AIK4qQBrMlwARidbAAA07QDSAHcA/PRVAAFZTQDgcYAAAAAAAAAAAAAAAABA+yH5PwAAAAAtRHQ+AAAAgJhG+DwAAABgUcx4OwAAAICDG/A5AAAAQCAlejgAAACAIoLjNgAAAAAd82k1AAAAAAAA4D8AAAAAAADgvwAAAAAAAPA/AAAAAAAA+D8AAAAAAAAAAAbQz0Pr/Uw+AAAAAAAAAAAAAABAA7jiPwDsBwRuYW1lAcUBGgARX193YXNtX2NhbGxfY3RvcnMBBGFjb3MCBWFjb3NoAwRhc2luBAVhc2luaAUEYXRhbgYFYXRhbmgHBV9fY29zCBBfX3JlbV9waW8yX2xhcmdlCQpfX3JlbV9waW8yCgVfX3NpbgsDY29zDAdfX2V4cG8yDQRjb3NoDgNleHAPBWV4cG0xEANsb2cRBWxvZzFwEgNwb3cTBnNjYWxibhQDc2luFQRzaW5oFgVfX3RhbhcDdGFuGAR0YW5oGQZtZW1zZXQCnAYaAAABBQACcDABAmwwAgJsMQMCbDIEAmwzAgIAAnAwAQJsMAMGAAJwMAECbDACAmwxAwJsMgQCbDMFAmw0BAUAAnAwAQJsMAICbDEDAmwyBAJsMwUIAAJwMAECbDACAmwxAwJsMgQCbDMFAmw0BgJsNQcCbDYGBQACcDABAmwwAgJsMQMCbDIEAmwzBwUAAnAwAQJwMQICbDADAmwxBAJsMggdAAJwMAECcDECAnAyAwJwMwQCcDQFAmwwBgJsMQcCbDIIAmwzCQJsNAoCbDULAmw2DAJsNw0CbDgOAmw5DwNsMTAQA2wxMREDbDEyEgNsMTMTA2wxNBQDbDE1FQNsMTYWA2wxNxcDbDE4GANsMTkZA2wyMBoDbDIxGwNsMjIcA2wyMwkMAAJwMAECcDECAmwwAwJsMQQCbDIFAmwzBgJsNAcCbDUIAmw2CQJsNwoCbDgLAmw5CgYAAnAwAQJwMQICcDIDAmwwBAJsMQUCbDILBAACcDABAmwwAgJsMQMCbDIMAQACcDANBAACcDABAmwwAgJsMQMCbDIOCAACcDABAmwwAgJsMQMCbDIEAmwzBQJsNAYCbDUHAmw2DwkAAnAwAQJsMAICbDEDAmwyBAJsMwUCbDQGAmw1BwJsNggCbDcQBwACcDABAmwwAgJsMQMCbDIEAmwzBQJsNAYCbDURBwACcDABAmwwAgJsMQMCbDIEAmwzBQJsNAYCbDUSFQACcDABAnAxAgJsMAMCbDEEAmwyBQJsMwYCbDQHAmw1CAJsNgkCbDcKAmw4CwJsOQwDbDEwDQNsMTEOA2wxMg8DbDEzEANsMTQRA2wxNRIDbDE2EwNsMTcUA2wxOBMDAAJwMAECcDECAmwwFAQAAnAwAQJsMAICbDEDAmwyFQUAAnAwAQJsMAICbDEDAmwyBAJsMxYJAAJwMAECcDECAnAyAwJsMAQCbDEFAmwyBgJsMwcCbDQIAmw1FwMAAnAwAQJsMAICbDEYBQACcDABAmwwAgJsMQMCbDIEAmwzGQcAAnAwAQJwMQICcDIDAmwwBAJsMQUCbDIGAmwz" diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt new file mode 100644 index 000000000..822dedc3a --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt @@ -0,0 +1,77 @@ +package space.kscience.kmath.wasm + +import space.kscience.kmath.estree.compileWith +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.wasm.internal.DoubleWasmBuilder +import space.kscience.kmath.wasm.internal.IntWasmBuilder + +/** + * Compiles an [MST] to WASM in the context of reals. + * + * @author Iaroslav Postovalov + */ +public fun DoubleField.expression(mst: MST): Expression = + DoubleWasmBuilder(mst).instance + +/** + * Compiles an [MST] to WASM in the context of integers. + * + * @author Iaroslav Postovalov + */ +public fun IntRing.expression(mst: MST): Expression = + IntWasmBuilder(mst).instance + +/** + * Create a compiled expression with given [MST] and given [algebra]. + * + * @author Iaroslav Postovalov + */ +public fun MST.compileToExpression(algebra: IntRing): Expression = compileWith(algebra) + + +/** + * Compile given MST to expression and evaluate it against [arguments]. + * + * @author Iaroslav Postovalov + */ +public fun MST.compile(algebra: IntRing, arguments: Map): Int = + compileToExpression(algebra).invoke(arguments) + + +/** + * Compile given MST to expression and evaluate it against [arguments]. + * + * @author Iaroslav Postovalov + */ +public fun MST.compile(algebra: IntRing, vararg arguments: Pair): Int = + compileToExpression(algebra)(*arguments) + +/** + * Create a compiled expression with given [MST] and given [algebra]. + * + * @author Iaroslav Postovalov + */ +public fun MST.compileToExpression(algebra: DoubleField): Expression = compileWith(algebra) + + +/** + * Compile given MST to expression and evaluate it against [arguments]. + * + * @author Iaroslav Postovalov + */ +public fun MST.compile(algebra: DoubleField, arguments: Map): Double = + compileToExpression(algebra).invoke(arguments) + + +/** + * Compile given MST to expression and evaluate it against [arguments]. + * + * @author Iaroslav Postovalov + */ +public fun MST.compile(algebra: DoubleField, vararg arguments: Pair): Double = + compileToExpression(algebra).invoke(*arguments) diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt new file mode 100644 index 000000000..634a89b26 --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt @@ -0,0 +1,67 @@ +package space.kscience.kmath.ast + +import space.kscience.kmath.expressions.* +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.math.sin +import kotlin.random.Random +import kotlin.test.Test +import kotlin.time.measureTime +import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression +import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression + +internal class TestExecutionTime { + private companion object { + private const val times = 1_000_000 + private val x by symbol + private val algebra: ExtendedField = DoubleField + + private val functional = DoubleField.expressionInExtendedField { + bindSymbol(x) * const(2.0) + const(2.0) / bindSymbol(x) - const(16.0) / sin(bindSymbol(x)) + } + + private val node = MstExtendedField { + bindSymbol(x) * number(2.0) + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x)) + } + + private val mst = node.toExpression(DoubleField) + private val wasm = node.wasmCompileToExpression(DoubleField) + private val estree = node.estreeCompileToExpression(DoubleField) + + // In JavaScript, the expression below is implemented like + // _no_name_provided__125.prototype.invoke_178 = function (args) { + // var tmp = getValue(args, raw$_get_x__3(this._$x$delegate_2)) * 2.0 + 2.0 / getValue(args, raw$_get_x__3(this._$x$delegate_2)); + // var tmp0_sin_0_5 = getValue(args, raw$_get_x__3(this._$x$delegate_2)); + // return tmp - 16.0 / Math.sin(tmp0_sin_0_5); + // }; + + private val raw = Expression { args -> + args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 / sin(args.getValue(x)) + } + } + + private fun invokeAndSum(name: String, expr: Expression) { + println(name) + val rng = Random(0) + var sum = 0.0 + measureTime { repeat(times) { sum += expr(x to rng.nextDouble()) } }.also(::println) + } + + @Test + fun functionalExpression() = invokeAndSum("functional", functional) + + @Test + fun mstExpression() = invokeAndSum("mst", mst) + + @Test + fun wasmExpression() = invokeAndSum("wasm", wasm) + + @Test + fun estreeExpression() = invokeAndSum("estree", wasm) + + @Test + fun rawExpression() = invokeAndSum("raw", raw) +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt index 5823518ce..d80318db8 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt @@ -8,18 +8,17 @@ package space.kscience.kmath.estree import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.toComplex import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals internal class TestESTreeConsistencyWithInterpreter { - @Test fun mstSpace() { - val mst = MstGroup { binaryOperationFunction("+")( unaryOperationFunction("+")( @@ -30,12 +29,12 @@ internal class TestESTreeConsistencyWithInterpreter { ), number(1) - ) + bindSymbol("x") + zero + ) + bindSymbol(x) + zero } assertEquals( - mst.interpret(MstGroup, Symbol.x to MST.Numeric(2)), - mst.compile(MstGroup, Symbol.x to MST.Numeric(2)) + mst.interpret(MstGroup, x to MST.Numeric(2)), + mst.compile(MstGroup, x to MST.Numeric(2)) ) } @@ -44,7 +43,7 @@ internal class TestESTreeConsistencyWithInterpreter { val mst = MstRing { binaryOperationFunction("+")( unaryOperationFunction("+")( - (bindSymbol("x") - (2.toByte() + (scale( + (bindSymbol(x) - (2.toByte() + (scale( add(number(1), number(1)), 2.0 ) + 1.toByte()))) * 3.0 - 1.toByte() @@ -55,24 +54,24 @@ internal class TestESTreeConsistencyWithInterpreter { } assertEquals( - mst.interpret(ByteRing, Symbol.x to 3.toByte()), - mst.compile(ByteRing, Symbol.x to 3.toByte()) + mst.interpret(ByteRing, x to 3.toByte()), + mst.compile(ByteRing, x to 3.toByte()) ) } @Test - fun realField() { + fun doubleField() { val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero } assertEquals( - mst.interpret(DoubleField, Symbol.x to 2.0), - mst.compile(DoubleField, Symbol.x to 2.0) + mst.interpret(DoubleField, x to 2.0), + mst.compile(DoubleField, x to 2.0) ) } @@ -80,15 +79,19 @@ internal class TestESTreeConsistencyWithInterpreter { fun complexField() { val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero } assertEquals( - mst.interpret(ComplexField, Symbol.x to 2.0.toComplex()), - mst.compile(ComplexField, Symbol.x to 2.0.toComplex()) + mst.interpret(ComplexField, x to 2.0.toComplex()), + mst.compile(ComplexField, x to 2.0.toComplex()), ) } + + private companion object { + private val x by symbol + } } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt index a1bff92d0..a0b68a811 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt @@ -5,43 +5,38 @@ package space.kscience.kmath.estree -import space.kscience.kmath.expressions.MstExtendedField +import space.kscience.kmath.expressions.MstField +import space.kscience.kmath.expressions.MstGroup import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke -import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals internal class TestESTreeOperationsSupport { @Test fun testUnaryOperationInvocation() { - val expression = MstExtendedField { -bindSymbol("x") }.compileToExpression(DoubleField) - val res = expression("x" to 2.0) + val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField) + val res = expression(x to 2.0) assertEquals(-2.0, res) } @Test fun testBinaryOperationInvocation() { - val expression = MstExtendedField { -bindSymbol("x") + number(1.0) }.compileToExpression(DoubleField) - val res = expression("x" to 2.0) + val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField) + val res = expression(x to 2.0) assertEquals(-1.0, res) } @Test fun testConstProductInvocation() { - val res = MstExtendedField { bindSymbol("x") * 2 }.compileToExpression(DoubleField)("x" to 2.0) + val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0) assertEquals(4.0, res) } - @Test - fun testMultipleCalls() { - val e = - MstExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } - .compileToExpression(DoubleField) - val r = Random(0) - var s = 0.0 - repeat(1000000) { s += e("x" to r.nextDouble()) } - println(s) + private companion object { + private val x by symbol } } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt index b5ae1ca3f..6756fd8c7 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt @@ -7,7 +7,9 @@ package space.kscience.kmath.estree import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals @@ -15,55 +17,60 @@ import kotlin.test.assertEquals internal class TestESTreeSpecialization { @Test fun testUnaryPlus() { - val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol("x")) }.compileToExpression(DoubleField) - assertEquals(2.0, expr("x" to 2.0)) + val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(2.0, expr(x to 2.0)) } @Test fun testUnaryMinus() { - val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol("x")) }.compileToExpression(DoubleField) - assertEquals(-2.0, expr("x" to 2.0)) + val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(-2.0, expr(x to 2.0)) } @Test fun testAdd() { val expr = MstExtendedField { - binaryOperationFunction("+")(bindSymbol("x"), - bindSymbol("x")) + binaryOperationFunction("+")( + bindSymbol(x), + bindSymbol(x), + ) }.compileToExpression(DoubleField) - assertEquals(4.0, expr("x" to 2.0)) + assertEquals(4.0, expr(x to 2.0)) } @Test fun testSine() { - val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol("x")) }.compileToExpression(DoubleField) - assertEquals(0.0, expr("x" to 0.0)) + val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(0.0, expr(x to 0.0)) } @Test - fun testMinus() { + fun testSubtract() { val expr = MstExtendedField { - binaryOperationFunction("-")(bindSymbol("x"), - bindSymbol("x")) + binaryOperationFunction("-")(bindSymbol(x), + bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(0.0, expr("x" to 2.0)) + assertEquals(0.0, expr(x to 2.0)) } @Test fun testDivide() { val expr = MstExtendedField { - binaryOperationFunction("/")(bindSymbol("x"), - bindSymbol("x")) + binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(1.0, expr("x" to 2.0)) + assertEquals(1.0, expr(x to 2.0)) } @Test fun testPower() { val expr = MstExtendedField { - binaryOperationFunction("pow")(bindSymbol("x"), number(2)) + binaryOperationFunction("pow")(bindSymbol(x), number(2)) }.compileToExpression(DoubleField) - assertEquals(4.0, expr("x" to 2.0)) + assertEquals(4.0, expr(x to 2.0)) + } + + private companion object { + private val x by symbol } } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt index 1effe14e1..e1830d9df 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt @@ -7,7 +7,9 @@ package space.kscience.kmath.estree import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.ByteRing +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals @@ -16,13 +18,17 @@ import kotlin.test.assertFailsWith internal class TestESTreeVariables { @Test fun testVariable() { - val expr = MstRing{ bindSymbol("x") }.compileToExpression(ByteRing) - assertEquals(1.toByte(), expr("x" to 1.toByte())) + val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) + assertEquals(1.toByte(), expr(x to 1.toByte())) } @Test fun testUndefinedVariableFails() { - val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing) + val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) assertFailsWith { expr() } } + + private companion object { + private val x by symbol + } } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt new file mode 100644 index 000000000..f3e0726d6 --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt @@ -0,0 +1,60 @@ +/* + * 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.wasm + +import space.kscience.kmath.expressions.MstField +import space.kscience.kmath.expressions.MstRing +import space.kscience.kmath.expressions.interpret +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class TestWasmConsistencyWithInterpreter { + @Test + fun intRing() { + val mst = MstRing { + binaryOperationFunction("+")( + unaryOperationFunction("+")( + (bindSymbol(x) - (2.toByte() + (scale( + add(number(1), number(1)), + 2.0 + ) + 1.toByte()))) * 3.0 - 1.toByte() + ), + + number(1) + ) * number(2) + } + + assertEquals( + mst.interpret(IntRing, x to 3), + mst.compile(IntRing, x to 3) + ) + } + + @Test + fun doubleField() { + val mst = MstField { + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( + (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + + number(1), + number(1) / 2 + number(2.0) * one + ) + zero + } + + assertEquals( + mst.interpret(DoubleField, x to 2.0), + mst.compile(DoubleField, x to 2.0) + ) + } + + private companion object { + private val x by symbol + } +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt new file mode 100644 index 000000000..2946592f4 --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.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.wasm + +import space.kscience.kmath.expressions.MstField +import space.kscience.kmath.expressions.MstGroup +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class TestWasmOperationsSupport { + @Test + fun testUnaryOperationInvocation() { + val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField) + val res = expression(x to 2.0) + assertEquals(-2.0, res) + } + + @Test + fun testBinaryOperationInvocation() { + val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField) + val res = expression(x to 2.0) + assertEquals(-1.0, res) + } + + @Test + fun testConstProductInvocation() { + val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0) + assertEquals(4.0, res) + } + + private companion object { + private val x by symbol + } +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt new file mode 100644 index 000000000..e1f7b603a --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt @@ -0,0 +1,76 @@ +/* + * 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.wasm + +import space.kscience.kmath.expressions.MstExtendedField +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class TestWasmSpecialization { + @Test + fun testUnaryPlus() { + val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(2.0, expr(x to 2.0)) + } + + @Test + fun testUnaryMinus() { + val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(-2.0, expr(x to 2.0)) + } + + @Test + fun testAdd() { + val expr = MstExtendedField { + binaryOperationFunction("+")( + bindSymbol(x), + bindSymbol(x), + ) + }.compileToExpression(DoubleField) + assertEquals(4.0, expr(x to 2.0)) + } + + @Test + fun testSine() { + val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(0.0, expr(x to 0.0)) + } + + @Test + fun testSubtract() { + val expr = MstExtendedField { + binaryOperationFunction("-")(bindSymbol(x), + bindSymbol(x)) + }.compileToExpression(DoubleField) + assertEquals(0.0, expr(x to 2.0)) + } + + @Test + fun testDivide() { + val expr = MstExtendedField { + binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x)) + }.compileToExpression(DoubleField) + assertEquals(1.0, expr(x to 2.0)) + } + + @Test + fun testPower() { + val expr = MstExtendedField { + binaryOperationFunction("pow")(bindSymbol(x), number(2)) + }.compileToExpression(DoubleField) + + assertEquals(4.0, expr(x to 2.0)) + } + + private companion object { + private val x by symbol + } +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt new file mode 100644 index 000000000..e627f551c --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt @@ -0,0 +1,48 @@ +package space.kscience.kmath.wasm + +import space.kscience.kmath.expressions.MstExtendedField +import space.kscience.kmath.expressions.MstRing +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class TestWasmSpecific { + @Test + fun int() { + val res = MstRing { number(100000000) + number(10000000) }.compile(IntRing) + assertEquals(110000000, res) + } + + @Test + fun real() { + val res = MstExtendedField { number(100000000) + number(2).pow(10) }.compile(DoubleField) + assertEquals(100001024.0, res) + } + + @Test + fun argsPassing() { + val res = MstExtendedField { bindSymbol(y) + bindSymbol(x).pow(10) }.compile( + DoubleField, + x to 2.0, + y to 100000000.0, + ) + + assertEquals(100001024.0, res) + } + + @Test + fun powFunction() { + val expr = MstExtendedField { bindSymbol(x).pow(1.0 / 6.0) }.compileToExpression(DoubleField) + assertEquals(0.9730585187140817, expr(x to 0.8488554755054833)) + } + + private companion object { + private val x by symbol + private val y by symbol + } +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt new file mode 100644 index 000000000..406ba8c8d --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt @@ -0,0 +1,34 @@ +/* + * 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.wasm + +import space.kscience.kmath.expressions.MstRing +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +internal class TestWasmVariables { + @Test + fun testVariable() { + val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing) + assertEquals(1, expr(x to 1)) + } + + @Test + fun testUndefinedVariableFails() { + val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing) + assertFailsWith { expr() } + } + + private companion object { + private val x by symbol + } +} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt index 77cfb2241..f94d36602 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt @@ -8,18 +8,17 @@ package space.kscience.kmath.asm import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.toComplex import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.Symbol.Companion.x +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals internal class TestAsmConsistencyWithInterpreter { - @Test fun mstSpace() { - val mst = MstGroup { binaryOperationFunction("+")( unaryOperationFunction("+")( @@ -30,7 +29,7 @@ internal class TestAsmConsistencyWithInterpreter { ), number(1) - ) + bindSymbol("x") + zero + ) + bindSymbol(x) + zero } assertEquals( @@ -44,7 +43,7 @@ internal class TestAsmConsistencyWithInterpreter { val mst = MstRing { binaryOperationFunction("+")( unaryOperationFunction("+")( - (bindSymbol("x") - (2.toByte() + (scale( + (bindSymbol(x) - (2.toByte() + (scale( add(number(1), number(1)), 2.0 ) + 1.toByte()))) * 3.0 - 1.toByte() @@ -61,10 +60,10 @@ internal class TestAsmConsistencyWithInterpreter { } @Test - fun realField() { + fun doubleField() { val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero @@ -80,7 +79,7 @@ internal class TestAsmConsistencyWithInterpreter { fun complexField() { val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero @@ -91,4 +90,8 @@ internal class TestAsmConsistencyWithInterpreter { mst.compile(ComplexField, x to 2.0.toComplex()) ) } + + private companion object { + private val x by symbol + } } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt index 757235fb7..147639f7c 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt @@ -5,45 +5,38 @@ package space.kscience.kmath.asm -import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.MstField import space.kscience.kmath.expressions.MstGroup import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke -import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals internal class TestAsmOperationsSupport { @Test fun testUnaryOperationInvocation() { - val expression = MstGroup { -bindSymbol("x") }.compileToExpression(DoubleField) - val res = expression("x" to 2.0) + val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField) + val res = expression(x to 2.0) assertEquals(-2.0, res) } @Test fun testBinaryOperationInvocation() { - val expression = MstGroup { -bindSymbol("x") + number(1.0) }.compileToExpression(DoubleField) - val res = expression("x" to 2.0) + val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField) + val res = expression(x to 2.0) assertEquals(-1.0, res) } @Test fun testConstProductInvocation() { - val res = MstField { bindSymbol("x") * 2 }.compileToExpression(DoubleField)("x" to 2.0) + val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0) assertEquals(4.0, res) } - @Test - fun testMultipleCalls() { - val e = - MstExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } - .compileToExpression(DoubleField) - val r = Random(0) - var s = 0.0 - repeat(1000000) { s += e("x" to r.nextDouble()) } - println(s) + private companion object { + private val x by symbol } } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt index b09d79515..3a681e482 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt @@ -7,7 +7,9 @@ package space.kscience.kmath.asm import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals @@ -15,55 +17,60 @@ import kotlin.test.assertEquals internal class TestAsmSpecialization { @Test fun testUnaryPlus() { - val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol("x")) }.compileToExpression(DoubleField) - assertEquals(2.0, expr("x" to 2.0)) + val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(2.0, expr(x to 2.0)) } @Test fun testUnaryMinus() { - val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol("x")) }.compileToExpression(DoubleField) - assertEquals(-2.0, expr("x" to 2.0)) + val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(-2.0, expr(x to 2.0)) } @Test fun testAdd() { val expr = MstExtendedField { - binaryOperationFunction("+")(bindSymbol("x"), - bindSymbol("x")) + binaryOperationFunction("+")( + bindSymbol(x), + bindSymbol(x), + ) }.compileToExpression(DoubleField) - assertEquals(4.0, expr("x" to 2.0)) + assertEquals(4.0, expr(x to 2.0)) } @Test fun testSine() { - val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol("x")) }.compileToExpression(DoubleField) - assertEquals(0.0, expr("x" to 0.0)) + val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(0.0, expr(x to 0.0)) } @Test - fun testMinus() { + fun testSubtract() { val expr = MstExtendedField { - binaryOperationFunction("-")(bindSymbol("x"), - bindSymbol("x")) + binaryOperationFunction("-")(bindSymbol(x), + bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(0.0, expr("x" to 2.0)) + assertEquals(0.0, expr(x to 2.0)) } @Test fun testDivide() { val expr = MstExtendedField { - binaryOperationFunction("/")(bindSymbol("x"), - bindSymbol("x")) + binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(1.0, expr("x" to 2.0)) + assertEquals(1.0, expr(x to 2.0)) } @Test fun testPower() { val expr = MstExtendedField { - binaryOperationFunction("pow")(bindSymbol("x"), number(2)) + binaryOperationFunction("pow")(bindSymbol(x), number(2)) }.compileToExpression(DoubleField) - assertEquals(4.0, expr("x" to 2.0)) + assertEquals(4.0, expr(x to 2.0)) + } + + private companion object { + private val x by symbol } } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt index 740326a59..89b98d720 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt @@ -7,7 +7,9 @@ package space.kscience.kmath.asm import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.ByteRing +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals @@ -16,13 +18,17 @@ import kotlin.test.assertFailsWith internal class TestAsmVariables { @Test fun testVariable() { - val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing) - assertEquals(1.toByte(), expr("x" to 1.toByte())) + val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) + assertEquals(1.toByte(), expr(x to 1.toByte())) } @Test fun testUndefinedVariableFails() { - val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing) + val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) assertFailsWith { expr() } } + + private companion object { + private val x by symbol + } } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt deleted file mode 100644 index 1584293ce..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.ast.rendering - -import space.kscience.kmath.ast.rendering.TestUtils.testLatex -import space.kscience.kmath.expressions.MST.Numeric -import kotlin.test.Test - -internal class TestFeatures { - @Test - fun printSymbolic() = testLatex("x", "x") - - @Test - fun printNumeric() { - val num = object : Number() { - override fun toByte(): Byte = throw UnsupportedOperationException() - override fun toChar(): Char = throw UnsupportedOperationException() - override fun toDouble(): Double = throw UnsupportedOperationException() - override fun toFloat(): Float = throw UnsupportedOperationException() - override fun toInt(): Int = throw UnsupportedOperationException() - override fun toLong(): Long = throw UnsupportedOperationException() - override fun toShort(): Short = throw UnsupportedOperationException() - override fun toString(): String = "foo" - } - - testLatex(Numeric(num), "foo") - } - - @Test - fun prettyPrintFloats() { - testLatex(Numeric(Double.NaN), "NaN") - testLatex(Numeric(Double.POSITIVE_INFINITY), "\\infty") - testLatex(Numeric(Double.NEGATIVE_INFINITY), "-\\infty") - testLatex(Numeric(1.0), "1") - testLatex(Numeric(-1.0), "-1") - testLatex(Numeric(1.42), "1.42") - testLatex(Numeric(-1.42), "-1.42") - testLatex(Numeric(1.1e10), "1.1\\times10^{10}") - testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}") - testLatex(Numeric(-1.1e-10), "-1.1\\times10^{-10}") - testLatex(Numeric(-1.1e10), "-1.1\\times10^{10}") - } - - @Test - fun prettyPrintIntegers() { - testLatex(Numeric(42), "42") - testLatex(Numeric(-42), "-42") - } - - @Test - fun prettyPrintPi() { - testLatex("pi", "\\pi") - } - - @Test - fun binaryPlus() = testLatex("2+2", "2+2") - - @Test - fun binaryMinus() = testLatex("2-2", "2-2") - - @Test - fun fraction() = testLatex("2/2", "\\frac{2}{2}") - - @Test - fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)") - - @Test - fun unaryOperator() = testLatex("f(x)", "\\operatorname{f}\\,\\left(x\\right)") - - @Test - fun power() = testLatex("x^y", "x^{y}") - - @Test - fun squareRoot() = testLatex("sqrt(x)", "\\sqrt{x}") - - @Test - fun exponential() = testLatex("exp(x)", "e^{x}") - - @Test - fun multiplication() = testLatex("x*1", "x\\times1") - - @Test - fun inverseTrigonometry() { - testLatex("asin(x)", "\\operatorname{sin}^{-1}\\,\\left(x\\right)") - testLatex("asinh(x)", "\\operatorname{sinh}^{-1}\\,\\left(x\\right)") - testLatex("acos(x)", "\\operatorname{cos}^{-1}\\,\\left(x\\right)") - testLatex("acosh(x)", "\\operatorname{cosh}^{-1}\\,\\left(x\\right)") - testLatex("atan(x)", "\\operatorname{tan}^{-1}\\,\\left(x\\right)") - testLatex("atanh(x)", "\\operatorname{tanh}^{-1}\\,\\left(x\\right)") - } - -// @Test -// fun unaryPlus() { -// testLatex("+1", "+1") -// testLatex("+1", "++1") -// } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt deleted file mode 100644 index 6322df25d..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.ast.rendering - -import space.kscience.kmath.ast.rendering.TestUtils.testLatex -import space.kscience.kmath.expressions.MST -import space.kscience.kmath.operations.GroupOperations -import kotlin.test.Test - -internal class TestLatex { - @Test - fun number() = testLatex("42", "42") - - @Test - fun symbol() = testLatex("x", "x") - - @Test - fun operatorName() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") - - @Test - fun specialSymbol() { - testLatex(MST.Numeric(Double.POSITIVE_INFINITY), "\\infty") - testLatex("pi", "\\pi") - } - - @Test - fun operand() { - testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") - testLatex("1+1", "1+1") - } - - @Test - fun unaryOperator() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") - - @Test - fun unaryPlus() = testLatex(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1") - - @Test - fun unaryMinus() = testLatex("-x", "-x") - - @Test - fun radical() = testLatex("sqrt(x)", "\\sqrt{x}") - - @Test - fun superscript() = testLatex("x^y", "x^{y}") - - @Test - fun subscript() = testLatex(SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), "x_{123}") - - @Test - fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)") - - @Test - fun binaryPlus() = testLatex("x+x", "x+x") - - @Test - fun binaryMinus() = testLatex("x-x", "x-x") - - @Test - fun fraction() = testLatex("x/x", "\\frac{x}{x}") - - @Test - fun radicalWithIndex() = testLatex(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), "\\sqrt[x]{y}") - - @Test - fun multiplication() { - testLatex("x*1", "x\\times1") - testLatex("1*x", "1\\,x") - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt deleted file mode 100644 index 2d7bfad19..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.ast.rendering - -import space.kscience.kmath.ast.rendering.TestUtils.testMathML -import space.kscience.kmath.expressions.MST -import space.kscience.kmath.operations.GroupOperations -import kotlin.test.Test - -internal class TestMathML { - @Test - fun number() = testMathML("42", "42") - - @Test - fun symbol() = testMathML("x", "x") - - @Test - fun operatorName() = testMathML( - "sin(1)", - "sin1", - ) - - @Test - fun specialSymbol() { - testMathML(MST.Numeric(Double.POSITIVE_INFINITY), "") - testMathML("pi", "π") - } - - @Test - fun operand() { - testMathML( - "sin(1)", - "sin1", - ) - - testMathML("1+1", "1+1") - } - - @Test - fun unaryOperator() = testMathML( - "sin(1)", - "sin1", - ) - - @Test - fun unaryPlus() = - testMathML(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1") - - @Test - fun unaryMinus() = testMathML("-x", "-x") - - @Test - fun radical() = testMathML("sqrt(x)", "x") - - @Test - fun superscript() = testMathML("x^y", "xy") - - @Test - fun subscript() = testMathML( - SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), - "x123", - ) - - @Test - fun binaryOperator() = testMathML( - "f(x, y)", - "fx,y", - ) - - @Test - fun binaryPlus() = testMathML("x+x", "x+x") - - @Test - fun binaryMinus() = testMathML("x-x", "x-x") - - @Test - fun fraction() = testMathML("x/x", "xx") - - @Test - fun radicalWithIndex() = - testMathML(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), - "yx") - - @Test - fun multiplication() { - testMathML("x*1", "x×1") - testMathML("1*x", "1x") - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt deleted file mode 100644 index a4017fdb4..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.ast.rendering - -import space.kscience.kmath.ast.rendering.TestUtils.testLatex -import kotlin.test.Test - -internal class TestStages { - @Test - fun betterMultiplication() { - testLatex("a*1", "a\\times1") - testLatex("1*(2/3)", "1\\times\\left(\\frac{2}{3}\\right)") - testLatex("1*1", "1\\times1") - testLatex("2e10", "2\\times10^{10}") - testLatex("2*x", "2\\,x") - testLatex("2*(x+1)", "2\\,\\left(x+1\\right)") - testLatex("x*y", "x\\,y") - } - - @Test - fun parentheses() { - testLatex("(x+1)", "x+1") - testLatex("x*x*x", "x\\,x\\,x") - testLatex("(x+x)*x", "\\left(x+x\\right)\\,x") - testLatex("x+x*x", "x+x\\,x") - testLatex("x+x^x*x+x", "x+x^{x}\\,x+x") - testLatex("(x+x)^x+x*x", "\\left(x+x\\right)^{x}+x\\,x") - testLatex("x^(x+x)", "x^{x+x}") - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt deleted file mode 100644 index 7c9400532..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.ast.rendering - -import space.kscience.kmath.ast.parseMath -import space.kscience.kmath.expressions.MST -import kotlin.test.assertEquals - -internal object TestUtils { - private fun mathSyntax(mst: MST) = FeaturedMathRendererWithPostProcess.Default.render(mst) - private fun latex(mst: MST) = LatexSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst)) - private fun mathML(mst: MST) = MathMLSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst)) - - internal fun testLatex(mst: MST, expectedLatex: String) = assertEquals( - expected = expectedLatex, - actual = latex(mst), - ) - - internal fun testLatex(expression: String, expectedLatex: String) = assertEquals( - expected = expectedLatex, - actual = latex(expression.parseMath()), - ) - - internal fun testLatex(expression: MathSyntax, expectedLatex: String) = assertEquals( - expected = expectedLatex, - actual = LatexSyntaxRenderer.renderWithStringBuilder(expression), - ) - - internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", - actual = mathML(mst), - ) - - internal fun testMathML(expression: String, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", - actual = mathML(expression.parseMath()), - ) - - internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", - actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression), - ) -} diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 3a05c3d6d..70beab95a 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-7`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0-dev-6' + implementation 'space.kscience:kmath-complex:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -31,6 +31,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0-dev-6") + implementation("space.kscience:kmath-complex:0.3.0-dev-7") } ``` diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index 1c2e8a0a2..a28226d90 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -1,5 +1,3 @@ -import ru.mipt.npm.gradle.Maturity - /* * 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. @@ -21,7 +19,7 @@ kotlin.sourceSets { readme { description = "Complex numbers and quaternions." - maturity = Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-core/README.md b/kmath-core/README.md index b83fb13d0..e28873045 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-7`. **Gradle:** ```gradle @@ -26,7 +26,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0-dev-6' + implementation 'space.kscience:kmath-core:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -38,6 +38,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0-dev-6") + implementation("space.kscience:kmath-core:0.3.0-dev-7") } ``` diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index df70aa40b..f1a2ed40f 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -21,7 +19,7 @@ kotlin.sourceSets { readme { description = "Core classes, algebra definitions, basic linear algebra" - maturity = Maturity.DEVELOPMENT + maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt new file mode 100644 index 000000000..b5e652784 --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt @@ -0,0 +1,18 @@ +package space.kscience.kmath.expressions + +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test + +internal class InterpretTest { + @Test + fun interpretation() { + val expr = MstField { + val x = bindSymbol(Symbol.x) + x * 2.0 + number(2.0) / x - 16.0 + }.toExpression(DoubleField) + expr(Symbol.x to 2.2) + } +} diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index 30f9ce1f9..531bbd935 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -29,5 +27,5 @@ kotlin.sourceSets { } readme { - maturity = Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index cae11724d..3bf29f803 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-7`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0-dev-6' + implementation 'space.kscience:kmath-ejml:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0-dev-6") + implementation("space.kscience:kmath-ejml:0.3.0-dev-7") } ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 922e6572b..20e52deb2 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-7`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0-dev-6' + implementation 'space.kscience:kmath-for-real:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0-dev-6") + implementation("space.kscience:kmath-for-real:0.3.0-dev-7") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index eef677565..d5907f1c5 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-7`. **Gradle:** ```gradle @@ -22,7 +22,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0-dev-6' + implementation 'space.kscience:kmath-functions:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -34,6 +34,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0-dev-6") + implementation("space.kscience:kmath-functions:0.3.0-dev-7") } ``` diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index 65db43edf..121498ce8 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -17,5 +15,5 @@ kotlin.sourceSets.commonMain { } readme { - maturity = Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE } diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index 024e34076..af3ebaed9 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -28,5 +26,5 @@ kotlin.sourceSets { } readme { - maturity = Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE } diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index 66018a227..3ed73451d 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -10,6 +10,7 @@ import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.MstAlgebra import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals @@ -19,8 +20,8 @@ import kotlin.test.fail internal class AdaptingTests { @Test fun symbol() { - val c1 = MstAlgebra.bindSymbol("x") - assertTrue(c1.toSVar>().name == "x") + val c1 = MstAlgebra.bindSymbol(x.identity) + assertEquals(x.identity, c1.toSVar>().name) val c2 = "kitten".parseMath().toSFun>() if (c2 is SVar) assertTrue(c2.name == "kitten") else fail() } @@ -45,23 +46,27 @@ internal class AdaptingTests { @Test fun simpleFunctionDerivative() { - val x = MstAlgebra.bindSymbol("x").toSVar>() + val xSVar = MstAlgebra.bindSymbol(x.identity).toSVar>() val quadratic = "x^2-4*x-44".parseMath().toSFun>() - val actualDerivative = quadratic.d(x).toMst().compileToExpression(DoubleField) + val actualDerivative = quadratic.d(xSVar).toMst().compileToExpression(DoubleField) val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField) - assertEquals(actualDerivative("x" to 123.0), expectedDerivative("x" to 123.0)) + assertEquals(actualDerivative(x to 123.0), expectedDerivative(x to 123.0)) } @Test fun moreComplexDerivative() { - val x = MstAlgebra.bindSymbol("x").toSVar>() + val xSVar = MstAlgebra.bindSymbol(x.identity).toSVar>() val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun>() - val actualDerivative = composition.d(x).toMst().compileToExpression(DoubleField) + val actualDerivative = composition.d(xSVar).toMst().compileToExpression(DoubleField) - val expectedDerivative = - "-(2*x*cos(x^2)+2*sin(x)*cos(x)-16)/(2*sqrt(sin(x^2)-16*x-cos(x)^2))".parseMath().compileToExpression(DoubleField) + val expectedDerivative = "-(2*x*cos(x^2)+2*sin(x)*cos(x)-16)/(2*sqrt(sin(x^2)-16*x-cos(x)^2))" + .parseMath() + .compileToExpression(DoubleField) + assertEquals(actualDerivative(x to 0.1), expectedDerivative(x to 0.1)) + } - assertEquals(actualDerivative("x" to 0.1), expectedDerivative("x" to 0.1)) + private companion object { + private val x by symbol } } diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 829fe4142..66e0483a4 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-7`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0-dev-6' + implementation 'space.kscience:kmath-nd4j:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -32,7 +32,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0-dev-6") + implementation("space.kscience:kmath-nd4j:0.3.0-dev-7") } ``` diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index c7d891206..2b549f919 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") @@ -20,7 +18,7 @@ dependencies { readme { description = "ND4J NDStructure implementation and according NDAlgebra classes" - maturity = Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index dff504ef0..8522cf92f 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -30,5 +28,5 @@ kotlin.sourceSets { } readme { - maturity = Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 0d853dea7..747fe0252 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") @@ -18,5 +16,5 @@ dependencies { } readme { - maturity = Maturity.DEVELOPMENT + maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT } \ No newline at end of file From 0a0d0af94a4e586a0214815a272c17d7d530827b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 21 Apr 2021 19:46:02 +0700 Subject: [PATCH 122/211] Configure copyright scoping --- .gitignore | 1 + .idea/copyright/kmath.xml | 6 ++++++ .idea/copyright/profiles_settings.xml | 21 +++++++++++++++++++ .idea/scopes/Apply_copyright.xml | 4 ++++ benchmarks/build.gradle.kts | 5 ----- build.gradle.kts | 5 ----- examples/build.gradle.kts | 5 ----- .../kscience/kmath/functions/integrate.kt | 5 +++++ .../kmath/functions/matrixIntegration.kt | 5 +++++ gradlew | 15 +++++++++++-- kmath-ast/build.gradle.kts | 5 ----- .../kmath/ast/ParserPrecedenceTest.kt | 5 +++++ .../space/kscisnce/kmath/ast/ParserTest.kt | 5 +++++ .../internal/astring/astring.typealises.kt | 5 +++++ .../kscience/kmath/internal/base64/base64.kt | 5 +++++ .../kmath/internal/binaryen/index.binaryen.kt | 5 +++++ .../binaryen/index.binaryen.typealiases.kt | 5 +++++ .../kscience/kmath/internal/stream/stream.kt | 5 +++++ .../lib.dom.WebAssembly.module_dukat.kt | 5 +++++ .../nonDeclarations.WebAssembly.kt | 5 +++++ .../kmath/wasm/internal/WasmBuilder.kt | 5 +++++ .../wasm/internal/f64StandardFunctions.kt | 5 +++++ .../kotlin/space/kscience/kmath/wasm/wasm.kt | 5 +++++ .../kscience/kmath/ast/TestExecutionTime.kt | 5 +++++ .../kscience/kmath/wasm/TestWasmSpecific.kt | 5 +++++ kmath-commons/build.gradle.kts | 6 +----- kmath-complex/build.gradle.kts | 5 ----- kmath-core/build.gradle.kts | 5 ----- .../kmath/expressions/InterpretTest.kt | 5 +++++ kmath-coroutines/build.gradle.kts | 5 ----- kmath-functions/build.gradle.kts | 5 ----- kmath-geometry/build.gradle.kts | 5 ----- kmath-histograms/build.gradle.kts | 5 ----- kmath-kotlingrad/build.gradle.kts | 7 +------ kmath-memory/build.gradle.kts | 7 +------ kmath-nd4j/build.gradle.kts | 5 ----- kmath-stat/build.gradle.kts | 5 ----- kmath-viktor/build.gradle.kts | 5 ----- settings.gradle.kts | 5 ----- 39 files changed, 133 insertions(+), 89 deletions(-) create mode 100644 .idea/copyright/kmath.xml create mode 100644 .idea/copyright/profiles_settings.xml create mode 100644 .idea/scopes/Apply_copyright.xml diff --git a/.gitignore b/.gitignore index 2a13b9e3c..d6c4af4e3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ out/ .idea/ !.idea/copyright/ +!.idea/scopes/ .vscode/ diff --git a/.idea/copyright/kmath.xml b/.idea/copyright/kmath.xml new file mode 100644 index 000000000..17e44e4d0 --- /dev/null +++ b/.idea/copyright/kmath.xml @@ -0,0 +1,6 @@ + + + + diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 000000000..b538bdf41 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/scopes/Apply_copyright.xml b/.idea/scopes/Apply_copyright.xml new file mode 100644 index 000000000..0eb589133 --- /dev/null +++ b/.idea/scopes/Apply_copyright.xml @@ -0,0 +1,4 @@ + + + diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index d6796ed46..88f034a2a 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") kotlin("plugin.allopen") diff --git a/build.gradle.kts b/build.gradle.kts index a7c9144a7..4e0b6f256 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { id("ru.mipt.npm.gradle.project") } diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 67fe9853a..56feee9dc 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("jvm") } diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt index 90542adf4..6990e8c8f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt @@ -1,3 +1,8 @@ +/* + * 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.functions import space.kscience.kmath.integration.integrate diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt index bd431c22c..8020df8f6 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt @@ -1,3 +1,8 @@ +/* + * 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.functions import space.kscience.kmath.integration.integrate diff --git a/gradlew b/gradlew index 6ad9eb930..4f906e0c8 100755 --- a/gradlew +++ b/gradlew @@ -1,8 +1,19 @@ #!/usr/bin/env sh # -# 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. +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # ############################################################################## diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 15357b2d5..b4a0b28ac 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt index 509f87d98..14ceefc30 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt @@ -1,3 +1,8 @@ +/* + * 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.kscisnce.kmath.ast import space.kscience.kmath.ast.parseMath diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt index 13f5b3290..a0dcba9c0 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt @@ -1,3 +1,8 @@ +/* + * 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.kscisnce.kmath.ast import space.kscience.kmath.ast.parseMath diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt index 1f6a5f04d..93b4f6ce6 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt @@ -1,3 +1,8 @@ +/* + * 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.internal.astring internal typealias Generator = Any diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt index a0c7cb6ee..86e0cede7 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:Suppress( "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt index d3e3539c6..42b6ac7d8 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:Suppress( "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt index f89db20e2..523b13b40 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:Suppress("PackageDirectoryMismatch", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation") package space.kscience.kmath.internal.binaryen diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt index ae6c7eb35..52be5530f 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt @@ -1,3 +1,8 @@ +/* + * 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.internal.stream import space.kscience.kmath.internal.emitter.Emitter diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt index 322a2fa7b..3754c3eff 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:JsQualifier("WebAssembly") @file:Suppress( diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt index 095e46140..59733299a 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt index a031a4de4..bd2b340a0 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -1,3 +1,8 @@ +/* + * 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.wasm.internal import space.kscience.kmath.expressions.Expression diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt index cb0d71ad5..21a88b5d0 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt @@ -1,3 +1,8 @@ +/* + * 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.wasm.internal import space.kscience.kmath.internal.base64.toUint8Array diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt index 822dedc3a..d44c4e49d 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt @@ -1,3 +1,8 @@ +/* + * 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.wasm import space.kscience.kmath.estree.compileWith diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt index 634a89b26..01746ddb6 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt @@ -1,3 +1,8 @@ +/* + * 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.ast import space.kscience.kmath.expressions.* diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt index e627f551c..dd5452d04 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt @@ -1,3 +1,8 @@ +/* + * 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.wasm import space.kscience.kmath.expressions.MstExtendedField diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index 570ac2b74..a208c956c 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -1,12 +1,8 @@ -/* - * 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. - */ - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") } + description = "Commons math binding for kmath" dependencies { diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index a28226d90..ea74df646 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index f1a2ed40f..92a5f419d 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt index b5e652784..980819364 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt @@ -1,3 +1,8 @@ +/* + * 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.expressions import space.kscience.kmath.misc.Symbol diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index 531bbd935..1546e7d96 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index ca678bc0e..622b8f8da 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index 121498ce8..9b6e593b2 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index af3ebaed9..2167726c0 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index 576c073c3..f627beec9 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") @@ -16,4 +11,4 @@ dependencies { readme { maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE -} \ No newline at end of file +} diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 50c317324..288c61a51 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -14,4 +9,4 @@ readme { description = """ An API and basic implementation for arranging objects in a continous memory block. """.trimIndent() -} \ No newline at end of file +} diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 2b549f919..bc61060db 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index 8522cf92f..e8f629f7a 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 747fe0252..232bd1388 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") diff --git a/settings.gradle.kts b/settings.gradle.kts index 553367a22..ca36168e1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - pluginManagement { repositories { mavenLocal() From cfa9077e29f16417878eb8ebca54ce973da19741 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 21 Apr 2021 19:50:33 +0700 Subject: [PATCH 123/211] Move AST rendering tests to common --- .../kmath/ast/rendering/TestFeatures.kt | 100 ++++++++++++++++++ .../kscisnce/kmath/ast/rendering/TestLatex.kt | 73 +++++++++++++ .../kmath/ast/rendering/TestMathML.kt | 92 ++++++++++++++++ .../kmath/ast/rendering/TestStages.kt | 33 ++++++ .../kscisnce/kmath/ast/rendering/TestUtils.kt | 46 ++++++++ 5 files changed, 344 insertions(+) create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt new file mode 100644 index 000000000..1584293ce --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt @@ -0,0 +1,100 @@ +/* + * 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.ast.rendering + +import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import space.kscience.kmath.expressions.MST.Numeric +import kotlin.test.Test + +internal class TestFeatures { + @Test + fun printSymbolic() = testLatex("x", "x") + + @Test + fun printNumeric() { + val num = object : Number() { + override fun toByte(): Byte = throw UnsupportedOperationException() + override fun toChar(): Char = throw UnsupportedOperationException() + override fun toDouble(): Double = throw UnsupportedOperationException() + override fun toFloat(): Float = throw UnsupportedOperationException() + override fun toInt(): Int = throw UnsupportedOperationException() + override fun toLong(): Long = throw UnsupportedOperationException() + override fun toShort(): Short = throw UnsupportedOperationException() + override fun toString(): String = "foo" + } + + testLatex(Numeric(num), "foo") + } + + @Test + fun prettyPrintFloats() { + testLatex(Numeric(Double.NaN), "NaN") + testLatex(Numeric(Double.POSITIVE_INFINITY), "\\infty") + testLatex(Numeric(Double.NEGATIVE_INFINITY), "-\\infty") + testLatex(Numeric(1.0), "1") + testLatex(Numeric(-1.0), "-1") + testLatex(Numeric(1.42), "1.42") + testLatex(Numeric(-1.42), "-1.42") + testLatex(Numeric(1.1e10), "1.1\\times10^{10}") + testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}") + testLatex(Numeric(-1.1e-10), "-1.1\\times10^{-10}") + testLatex(Numeric(-1.1e10), "-1.1\\times10^{10}") + } + + @Test + fun prettyPrintIntegers() { + testLatex(Numeric(42), "42") + testLatex(Numeric(-42), "-42") + } + + @Test + fun prettyPrintPi() { + testLatex("pi", "\\pi") + } + + @Test + fun binaryPlus() = testLatex("2+2", "2+2") + + @Test + fun binaryMinus() = testLatex("2-2", "2-2") + + @Test + fun fraction() = testLatex("2/2", "\\frac{2}{2}") + + @Test + fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)") + + @Test + fun unaryOperator() = testLatex("f(x)", "\\operatorname{f}\\,\\left(x\\right)") + + @Test + fun power() = testLatex("x^y", "x^{y}") + + @Test + fun squareRoot() = testLatex("sqrt(x)", "\\sqrt{x}") + + @Test + fun exponential() = testLatex("exp(x)", "e^{x}") + + @Test + fun multiplication() = testLatex("x*1", "x\\times1") + + @Test + fun inverseTrigonometry() { + testLatex("asin(x)", "\\operatorname{sin}^{-1}\\,\\left(x\\right)") + testLatex("asinh(x)", "\\operatorname{sinh}^{-1}\\,\\left(x\\right)") + testLatex("acos(x)", "\\operatorname{cos}^{-1}\\,\\left(x\\right)") + testLatex("acosh(x)", "\\operatorname{cosh}^{-1}\\,\\left(x\\right)") + testLatex("atan(x)", "\\operatorname{tan}^{-1}\\,\\left(x\\right)") + testLatex("atanh(x)", "\\operatorname{tanh}^{-1}\\,\\left(x\\right)") + } + +// @Test +// fun unaryPlus() { +// testLatex("+1", "+1") +// testLatex("+1", "++1") +// } +} diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt new file mode 100644 index 000000000..6322df25d --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt @@ -0,0 +1,73 @@ +/* + * 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.ast.rendering + +import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.operations.GroupOperations +import kotlin.test.Test + +internal class TestLatex { + @Test + fun number() = testLatex("42", "42") + + @Test + fun symbol() = testLatex("x", "x") + + @Test + fun operatorName() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") + + @Test + fun specialSymbol() { + testLatex(MST.Numeric(Double.POSITIVE_INFINITY), "\\infty") + testLatex("pi", "\\pi") + } + + @Test + fun operand() { + testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") + testLatex("1+1", "1+1") + } + + @Test + fun unaryOperator() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") + + @Test + fun unaryPlus() = testLatex(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1") + + @Test + fun unaryMinus() = testLatex("-x", "-x") + + @Test + fun radical() = testLatex("sqrt(x)", "\\sqrt{x}") + + @Test + fun superscript() = testLatex("x^y", "x^{y}") + + @Test + fun subscript() = testLatex(SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), "x_{123}") + + @Test + fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)") + + @Test + fun binaryPlus() = testLatex("x+x", "x+x") + + @Test + fun binaryMinus() = testLatex("x-x", "x-x") + + @Test + fun fraction() = testLatex("x/x", "\\frac{x}{x}") + + @Test + fun radicalWithIndex() = testLatex(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), "\\sqrt[x]{y}") + + @Test + fun multiplication() { + testLatex("x*1", "x\\times1") + testLatex("1*x", "1\\,x") + } +} diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt new file mode 100644 index 000000000..2d7bfad19 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt @@ -0,0 +1,92 @@ +/* + * 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.ast.rendering + +import space.kscience.kmath.ast.rendering.TestUtils.testMathML +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.operations.GroupOperations +import kotlin.test.Test + +internal class TestMathML { + @Test + fun number() = testMathML("42", "42") + + @Test + fun symbol() = testMathML("x", "x") + + @Test + fun operatorName() = testMathML( + "sin(1)", + "sin1", + ) + + @Test + fun specialSymbol() { + testMathML(MST.Numeric(Double.POSITIVE_INFINITY), "") + testMathML("pi", "π") + } + + @Test + fun operand() { + testMathML( + "sin(1)", + "sin1", + ) + + testMathML("1+1", "1+1") + } + + @Test + fun unaryOperator() = testMathML( + "sin(1)", + "sin1", + ) + + @Test + fun unaryPlus() = + testMathML(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1") + + @Test + fun unaryMinus() = testMathML("-x", "-x") + + @Test + fun radical() = testMathML("sqrt(x)", "x") + + @Test + fun superscript() = testMathML("x^y", "xy") + + @Test + fun subscript() = testMathML( + SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), + "x123", + ) + + @Test + fun binaryOperator() = testMathML( + "f(x, y)", + "fx,y", + ) + + @Test + fun binaryPlus() = testMathML("x+x", "x+x") + + @Test + fun binaryMinus() = testMathML("x-x", "x-x") + + @Test + fun fraction() = testMathML("x/x", "xx") + + @Test + fun radicalWithIndex() = + testMathML(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), + "yx") + + @Test + fun multiplication() { + testMathML("x*1", "x×1") + testMathML("1*x", "1x") + } +} diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt new file mode 100644 index 000000000..a4017fdb4 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt @@ -0,0 +1,33 @@ +/* + * 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.ast.rendering + +import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import kotlin.test.Test + +internal class TestStages { + @Test + fun betterMultiplication() { + testLatex("a*1", "a\\times1") + testLatex("1*(2/3)", "1\\times\\left(\\frac{2}{3}\\right)") + testLatex("1*1", "1\\times1") + testLatex("2e10", "2\\times10^{10}") + testLatex("2*x", "2\\,x") + testLatex("2*(x+1)", "2\\,\\left(x+1\\right)") + testLatex("x*y", "x\\,y") + } + + @Test + fun parentheses() { + testLatex("(x+1)", "x+1") + testLatex("x*x*x", "x\\,x\\,x") + testLatex("(x+x)*x", "\\left(x+x\\right)\\,x") + testLatex("x+x*x", "x+x\\,x") + testLatex("x+x^x*x+x", "x+x^{x}\\,x+x") + testLatex("(x+x)^x+x*x", "\\left(x+x\\right)^{x}+x\\,x") + testLatex("x^(x+x)", "x^{x+x}") + } +} diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt new file mode 100644 index 000000000..7c9400532 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt @@ -0,0 +1,46 @@ +/* + * 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.ast.rendering + +import space.kscience.kmath.ast.parseMath +import space.kscience.kmath.expressions.MST +import kotlin.test.assertEquals + +internal object TestUtils { + private fun mathSyntax(mst: MST) = FeaturedMathRendererWithPostProcess.Default.render(mst) + private fun latex(mst: MST) = LatexSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst)) + private fun mathML(mst: MST) = MathMLSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst)) + + internal fun testLatex(mst: MST, expectedLatex: String) = assertEquals( + expected = expectedLatex, + actual = latex(mst), + ) + + internal fun testLatex(expression: String, expectedLatex: String) = assertEquals( + expected = expectedLatex, + actual = latex(expression.parseMath()), + ) + + internal fun testLatex(expression: MathSyntax, expectedLatex: String) = assertEquals( + expected = expectedLatex, + actual = LatexSyntaxRenderer.renderWithStringBuilder(expression), + ) + + internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals( + expected = "$expectedMathML", + actual = mathML(mst), + ) + + internal fun testMathML(expression: String, expectedMathML: String) = assertEquals( + expected = "$expectedMathML", + actual = mathML(expression.parseMath()), + ) + + internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals( + expected = "$expectedMathML", + actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression), + ) +} From 488f5f00087ba45ea137a1ee527468cf4dd40dbc Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 8 Apr 2021 00:52:27 +0700 Subject: [PATCH 124/211] Redesign exponential function rendering --- .../ast/rendering/LatexSyntaxRenderer.kt | 9 + .../ast/rendering/MathMLSyntaxRenderer.kt | 13 + .../kmath/ast/rendering/MathRenderer.kt | 3 +- .../kmath/ast/rendering/MathSyntax.kt | 18 ++ .../kscience/kmath/ast/rendering/features.kt | 24 +- .../ast/rendering/multiplatformToString.kt | 9 + .../kscience/kmath/ast/rendering/stages.kt | 293 ++++++++++-------- .../kmath/ast/ParserPrecedenceTest.kt | 2 +- .../kmath/ast/ParserTest.kt | 3 +- .../kmath/ast/rendering/TestFeatures.kt | 16 + .../kmath/ast/rendering/TestLatex.kt | 0 .../kmath/ast/rendering/TestMathML.kt | 0 .../kmath/ast/rendering/TestStages.kt | 7 + .../kmath/ast/rendering/TestUtils.kt | 0 .../ast/rendering/multiplatformToString.kt | 18 ++ .../ast/rendering/multiplatformToString.kt | 9 + 16 files changed, 283 insertions(+), 141 deletions(-) create mode 100644 kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/ParserPrecedenceTest.kt (97%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/ParserTest.kt (95%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestFeatures.kt (81%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestLatex.kt (100%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestMathML.kt (100%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestStages.kt (81%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestUtils.kt (100%) create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt create mode 100644 kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt index 34230f3c8..1c82bd6e7 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -71,6 +71,15 @@ public object LatexSyntaxRenderer : SyntaxRenderer { append('}') } + is ExponentSyntax -> if (node.useOperatorForm) { + append("\\operatorname{exp}\\,") + render(node.operand) + } else { + append("e^{") + render(node.operand) + append('}') + } + is SuperscriptSyntax -> { render(node.left) append("^{") diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index f7487a356..decd4ba46 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -82,6 +82,19 @@ public object MathMLSyntaxRenderer : SyntaxRenderer { is RadicalSyntax -> tag("msqrt") { render(node.operand) } + is ExponentSyntax -> if (node.useOperatorForm) { + tag("mo") { append("exp") } + tag("mspace", "width" to "0.167em") + render(node.operand) + } else { + tag("msup") { + tag("mrow") { + tag("mi") { append("e") } + } + tag("mrow") { render(node.operand) } + } + } + is SuperscriptSyntax -> tag("msup") { tag("mrow") { render(node.left) } tag("mrow") { render(node.right) } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index 891e8f05b..9df2c54dd 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -83,7 +83,7 @@ public open class FeaturedMathRendererWithPostProcess( Fraction.Default, Power.Default, SquareRoot.Default, - Exponential.Default, + Exponent.Default, InverseTrigonometricOperations.Default, // Fallback option for unknown operations - printing them as operator @@ -100,6 +100,7 @@ public open class FeaturedMathRendererWithPostProcess( PrintSymbolic, ), listOf( + BetterExponent, SimplifyParentheses.Default, BetterMultiplication, ), diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt index 069e56c71..6a46bf535 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -189,6 +189,24 @@ public data class RadicalSyntax( } } +/** + * Represents exponential function. + * + * @property operand The argument of function. + * @property useOperatorForm `true` if operator form is used (*exp (x)*), `false` if exponentiation form is used + * (*ex*). + * @author Iaroslav Postovalov + */ +public data class ExponentSyntax( + public override val operation: String, + public override val operand: OperandSyntax, + public var useOperatorForm: Boolean, +) : UnarySyntax() { + init { + operand.parent = this + } +} + /** * Represents a syntax node with superscript (usually, for exponentiation). * diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index 5d6c7bb0a..c09282bb6 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -56,10 +56,14 @@ private fun printSignedNumberString(s: String): MathSyntax { public class PrettyPrintFloats(public val types: Set>) : RenderFeature { public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { if (node !is MST.Numeric || node.value::class !in types) return null - val toString = node.value.toString().removeSuffix(".0") + val toString = when (val v = node.value) { + is Float -> v.multiplatformToString() + is Double -> v.multiplatformToString() + else -> v.toString() + }.removeSuffix(".0") - if ('E' in toString) { - val (beforeE, afterE) = toString.split('E') + if (toString.contains('E', ignoreCase = true)) { + val (beforeE, afterE) = toString.split('E', ignoreCase = true) val significand = beforeE.toDouble().toString().removeSuffix(".0") val exponent = afterE.toDouble().toString().removeSuffix(".0") @@ -108,9 +112,7 @@ public class PrettyPrintFloats(public val types: Set>) : Rend */ public class PrettyPrintIntegers(public val types: Set>) : RenderFeature { public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Numeric || node.value::class !in types) - return null - + if (node !is MST.Numeric || node.value::class !in types) return null return printSignedNumberString(node.value.toString()) } @@ -282,15 +284,15 @@ public class SquareRoot(operations: Collection?) : Unary(operations) { } } -public class Exponential(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = SuperscriptSyntax( +public class Exponent(operations: Collection?) : Unary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax( operation = node.operation, - left = SymbolSyntax(string = "e"), - right = parent.render(node.value), + operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), + useOperatorForm = true, ) public companion object { - public val Default: Exponential = Exponential(setOf(ExponentialOperations.EXP_OPERATION)) + public val Default: Exponent = Exponent(setOf(ExponentialOperations.EXP_OPERATION)) } } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt new file mode 100644 index 000000000..291399cee --- /dev/null +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -0,0 +1,9 @@ +/* + * 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.ast.rendering + +internal expect fun Double.multiplatformToString(): String +internal expect fun Float.multiplatformToString(): String diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt index 0ebb41b28..a08f089f1 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt @@ -16,69 +16,110 @@ import space.kscience.kmath.operations.RingOperations * @author Iaroslav Postovalov */ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage { - public override fun perform(node: MathSyntax) { - when (node) { - is NumberSyntax -> Unit - is SymbolSyntax -> Unit - is OperatorNameSyntax -> Unit - is SpecialSymbolSyntax -> Unit - is OperandSyntax -> perform(node.operand) + public override fun perform(node: MathSyntax): Unit = when (node) { + is NumberSyntax -> Unit + is SymbolSyntax -> Unit + is OperatorNameSyntax -> Unit + is SpecialSymbolSyntax -> Unit + is OperandSyntax -> perform(node.operand) - is UnaryOperatorSyntax -> { - perform(node.prefix) - perform(node.operand) - } - - is UnaryPlusSyntax -> perform(node.operand) - is UnaryMinusSyntax -> perform(node.operand) - is RadicalSyntax -> perform(node.operand) - - is SuperscriptSyntax -> { - perform(node.left) - perform(node.right) - } - - is SubscriptSyntax -> { - perform(node.left) - perform(node.right) - } - - is BinaryOperatorSyntax -> { - perform(node.prefix) - perform(node.left) - perform(node.right) - } - - is BinaryPlusSyntax -> { - perform(node.left) - perform(node.right) - } - - is BinaryMinusSyntax -> { - perform(node.left) - perform(node.right) - } - - is FractionSyntax -> { - perform(node.left) - perform(node.right) - } - - is RadicalWithIndexSyntax -> { - perform(node.left) - perform(node.right) - } - - is MultiplicationSyntax -> { - node.times = node.right.operand is NumberSyntax && !node.right.parentheses - || node.left.operand is NumberSyntax && node.right.operand is FractionSyntax - || node.left.operand is NumberSyntax && node.right.operand is NumberSyntax - || node.left.operand is NumberSyntax && node.right.operand is SuperscriptSyntax && node.right.operand.left is NumberSyntax - - perform(node.left) - perform(node.right) - } + is UnaryOperatorSyntax -> { + perform(node.prefix) + perform(node.operand) } + + is UnaryPlusSyntax -> perform(node.operand) + is UnaryMinusSyntax -> perform(node.operand) + is RadicalSyntax -> perform(node.operand) + is ExponentSyntax -> perform(node.operand) + + is SuperscriptSyntax -> { + perform(node.left) + perform(node.right) + } + + is SubscriptSyntax -> { + perform(node.left) + perform(node.right) + } + + is BinaryOperatorSyntax -> { + perform(node.prefix) + perform(node.left) + perform(node.right) + } + + is BinaryPlusSyntax -> { + perform(node.left) + perform(node.right) + } + + is BinaryMinusSyntax -> { + perform(node.left) + perform(node.right) + } + + is FractionSyntax -> { + perform(node.left) + perform(node.right) + } + + is RadicalWithIndexSyntax -> { + perform(node.left) + perform(node.right) + } + + is MultiplicationSyntax -> { + node.times = node.right.operand is NumberSyntax && !node.right.parentheses + || node.left.operand is NumberSyntax && node.right.operand is FractionSyntax + || node.left.operand is NumberSyntax && node.right.operand is NumberSyntax + || node.left.operand is NumberSyntax && node.right.operand is SuperscriptSyntax && node.right.operand.left is NumberSyntax + + perform(node.left) + perform(node.right) + } + } +} + + +/** + * Applies [ExponentSyntax.useOperatorForm] to [ExponentSyntax] when the operand contains a fraction, a + * superscript or a subscript to improve readability. + * + * @author Iaroslav Postovalov + */ +public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage { + private fun perform0(node: MathSyntax): Boolean { + return when (node) { + is NumberSyntax -> false + is SymbolSyntax -> false + is OperatorNameSyntax -> false + is SpecialSymbolSyntax -> false + is OperandSyntax -> perform0(node.operand) + is UnaryOperatorSyntax -> perform0(node.prefix) || perform0(node.operand) + is UnaryPlusSyntax -> perform0(node.operand) + is UnaryMinusSyntax -> perform0(node.operand) + is RadicalSyntax -> perform0(node.operand) + + is ExponentSyntax -> { + val r = perform0(node.operand) + node.useOperatorForm = r + r + } + + is SuperscriptSyntax -> true + is SubscriptSyntax -> true + is BinaryOperatorSyntax -> perform0(node.prefix) || perform0(node.left) || perform0(node.right) + is BinaryPlusSyntax -> perform0(node.left) || perform0(node.right) + is BinaryMinusSyntax -> perform0(node.left) || perform0(node.right) + is FractionSyntax -> true + is RadicalWithIndexSyntax -> perform0(node.left) || perform0(node.right) + is MultiplicationSyntax -> perform0(node.left) || perform0(node.right) + } + } + + public override fun perform(node: MathSyntax) { + perform0(node) } } @@ -90,89 +131,89 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro */ public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) : FeaturedMathRendererWithPostProcess.PostProcessStage { - public override fun perform(node: MathSyntax) { - when (node) { - is NumberSyntax -> Unit - is SymbolSyntax -> Unit - is OperatorNameSyntax -> Unit - is SpecialSymbolSyntax -> Unit + public override fun perform(node: MathSyntax): Unit = when (node) { + is NumberSyntax -> Unit + is SymbolSyntax -> Unit + is OperatorNameSyntax -> Unit + is SpecialSymbolSyntax -> Unit - is OperandSyntax -> { - val isRightOfSuperscript = - (node.parent is SuperscriptSyntax) && (node.parent as SuperscriptSyntax).right === node + is OperandSyntax -> { + val isRightOfSuperscript = + (node.parent is SuperscriptSyntax) && (node.parent as SuperscriptSyntax).right === node - val precedence = precedenceFunction(node.operand) + val precedence = precedenceFunction(node.operand) - val needParenthesesByPrecedence = when (val parent = node.parent) { - null -> false + val needParenthesesByPrecedence = when (val parent = node.parent) { + null -> false - is BinarySyntax -> { - val parentPrecedence = precedenceFunction(parent) + is BinarySyntax -> { + val parentPrecedence = precedenceFunction(parent) - parentPrecedence < precedence || - parentPrecedence == precedence && parentPrecedence != 0 && node === parent.right - } - - else -> precedence > precedenceFunction(parent) + parentPrecedence < precedence || + parentPrecedence == precedence && parentPrecedence != 0 && node === parent.right } - node.parentheses = !isRightOfSuperscript - && (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax) - - perform(node.operand) + else -> precedence > precedenceFunction(parent) } - is UnaryOperatorSyntax -> { - perform(node.prefix) - perform(node.operand) - } + val isInsideExpOperator = + node.parent is ExponentSyntax && (node.parent as ExponentSyntax).useOperatorForm - is UnaryPlusSyntax -> perform(node.operand) - is UnaryMinusSyntax -> { - perform(node.operand) - } - is RadicalSyntax -> perform(node.operand) + node.parentheses = !isRightOfSuperscript + && (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax || isInsideExpOperator) - is SuperscriptSyntax -> { - perform(node.left) - perform(node.right) - } + perform(node.operand) + } - is SubscriptSyntax -> { - perform(node.left) - perform(node.right) - } + is UnaryOperatorSyntax -> { + perform(node.prefix) + perform(node.operand) + } - is BinaryOperatorSyntax -> { - perform(node.prefix) - perform(node.left) - perform(node.right) - } + is UnaryPlusSyntax -> perform(node.operand) + is UnaryMinusSyntax -> perform(node.operand) + is RadicalSyntax -> perform(node.operand) + is ExponentSyntax -> perform(node.operand) - is BinaryPlusSyntax -> { - perform(node.left) - perform(node.right) - } + is SuperscriptSyntax -> { + perform(node.left) + perform(node.right) + } - is BinaryMinusSyntax -> { - perform(node.left) - perform(node.right) - } + is SubscriptSyntax -> { + perform(node.left) + perform(node.right) + } - is FractionSyntax -> { - perform(node.left) - perform(node.right) - } + is BinaryOperatorSyntax -> { + perform(node.prefix) + perform(node.left) + perform(node.right) + } - is MultiplicationSyntax -> { - perform(node.left) - perform(node.right) - } + is BinaryPlusSyntax -> { + perform(node.left) + perform(node.right) + } - is RadicalWithIndexSyntax -> { - perform(node.left) - perform(node.right) - } + is BinaryMinusSyntax -> { + perform(node.left) + perform(node.right) + } + + is FractionSyntax -> { + perform(node.left) + perform(node.right) + } + + is MultiplicationSyntax -> { + perform(node.left) + perform(node.right) + } + + is RadicalWithIndexSyntax -> { + perform(node.left) + perform(node.right) } } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt similarity index 97% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt index 14ceefc30..ca3a95bc8 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt @@ -3,7 +3,7 @@ * 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.kscisnce.kmath.ast +package space.kscience.kmath.ast import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.evaluate diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt similarity index 95% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt index a0dcba9c0..185659a1f 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt @@ -3,9 +3,8 @@ * 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.kscisnce.kmath.ast +package space.kscience.kmath.ast -import space.kscience.kmath.ast.parseMath import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.expressions.evaluate diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt similarity index 81% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt index 1584293ce..1ab20ed85 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt @@ -42,6 +42,22 @@ internal class TestFeatures { testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}") testLatex(Numeric(-1.1e-10), "-1.1\\times10^{-10}") testLatex(Numeric(-1.1e10), "-1.1\\times10^{10}") + testLatex(Numeric(0.001), "0.001") + testLatex(Numeric(0.0000001), "1\\times10^{-7}") + + testLatex(Numeric(Float.NaN), "NaN") + testLatex(Numeric(Float.POSITIVE_INFINITY), "\\infty") + testLatex(Numeric(Float.NEGATIVE_INFINITY), "-\\infty") + testLatex(Numeric(1.0f), "1") + testLatex(Numeric(-1.0f), "-1") + testLatex(Numeric(1.42f), "1.42") + testLatex(Numeric(-1.42f), "-1.42") + testLatex(Numeric(1e10f), "1\\times10^{10}") + testLatex(Numeric(1e-10f), "1\\times10^{-10}") + testLatex(Numeric(-1e-10f), "-1\\times10^{-10}") + testLatex(Numeric(-1e10f), "-1\\times10^{10}") + testLatex(Numeric(0.001f), "0.001") + testLatex(Numeric(0.0000001f), "1\\times10^{-7}") } @Test diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt similarity index 100% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt similarity index 100% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt similarity index 81% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt index a4017fdb4..599e43eb2 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt @@ -30,4 +30,11 @@ internal class TestStages { testLatex("(x+x)^x+x*x", "\\left(x+x\\right)^{x}+x\\,x") testLatex("x^(x+x)", "x^{x+x}") } + + @Test + fun exponent() { + testLatex("exp(x)", "e^{x}") + testLatex("exp(x/2)", "\\operatorname{exp}\\,\\left(\\frac{x}{2}\\right)") + testLatex("exp(x^2)", "\\operatorname{exp}\\,\\left(x^{2}\\right)") + } } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt similarity index 100% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt new file mode 100644 index 000000000..521907d2c --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -0,0 +1,18 @@ +/* + * 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.ast.rendering + +internal actual fun Double.multiplatformToString(): String { + val d = this + if (d >= 1e7 || d <= -1e7) return js("d.toExponential()") as String + return toString() +} + +internal actual fun Float.multiplatformToString(): String { + val d = this + if (d >= 1e7f || d <= -1e7f) return js("d.toExponential()") as String + return toString() +} diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt new file mode 100644 index 000000000..556adbe7d --- /dev/null +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -0,0 +1,9 @@ +/* + * 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.ast.rendering + +internal actual fun Double.multiplatformToString(): String = toString() +internal actual fun Float.multiplatformToString(): String = toString() From cc11df617489c6d3d8105b72cf5a472af1c90c01 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 21 Apr 2021 19:51:34 +0100 Subject: [PATCH 125/211] Casting receiver --- .../kmath/tensors/AnalyticTensorAlgebra.kt | 38 +-- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 21 +- .../kscience/kmath/tensors/TensorAlgebra.kt | 50 ++-- .../tensors/TensorPartialDivisionAlgebra.kt | 12 +- .../core/BroadcastDoubleTensorAlgebra.kt | 57 ++-- .../kmath/tensors/core/BufferedTensor.kt | 48 ++- .../core/DoubleAnalyticTensorAlgebra.kt | 37 +-- .../core/DoubleLinearOpsTensorAlgebra.kt | 65 ++-- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 279 +++++++++--------- .../kscience/kmath/tensors/core/checks.kt | 41 +-- .../kscience/kmath/tensors/core/linutils.kt | 4 +- .../kscience/kmath/tensors/core/utils.kt | 4 +- 12 files changed, 326 insertions(+), 330 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt index fa1de81fa..2a8b228f4 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt @@ -1,58 +1,58 @@ package space.kscience.kmath.tensors -public interface AnalyticTensorAlgebra> : - TensorPartialDivisionAlgebra { +public interface AnalyticTensorAlgebra : + TensorPartialDivisionAlgebra { //https://pytorch.org/docs/stable/generated/torch.exp.html - public fun TensorType.exp(): TensorType + public fun TensorStructure.exp(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.log.html - public fun TensorType.log(): TensorType + public fun TensorStructure.log(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.sqrt.html - public fun TensorType.sqrt(): TensorType + public fun TensorStructure.sqrt(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos - public fun TensorType.cos(): TensorType + public fun TensorStructure.cos(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.acos - public fun TensorType.acos(): TensorType + public fun TensorStructure.acos(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.cosh - public fun TensorType.cosh(): TensorType + public fun TensorStructure.cosh(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.acosh - public fun TensorType.acosh(): TensorType + public fun TensorStructure.acosh(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sin - public fun TensorType.sin(): TensorType + public fun TensorStructure.sin(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asin - public fun TensorType.asin(): TensorType + public fun TensorStructure.asin(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sinh - public fun TensorType.sinh(): TensorType + public fun TensorStructure.sinh(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asinh - public fun TensorType.asinh(): TensorType + public fun TensorStructure.asinh(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.tan - public fun TensorType.tan(): TensorType + public fun TensorStructure.tan(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.atan - public fun TensorType.atan(): TensorType + public fun TensorStructure.atan(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.tanh - public fun TensorType.tanh(): TensorType + public fun TensorStructure.tanh(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.atanh - public fun TensorType.atanh(): TensorType + public fun TensorStructure.atanh(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.ceil.html#torch.ceil - public fun TensorType.ceil(): TensorType + public fun TensorStructure.ceil(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor - public fun TensorType.floor(): TensorType + public fun TensorStructure.floor(): TensorStructure } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index 87c459f35..8ca8945a5 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -1,31 +1,32 @@ package space.kscience.kmath.tensors -public interface LinearOpsTensorAlgebra, IndexTensorType : TensorStructure> : - TensorPartialDivisionAlgebra { +public interface LinearOpsTensorAlgebra : + TensorPartialDivisionAlgebra { //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det - public fun TensorType.det(): TensorType + public fun TensorStructure.det(): TensorStructure //https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv - public fun TensorType.inv(): TensorType + public fun TensorStructure.inv(): TensorStructure //https://pytorch.org/docs/stable/linalg.html#torch.linalg.cholesky - public fun TensorType.cholesky(): TensorType + public fun TensorStructure.cholesky(): TensorStructure //https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr - public fun TensorType.qr(): Pair + public fun TensorStructure.qr(): Pair, TensorStructure> //https://pytorch.org/docs/stable/generated/torch.lu.html - public fun TensorType.lu(): Pair + public fun TensorStructure.lu(): Pair, TensorStructure> //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun luPivot(luTensor: TensorType, pivotsTensor: IndexTensorType): Triple + public fun luPivot(luTensor: TensorStructure, pivotsTensor: TensorStructure): + Triple, TensorStructure, TensorStructure> //https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd - public fun TensorType.svd(): Triple + public fun TensorStructure.svd(): Triple, TensorStructure, TensorStructure> //https://pytorch.org/docs/stable/generated/torch.symeig.html - public fun TensorType.symEig(): Pair + public fun TensorStructure.symEig(): Pair, TensorStructure> } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 8fd1cf2ed..f64d49dd8 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -1,46 +1,46 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Algebra_over_Ring -public interface TensorAlgebra> { +public interface TensorAlgebra { - public fun TensorType.value(): T + public fun TensorStructure.value(): T - public operator fun T.plus(other: TensorType): TensorType - public operator fun TensorType.plus(value: T): TensorType - public operator fun TensorType.plus(other: TensorType): TensorType - public operator fun TensorType.plusAssign(value: T): Unit - public operator fun TensorType.plusAssign(other: TensorType): Unit + public operator fun T.plus(other: TensorStructure): TensorStructure + public operator fun TensorStructure.plus(value: T): TensorStructure + public operator fun TensorStructure.plus(other: TensorStructure): TensorStructure + public operator fun TensorStructure.plusAssign(value: T): Unit + public operator fun TensorStructure.plusAssign(other: TensorStructure): Unit - public operator fun T.minus(other: TensorType): TensorType - public operator fun TensorType.minus(value: T): TensorType - public operator fun TensorType.minus(other: TensorType): TensorType - public operator fun TensorType.minusAssign(value: T): Unit - public operator fun TensorType.minusAssign(other: TensorType): Unit + public operator fun T.minus(other: TensorStructure): TensorStructure + public operator fun TensorStructure.minus(value: T): TensorStructure + public operator fun TensorStructure.minus(other: TensorStructure): TensorStructure + public operator fun TensorStructure.minusAssign(value: T): Unit + public operator fun TensorStructure.minusAssign(other: TensorStructure): Unit - public operator fun T.times(other: TensorType): TensorType - public operator fun TensorType.times(value: T): TensorType - public operator fun TensorType.times(other: TensorType): TensorType - public operator fun TensorType.timesAssign(value: T): Unit - public operator fun TensorType.timesAssign(other: TensorType): Unit - public operator fun TensorType.unaryMinus(): TensorType + public operator fun T.times(other: TensorStructure): TensorStructure + public operator fun TensorStructure.times(value: T): TensorStructure + public operator fun TensorStructure.times(other: TensorStructure): TensorStructure + public operator fun TensorStructure.timesAssign(value: T): Unit + public operator fun TensorStructure.timesAssign(other: TensorStructure): Unit + public operator fun TensorStructure.unaryMinus(): TensorStructure //https://pytorch.org/cppdocs/notes/tensor_indexing.html - public operator fun TensorType.get(i: Int): TensorType + public operator fun TensorStructure.get(i: Int): TensorStructure //https://pytorch.org/docs/stable/generated/torch.transpose.html - public fun TensorType.transpose(i: Int = -2, j: Int = -1): TensorType + public fun TensorStructure.transpose(i: Int = -2, j: Int = -1): TensorStructure //https://pytorch.org/docs/stable/tensor_view.html - public fun TensorType.view(shape: IntArray): TensorType - public fun TensorType.viewAs(other: TensorType): TensorType + public fun TensorStructure.view(shape: IntArray): TensorStructure + public fun TensorStructure.viewAs(other: TensorStructure): TensorStructure //https://pytorch.org/docs/stable/generated/torch.matmul.html - public infix fun TensorType.dot(other: TensorType): TensorType + public infix fun TensorStructure.dot(other: TensorStructure): TensorStructure //https://pytorch.org/docs/stable/generated/torch.diag_embed.html public fun diagonalEmbedding( - diagonalEntries: TensorType, + diagonalEntries: TensorStructure, offset: Int = 0, dim1: Int = -2, dim2: Int = -1 - ): TensorType + ): TensorStructure } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt index 0b9079967..b37ac6b6e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -1,10 +1,10 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Division_Algebra -public interface TensorPartialDivisionAlgebra> : - TensorAlgebra { - public operator fun TensorType.div(value: T): TensorType - public operator fun TensorType.div(other: TensorType): TensorType - public operator fun TensorType.divAssign(value: T) - public operator fun TensorType.divAssign(other: TensorType) +public interface TensorPartialDivisionAlgebra : + TensorAlgebra { + public operator fun TensorStructure.div(value: T): TensorStructure + public operator fun TensorStructure.div(other: TensorStructure): TensorStructure + public operator fun TensorStructure.divAssign(value: T) + public operator fun TensorStructure.divAssign(other: TensorStructure) } 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 f315f6b51..53c385197 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 @@ -1,11 +1,12 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.tensors.TensorStructure import kotlin.math.max public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { - override fun DoubleTensor.plus(other: DoubleTensor): DoubleTensor { - val broadcast = broadcastTensors(this, other) + override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> @@ -14,16 +15,16 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun DoubleTensor.plusAssign(other: DoubleTensor) { - val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] += - newOther.buffer.array()[this.bufferStart + i] + override fun TensorStructure.plusAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] += + newOther.buffer.array()[tensor.bufferStart + i] } } - override fun DoubleTensor.minus(other: DoubleTensor): DoubleTensor { - val broadcast = broadcastTensors(this, other) + override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> @@ -32,16 +33,16 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun DoubleTensor.minusAssign(other: DoubleTensor) { - val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] -= - newOther.buffer.array()[this.bufferStart + i] + override fun TensorStructure.minusAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] -= + newOther.buffer.array()[tensor.bufferStart + i] } } - override fun DoubleTensor.times(other: DoubleTensor): DoubleTensor { - val broadcast = broadcastTensors(this, other) + override fun TensorStructure.times(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> @@ -51,16 +52,16 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun DoubleTensor.timesAssign(other: DoubleTensor) { - val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] *= - newOther.buffer.array()[this.bufferStart + i] + override fun TensorStructure.timesAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] *= + newOther.buffer.array()[tensor.bufferStart + i] } } - override fun DoubleTensor.div(other: DoubleTensor): DoubleTensor { - val broadcast = broadcastTensors(this, other) + override fun TensorStructure.div(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> @@ -70,11 +71,11 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun DoubleTensor.divAssign(other: DoubleTensor) { - val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] /= - newOther.buffer.array()[this.bufferStart + i] + override fun TensorStructure.divAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] /= + newOther.buffer.array()[tensor.bufferStart + i] } } 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 9e393f1a8..2b61e10b2 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 @@ -6,13 +6,13 @@ import space.kscience.kmath.tensors.TensorStructure public open class BufferedTensor( override val shape: IntArray, - public val buffer: MutableBuffer, + internal val buffer: MutableBuffer, internal val bufferStart: Int ) : TensorStructure { public val linearStructure: TensorLinearStructure get() = TensorLinearStructure(shape) - public val numel: Int + public val numElements: Int get() = linearStructure.size override fun get(index: IntArray): T = buffer[bufferStart + linearStructure.offset(index)] @@ -41,26 +41,6 @@ public class IntTensor internal constructor( this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) } -public class LongTensor internal constructor( - shape: IntArray, - buffer: LongArray, - offset: Int = 0 -) : BufferedTensor(shape, LongBuffer(buffer), offset) -{ - internal constructor(bufferedTensor: BufferedTensor): - this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) -} - -public class FloatTensor internal constructor( - shape: IntArray, - buffer: FloatArray, - offset: Int = 0 -) : BufferedTensor(shape, FloatBuffer(buffer), offset) -{ - internal constructor(bufferedTensor: BufferedTensor): - this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) -} - public class DoubleTensor internal constructor( shape: IntArray, buffer: DoubleArray, @@ -74,7 +54,23 @@ public class DoubleTensor internal constructor( } -internal fun BufferedTensor.asTensor(): IntTensor = IntTensor(this) -internal fun BufferedTensor.asTensor(): LongTensor = LongTensor(this) -internal fun BufferedTensor.asTensor(): FloatTensor = FloatTensor(this) -internal fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this) +internal inline fun BufferedTensor.asTensor(): IntTensor = IntTensor(this) +internal inline fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this) + +internal inline fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { + is BufferedTensor -> this + else -> BufferedTensor(this.shape, this.elements().map{ it.second }.toMutableList().asMutableBuffer(), 0) +} + +internal val TensorStructure.tensor: DoubleTensor + get() = when (this) { + is DoubleTensor -> this + else -> this.toBufferedTensor().asTensor() + } + +internal val TensorStructure.tensor: IntTensor + get() = when (this) { + is IntTensor -> this + else -> this.toBufferedTensor().asTensor() + } + diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt index b46c7fa9c..233217f2f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt @@ -1,45 +1,46 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.AnalyticTensorAlgebra +import space.kscience.kmath.tensors.TensorStructure import kotlin.math.* public class DoubleAnalyticTensorAlgebra: - AnalyticTensorAlgebra, + AnalyticTensorAlgebra, DoubleTensorAlgebra() { - override fun DoubleTensor.exp(): DoubleTensor = this.map(::exp) + override fun TensorStructure.exp(): DoubleTensor = tensor.map(::exp) - override fun DoubleTensor.log(): DoubleTensor = this.map(::ln) + override fun TensorStructure.log(): DoubleTensor = tensor.map(::ln) - override fun DoubleTensor.sqrt(): DoubleTensor = this.map(::sqrt) + override fun TensorStructure.sqrt(): DoubleTensor = tensor.map(::sqrt) - override fun DoubleTensor.cos(): DoubleTensor = this.map(::cos) + override fun TensorStructure.cos(): DoubleTensor = tensor.map(::cos) - override fun DoubleTensor.acos(): DoubleTensor = this.map(::acos) + override fun TensorStructure.acos(): DoubleTensor = tensor.map(::acos) - override fun DoubleTensor.cosh(): DoubleTensor = this.map(::cosh) + override fun TensorStructure.cosh(): DoubleTensor = tensor.map(::cosh) - override fun DoubleTensor.acosh(): DoubleTensor = this.map(::acosh) + override fun TensorStructure.acosh(): DoubleTensor = tensor.map(::acosh) - override fun DoubleTensor.sin(): DoubleTensor = this.map(::sin) + override fun TensorStructure.sin(): DoubleTensor = tensor.map(::sin) - override fun DoubleTensor.asin(): DoubleTensor = this.map(::asin) + override fun TensorStructure.asin(): DoubleTensor = tensor.map(::asin) - override fun DoubleTensor.sinh(): DoubleTensor = this.map(::sinh) + override fun TensorStructure.sinh(): DoubleTensor = tensor.map(::sinh) - override fun DoubleTensor.asinh(): DoubleTensor = this.map(::asinh) + override fun TensorStructure.asinh(): DoubleTensor = tensor.map(::asinh) - override fun DoubleTensor.tan(): DoubleTensor = this.map(::tan) + override fun TensorStructure.tan(): DoubleTensor = tensor.map(::tan) - override fun DoubleTensor.atan(): DoubleTensor = this.map(::atan) + override fun TensorStructure.atan(): DoubleTensor = tensor.map(::atan) - override fun DoubleTensor.tanh(): DoubleTensor = this.map(::tanh) + override fun TensorStructure.tanh(): DoubleTensor = tensor.map(::tanh) - override fun DoubleTensor.atanh(): DoubleTensor = this.map(::atanh) + override fun TensorStructure.atanh(): DoubleTensor = tensor.map(::atanh) - override fun DoubleTensor.ceil(): DoubleTensor = this.map(::ceil) + override fun TensorStructure.ceil(): DoubleTensor = tensor.map(::ceil) - override fun DoubleTensor.floor(): DoubleTensor = this.map(::floor) + override fun TensorStructure.floor(): DoubleTensor = tensor.map(::floor) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index e72948c84..386fc2a1b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -3,44 +3,45 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.tensors.TensorStructure import kotlin.math.min public class DoubleLinearOpsTensorAlgebra : - LinearOpsTensorAlgebra, + LinearOpsTensorAlgebra, DoubleTensorAlgebra() { - override fun DoubleTensor.inv(): DoubleTensor = invLU(1e-9) + override fun TensorStructure.inv(): DoubleTensor = invLU(1e-9) - override fun DoubleTensor.det(): DoubleTensor = detLU(1e-9) + override fun TensorStructure.det(): DoubleTensor = detLU(1e-9) - public fun DoubleTensor.lu(epsilon: Double): Pair = - computeLU(this, epsilon) ?: + public fun TensorStructure.lu(epsilon: Double): Pair = + computeLU(tensor, epsilon) ?: throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon") - override fun DoubleTensor.lu(): Pair = lu(1e-9) + override fun TensorStructure.lu(): Pair = lu(1e-9) override fun luPivot( - luTensor: DoubleTensor, - pivotsTensor: IntTensor + luTensor: TensorStructure, + pivotsTensor: TensorStructure ): Triple { //todo checks checkSquareMatrix(luTensor.shape) check( luTensor.shape.dropLast(2).toIntArray() contentEquals pivotsTensor.shape.dropLast(1).toIntArray() || luTensor.shape.last() == pivotsTensor.shape.last() - 1 - ) { "Bed shapes ((" } //todo rewrite + ) { "Bad shapes ((" } //todo rewrite val n = luTensor.shape.last() val pTensor = luTensor.zeroesLike() - for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) + for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.tensor.vectorSequence())) pivInit(p.as2D(), pivot.as1D(), n) val lTensor = luTensor.zeroesLike() val uTensor = luTensor.zeroesLike() for ((pairLU, lu) in lTensor.matrixSequence().zip(uTensor.matrixSequence()) - .zip(luTensor.matrixSequence())) { + .zip(luTensor.tensor.matrixSequence())) { val (l, u) = pairLU luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) } @@ -49,26 +50,26 @@ public class DoubleLinearOpsTensorAlgebra : } - public fun DoubleTensor.cholesky(epsilon: Double): DoubleTensor { + public fun TensorStructure.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) - checkPositiveDefinite(this, epsilon) + checkPositiveDefinite(tensor, epsilon) val n = shape.last() val lTensor = zeroesLike() - for ((a, l) in this.matrixSequence().zip(lTensor.matrixSequence())) + for ((a, l) in tensor.matrixSequence().zip(lTensor.matrixSequence())) for (i in 0 until n) choleskyHelper(a.as2D(), l.as2D(), n) return lTensor } - override fun DoubleTensor.cholesky(): DoubleTensor = cholesky(1e-6) + override fun TensorStructure.cholesky(): DoubleTensor = cholesky(1e-6) - override fun DoubleTensor.qr(): Pair { + override fun TensorStructure.qr(): Pair { checkSquareMatrix(shape) val qTensor = zeroesLike() val rTensor = zeroesLike() - val seq = matrixSequence().zip((qTensor.matrixSequence().zip(rTensor.matrixSequence()))) + val seq = tensor.matrixSequence().zip((qTensor.matrixSequence().zip(rTensor.matrixSequence()))) for ((matrix, qr) in seq) { val (q, r) = qr qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) @@ -76,18 +77,18 @@ public class DoubleLinearOpsTensorAlgebra : return qTensor to rTensor } - override fun DoubleTensor.svd(): Triple = + override fun TensorStructure.svd(): Triple = svd(epsilon = 1e-10) - public fun DoubleTensor.svd(epsilon: Double): Triple { - val size = this.linearStructure.dim - val commonShape = this.shape.sliceArray(0 until size - 2) - val (n, m) = this.shape.sliceArray(size - 2 until size) + public fun TensorStructure.svd(epsilon: Double): Triple { + val size = tensor.linearStructure.dim + val commonShape = tensor.shape.sliceArray(0 until size - 2) + val (n, m) = tensor.shape.sliceArray(size - 2 until size) val resU = zeros(commonShape + intArrayOf(min(n, m), n)) val resS = zeros(commonShape + intArrayOf(min(n, m))) val resV = zeros(commonShape + intArrayOf(min(n, m), m)) - for ((matrix, USV) in this.matrixSequence() + for ((matrix, USV) in tensor.matrixSequence() .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) { val size = matrix.shape.reduce { acc, i -> acc * i } val curMatrix = DoubleTensor( @@ -99,13 +100,13 @@ public class DoubleLinearOpsTensorAlgebra : return Triple(resU.transpose(), resS, resV.transpose()) } - override fun DoubleTensor.symEig(): Pair = + override fun TensorStructure.symEig(): Pair = symEig(epsilon = 1e-15) //http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html - public fun DoubleTensor.symEig(epsilon: Double): Pair { - checkSymmetric(this, epsilon) - val (u, s, v) = this.svd(epsilon) + public fun TensorStructure.symEig(epsilon: Double): Pair { + checkSymmetric(tensor, epsilon) + val (u, s, v) = tensor.svd(epsilon) val shp = s.shape + intArrayOf(1) val utv = u.transpose() dot v val n = s.shape.last() @@ -116,11 +117,11 @@ public class DoubleLinearOpsTensorAlgebra : return Pair(eig, v) } - public fun DoubleTensor.detLU(epsilon: Double = 1e-9): DoubleTensor { + public fun TensorStructure.detLU(epsilon: Double = 1e-9): DoubleTensor { - checkSquareMatrix(this.shape) - val luTensor = this.copy() - val pivotsTensor = this.setUpPivots() + checkSquareMatrix(tensor.shape) + val luTensor = tensor.copy() + val pivotsTensor = tensor.setUpPivots() val n = shape.size @@ -141,7 +142,7 @@ public class DoubleLinearOpsTensorAlgebra : return detTensor } - public fun DoubleTensor.invLU(epsilon: Double = 1e-9): DoubleTensor { + public fun TensorStructure.invLU(epsilon: Double = 1e-9): DoubleTensor { val (luTensor, pivotsTensor) = lu(epsilon) val invTensor = luTensor.zeroesLike() 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 8f355dd3d..7544bf68e 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 @@ -1,16 +1,18 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra import space.kscience.kmath.nd.as2D +import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra +import space.kscience.kmath.tensors.TensorStructure import kotlin.math.abs -public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { +public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { - override fun DoubleTensor.value(): Double { - check(this.shape contentEquals intArrayOf(1)) { + + override fun TensorStructure.value(): Double { + check(tensor.shape contentEquals intArrayOf(1)) { "Inconsistent value for tensor of shape ${shape.toList()}" } - return this.buffer.array()[this.bufferStart] + return tensor.buffer.array()[tensor.bufferStart] } public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor { @@ -20,11 +22,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra.get(i: Int): DoubleTensor { + val lastShape = tensor.shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) - val newStart = newShape.reduce(Int::times) * i + this.bufferStart - return DoubleTensor(newShape, this.buffer.array(), newStart) + val newStart = newShape.reduce(Int::times) * i + tensor.bufferStart + return DoubleTensor(newShape, tensor.buffer.array(), newStart) } public fun full(value: Double, shape: IntArray): DoubleTensor { @@ -33,19 +35,19 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra.fullLike(value: Double): DoubleTensor { + val shape = tensor.shape + val buffer = DoubleArray(tensor.numElements) { value } return DoubleTensor(shape, buffer) } public fun zeros(shape: IntArray): DoubleTensor = full(0.0, shape) - public fun DoubleTensor.zeroesLike(): DoubleTensor = this.fullLike(0.0) + public fun TensorStructure.zeroesLike(): DoubleTensor = tensor.fullLike(0.0) public fun ones(shape: IntArray): DoubleTensor = full(1.0, shape) - public fun DoubleTensor.onesLike(): DoubleTensor = this.fullLike(1.0) + public fun TensorStructure.onesLike(): DoubleTensor = tensor.fullLike(1.0) public fun eye(n: Int): DoubleTensor { val shape = intArrayOf(n, n) @@ -57,200 +59,200 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra.copy(): DoubleTensor { + return DoubleTensor(tensor.shape, tensor.buffer.array().copyOf(), tensor.bufferStart) } - override fun Double.plus(other: DoubleTensor): DoubleTensor { - val resBuffer = DoubleArray(other.linearStructure.size) { i -> - other.buffer.array()[other.bufferStart + i] + this + override fun Double.plus(other: TensorStructure): DoubleTensor { + val resBuffer = DoubleArray(other.tensor.numElements) { i -> + other.tensor.buffer.array()[other.tensor.bufferStart + i] + this } return DoubleTensor(other.shape, resBuffer) } - override fun DoubleTensor.plus(value: Double): DoubleTensor = value + this + override fun TensorStructure.plus(value: Double): DoubleTensor = value + tensor - override fun DoubleTensor.plus(other: DoubleTensor): DoubleTensor { - checkShapesCompatible(this, other) - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[i] + other.buffer.array()[i] + override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { + checkShapesCompatible(tensor, other.tensor) + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[i] + other.tensor.buffer.array()[i] } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.plusAssign(value: Double) { - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] += value + override fun TensorStructure.plusAssign(value: Double) { + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] += value } } - override fun DoubleTensor.plusAssign(other: DoubleTensor) { - checkShapesCompatible(this, other) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] += - other.buffer.array()[this.bufferStart + i] + override fun TensorStructure.plusAssign(other: TensorStructure) { + checkShapesCompatible(tensor, other.tensor) + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] += + other.tensor.buffer.array()[tensor.bufferStart + i] } } - override fun Double.minus(other: DoubleTensor): DoubleTensor { - val resBuffer = DoubleArray(other.linearStructure.size) { i -> - this - other.buffer.array()[other.bufferStart + i] + override fun Double.minus(other: TensorStructure): DoubleTensor { + val resBuffer = DoubleArray(other.tensor.numElements) { i -> + this - other.tensor.buffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } - override fun DoubleTensor.minus(value: Double): DoubleTensor { - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[this.bufferStart + i] - value + override fun TensorStructure.minus(value: Double): DoubleTensor { + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[tensor.bufferStart + i] - value } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.minus(other: DoubleTensor): DoubleTensor { - checkShapesCompatible(this, other) - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[i] - other.buffer.array()[i] + override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { + checkShapesCompatible(tensor, other) + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[i] - other.tensor.buffer.array()[i] } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.minusAssign(value: Double) { - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] -= value + override fun TensorStructure.minusAssign(value: Double) { + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] -= value } } - override fun DoubleTensor.minusAssign(other: DoubleTensor) { - checkShapesCompatible(this, other) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] -= - other.buffer.array()[this.bufferStart + i] + override fun TensorStructure.minusAssign(other: TensorStructure) { + checkShapesCompatible(tensor, other) + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] -= + other.tensor.buffer.array()[tensor.bufferStart + i] } } - override fun Double.times(other: DoubleTensor): DoubleTensor { - val resBuffer = DoubleArray(other.linearStructure.size) { i -> - other.buffer.array()[other.bufferStart + i] * this + override fun Double.times(other: TensorStructure): DoubleTensor { + val resBuffer = DoubleArray(other.tensor.numElements) { i -> + other.tensor.buffer.array()[other.tensor.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) } - override fun DoubleTensor.times(value: Double): DoubleTensor = value * this + override fun TensorStructure.times(value: Double): DoubleTensor = value * tensor - override fun DoubleTensor.times(other: DoubleTensor): DoubleTensor { - checkShapesCompatible(this, other) - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[this.bufferStart + i] * - other.buffer.array()[other.bufferStart + i] + override fun TensorStructure.times(other: TensorStructure): DoubleTensor { + checkShapesCompatible(tensor, other) + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[tensor.bufferStart + i] * + other.tensor.buffer.array()[other.tensor.bufferStart + i] } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.timesAssign(value: Double) { - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] *= value + override fun TensorStructure.timesAssign(value: Double) { + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] *= value } } - override fun DoubleTensor.timesAssign(other: DoubleTensor) { - checkShapesCompatible(this, other) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] *= - other.buffer.array()[this.bufferStart + i] + override fun TensorStructure.timesAssign(other: TensorStructure) { + checkShapesCompatible(tensor, other) + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] *= + other.tensor.buffer.array()[tensor.bufferStart + i] } } - override fun DoubleTensor.div(value: Double): DoubleTensor { - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[this.bufferStart + i] / value + override fun TensorStructure.div(value: Double): DoubleTensor { + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[tensor.bufferStart + i] / value } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.div(other: DoubleTensor): DoubleTensor { - checkShapesCompatible(this, other) - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[other.bufferStart + i] / - other.buffer.array()[other.bufferStart + i] + override fun TensorStructure.div(other: TensorStructure): DoubleTensor { + checkShapesCompatible(tensor, other) + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[other.tensor.bufferStart + i] / + other.tensor.buffer.array()[other.tensor.bufferStart + i] } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.divAssign(value: Double) { - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] /= value + override fun TensorStructure.divAssign(value: Double) { + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] /= value } } - override fun DoubleTensor.divAssign(other: DoubleTensor) { - checkShapesCompatible(this, other) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] /= - other.buffer.array()[this.bufferStart + i] + override fun TensorStructure.divAssign(other: TensorStructure) { + checkShapesCompatible(tensor, other) + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] /= + other.tensor.buffer.array()[tensor.bufferStart + i] } } - override fun DoubleTensor.unaryMinus(): DoubleTensor { - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[this.bufferStart + i].unaryMinus() + override fun TensorStructure.unaryMinus(): DoubleTensor { + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[tensor.bufferStart + i].unaryMinus() } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.transpose(i: Int, j: Int): DoubleTensor { - val ii = minusIndex(i) - val jj = minusIndex(j) - checkTranspose(this.dimension, ii, jj) - val n = this.linearStructure.size + override fun TensorStructure.transpose(i: Int, j: Int): DoubleTensor { + val ii = tensor.minusIndex(i) + val jj = tensor.minusIndex(j) + checkTranspose(tensor.dimension, ii, jj) + val n = tensor.numElements val resBuffer = DoubleArray(n) - val resShape = this.shape.copyOf() + val resShape = tensor.shape.copyOf() resShape[ii] = resShape[jj].also { resShape[jj] = resShape[ii] } val resTensor = DoubleTensor(resShape, resBuffer) for (offset in 0 until n) { - val oldMultiIndex = this.linearStructure.index(offset) + val oldMultiIndex = tensor.linearStructure.index(offset) val newMultiIndex = oldMultiIndex.copyOf() newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } val linearIndex = resTensor.linearStructure.offset(newMultiIndex) resTensor.buffer.array()[linearIndex] = - this.buffer.array()[this.bufferStart + offset] + tensor.buffer.array()[tensor.bufferStart + offset] } return resTensor } - override fun DoubleTensor.view(shape: IntArray): DoubleTensor { - checkView(this, shape) - return DoubleTensor(shape, this.buffer.array(), this.bufferStart) + override fun TensorStructure.view(shape: IntArray): DoubleTensor { + checkView(tensor, shape) + return DoubleTensor(shape, tensor.buffer.array(), tensor.bufferStart) } - override fun DoubleTensor.viewAs(other: DoubleTensor): DoubleTensor { - return this.view(other.shape) + override fun TensorStructure.viewAs(other: TensorStructure): DoubleTensor { + return tensor.view(other.shape) } - override infix fun DoubleTensor.dot(other: DoubleTensor): DoubleTensor { - if (this.shape.size == 1 && other.shape.size == 1) { - return DoubleTensor(intArrayOf(1), doubleArrayOf(this.times(other).buffer.array().sum())) + override infix fun TensorStructure.dot(other: TensorStructure): DoubleTensor { + if (tensor.shape.size == 1 && other.shape.size == 1) { + return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.buffer.array().sum())) } - var newThis = this.copy() + var newThis = tensor.copy() var newOther = other.copy() var penultimateDim = false var lastDim = false - if (this.shape.size == 1) { + if (tensor.shape.size == 1) { penultimateDim = true - newThis = this.view(intArrayOf(1) + this.shape) + newThis = tensor.view(intArrayOf(1) + tensor.shape) } if (other.shape.size == 1) { lastDim = true - newOther = other.view(other.shape + intArrayOf(1)) + newOther = other.tensor.view(other.shape + intArrayOf(1)) } - val broadcastTensors = broadcastOuterTensors(newThis, newOther) + val broadcastTensors = broadcastOuterTensors(newThis.tensor, newOther.tensor) newThis = broadcastTensors[0] newOther = broadcastTensors[1] @@ -284,10 +286,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra, offset: Int, dim1: Int, dim2: Int): + DoubleTensor { val n = diagonalEntries.shape.size + val d1 = minusIndexFrom(n + 1, dim1) + val d2 = minusIndexFrom(n + 1, dim2) + if (d1 == d2) { throw RuntimeException("Diagonal dimensions cannot be identical $d1, $d2") } @@ -300,7 +304,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra greaterDim) { realOffset *= -1 - lessDim = greaterDim.also {greaterDim = lessDim} + lessDim = greaterDim.also { greaterDim = lessDim } } val resShape = diagonalEntries.shape.slice(0 until lessDim).toIntArray() + @@ -310,13 +314,13 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Double): DoubleTensor { + public fun TensorStructure.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( - this.shape, - this.buffer.array().map { transform(it) }.toDoubleArray(), - this.bufferStart + tensor.shape, + tensor.buffer.array().map { transform(it) }.toDoubleArray(), + tensor.bufferStart ) } - public fun DoubleTensor.eq(other: DoubleTensor, delta: Double): Boolean { - return this.eq(other) { x, y -> abs(x - y) < delta } + public fun TensorStructure.eq(other: TensorStructure, delta: Double): Boolean { + return tensor.eq(other) { x, y -> abs(x - y) < delta } } - public fun DoubleTensor.eq(other: DoubleTensor): Boolean = this.eq(other, 1e-5) + public fun TensorStructure.eq(other: TensorStructure): Boolean = tensor.eq(other, 1e-5) - private fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { - checkShapesCompatible(this, other) - val n = this.linearStructure.size - if (n != other.linearStructure.size) { + private fun TensorStructure.eq( + other: TensorStructure, + eqFunction: (Double, Double) -> Boolean + ): Boolean { + checkShapesCompatible(tensor, other) + val n = tensor.numElements + if (n != other.tensor.numElements) { return false } for (i in 0 until n) { - if (!eqFunction(this.buffer[this.bufferStart + i], other.buffer[other.bufferStart + i])) { + if (!eqFunction(tensor.buffer[tensor.bufferStart + i], other.tensor.buffer[other.tensor.bufferStart + i])) { return false } } @@ -362,8 +369,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra.randNormalLike(seed: Long = 0): DoubleTensor = + DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 730b6ed9a..28828eb09 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -1,54 +1,40 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.tensors.TensorAlgebra import space.kscience.kmath.tensors.TensorStructure -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkEmptyShape(shape: IntArray): Unit = +internal inline fun checkEmptyShape(shape: IntArray): Unit = check(shape.isNotEmpty()) { "Illegal empty shape provided" } -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = +internal inline fun checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = check(buffer.isNotEmpty()) { "Illegal empty buffer provided" } -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = +internal inline fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = check(buffer.size == shape.reduce(Int::times)) { "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" } -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkShapesCompatible(a: TensorType, b: TensorType): Unit = +internal inline fun checkShapesCompatible(a: TensorStructure, b: TensorStructure): Unit = check(a.shape contentEquals b.shape) { "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " } -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkTranspose(dim: Int, i: Int, j: Int): Unit = +internal inline fun checkTranspose(dim: Int, i: Int, j: Int): Unit = check((i < dim) and (j < dim)) { "Cannot transpose $i to $j for a tensor of dim $dim" } -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = +internal inline fun checkView(a: TensorStructure, shape: IntArray): Unit = check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkSquareMatrix(shape: IntArray): Unit { + +internal inline fun checkSquareMatrix(shape: IntArray): Unit { val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n instead" @@ -58,16 +44,19 @@ internal inline fun , } } -internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor, epsilon: Double = 1e-6): Unit = +internal inline fun DoubleTensorAlgebra.checkSymmetric( + tensor: TensorStructure, epsilon: Double = 1e-6 +): Unit = check(tensor.eq(tensor.transpose(), epsilon)) { "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( - tensor: DoubleTensor, epsilon: Double = 1e-6): Unit { + tensor: DoubleTensor, epsilon: Double = 1e-6 +): Unit { checkSymmetric(tensor, epsilon) - for( mat in tensor.matrixSequence()) - check(mat.asTensor().detLU().value() > 0.0){ + for (mat in tensor.matrixSequence()) + check(mat.asTensor().detLU().value() > 0.0) { "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index ba5e0caaf..166f1d6c4 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -14,7 +14,7 @@ internal inline fun BufferedTensor.vectorSequence(): Sequence BufferedTensor.matrixSequence(): Sequence= 0) i else { ii } -internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.linearStructure.dim, i) +internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.dimension, i) internal inline fun format(value: Double, digits: Int = 4): String { val ten = 10.0 @@ -111,7 +111,7 @@ internal inline fun DoubleTensor.toPrettyString(): String = buildString { } offset += vectorSize // todo refactor - if (this@toPrettyString.numel == offset) { + if (this@toPrettyString.numElements == offset) { break } append(",\n") From 559e8b24ab6189b523e3707b605b7f2c75c8b92c Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 21 Apr 2021 23:44:39 +0300 Subject: [PATCH 126/211] rework structure + fixes --- .../{ => api}/AnalyticTensorAlgebra.kt | 7 +- .../{ => api}/LinearOpsTensorAlgebra.kt | 7 +- .../kmath/tensors/{ => api}/TensorAlgebra.kt | 11 +- .../{ => api}/TensorPartialDivisionAlgebra.kt | 9 +- .../tensors/{ => api}/TensorStructure.kt | 2 +- .../kmath/tensors/core/BufferedTensor.kt | 3 +- .../algebras/BroadcastDoubleTensorAlgebra.kt | 89 ++++++++++ .../DoubleAnalyticTensorAlgebra.kt | 13 +- .../DoubleLinearOpsTensorAlgebra.kt | 27 +++- .../{ => algebras}/DoubleTensorAlgebra.kt | 27 +++- .../{ => algebras}/TensorLinearStructure.kt | 7 +- ...ubleTensorAlgebra.kt => broadcastUtils.kt} | 153 ++++-------------- .../kscience/kmath/tensors/core/checks.kt | 4 +- .../tensors/core/{linutils.kt => linUtils.kt} | 10 +- .../kscience/kmath/tensors/core/utils.kt | 1 - .../kmath/tensors/core/TestBroadcasting.kt | 1 + .../core/TestDoubleAnalyticTensorAlgebra.kt | 1 + .../core/TestDoubleLinearOpsAlgebra.kt | 3 +- .../kmath/tensors/core/TestDoubleTensor.kt | 2 +- .../tensors/core/TestDoubleTensorAlgebra.kt | 20 ++- 20 files changed, 237 insertions(+), 160 deletions(-) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => api}/AnalyticTensorAlgebra.kt (91%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => api}/LinearOpsTensorAlgebra.kt (86%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => api}/TensorAlgebra.kt (89%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => api}/TensorPartialDivisionAlgebra.kt (64%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => api}/TensorStructure.kt (73%) create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => algebras}/DoubleAnalyticTensorAlgebra.kt (77%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => algebras}/DoubleLinearOpsTensorAlgebra.kt (84%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => algebras}/DoubleTensorAlgebra.kt (92%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => algebras}/TensorLinearStructure.kt (90%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{BroadcastDoubleTensorAlgebra.kt => broadcastUtils.kt} (52%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{linutils.kt => linUtils.kt} (97%) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt similarity index 91% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 2a8b228f4..315f39027 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -1,4 +1,9 @@ -package space.kscience.kmath.tensors +/* + * 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.api public interface AnalyticTensorAlgebra : diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt similarity index 86% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 8ca8945a5..5cd48ca78 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -1,4 +1,9 @@ -package space.kscience.kmath.tensors +/* + * 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.api public interface LinearOpsTensorAlgebra : diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt similarity index 89% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index f64d49dd8..c1657d916 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -1,4 +1,9 @@ -package space.kscience.kmath.tensors +/* + * 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.api // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra { @@ -40,7 +45,9 @@ public interface TensorAlgebra { //https://pytorch.org/docs/stable/generated/torch.diag_embed.html public fun diagonalEmbedding( diagonalEntries: TensorStructure, - offset: Int = 0, dim1: Int = -2, dim2: Int = -1 + offset: Int = 0, + dim1: Int = -2, + dim2: Int = -1 ): TensorStructure } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt similarity index 64% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt index b37ac6b6e..075e86e61 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt @@ -1,8 +1,13 @@ -package space.kscience.kmath.tensors +/* + * 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.api // https://proofwiki.org/wiki/Definition:Division_Algebra public interface TensorPartialDivisionAlgebra : - TensorAlgebra { + TensorAlgebra { public operator fun TensorStructure.div(value: T): TensorStructure public operator fun TensorStructure.div(other: TensorStructure): TensorStructure public operator fun TensorStructure.divAssign(value: T) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorStructure.kt similarity index 73% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorStructure.kt index 64c4d98b8..edecd6383 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorStructure.kt @@ -1,4 +1,4 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.api import space.kscience.kmath.nd.MutableStructureND 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 2b61e10b2..5c0d9c4ea 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,7 +1,8 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.structures.* -import space.kscience.kmath.tensors.TensorStructure +import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure public open class BufferedTensor( diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt new file mode 100644 index 000000000..1b00197ff --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -0,0 +1,89 @@ +/* + * 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.algebras + +import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.broadcastTensors +import space.kscience.kmath.tensors.core.broadcastTo + +public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { + + override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + newThis.buffer.array()[i] + newOther.buffer.array()[i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun TensorStructure.plusAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] += + newOther.buffer.array()[tensor.bufferStart + i] + } + } + + override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + newThis.buffer.array()[i] - newOther.buffer.array()[i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun TensorStructure.minusAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] -= + newOther.buffer.array()[tensor.bufferStart + i] + } + } + + override fun TensorStructure.times(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + newThis.buffer.array()[newThis.bufferStart + i] * + newOther.buffer.array()[newOther.bufferStart + i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun TensorStructure.timesAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] *= + newOther.buffer.array()[tensor.bufferStart + i] + } + } + + override fun TensorStructure.div(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + newThis.buffer.array()[newOther.bufferStart + i] / + newOther.buffer.array()[newOther.bufferStart + i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun TensorStructure.divAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] /= + newOther.buffer.array()[tensor.bufferStart + i] + } + } + +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt similarity index 77% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 233217f2f..7d1cceb15 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -1,7 +1,14 @@ -package space.kscience.kmath.tensors.core +/* + * 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. + */ -import space.kscience.kmath.tensors.AnalyticTensorAlgebra -import space.kscience.kmath.tensors.TensorStructure +package space.kscience.kmath.tensors.core.algebras + +import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra +import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.tensor import kotlin.math.* public class DoubleAnalyticTensorAlgebra: diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt similarity index 84% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 386fc2a1b..62629f3db 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -1,9 +1,23 @@ -package space.kscience.kmath.tensors.core +/* + * 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. + */ -import space.kscience.kmath.tensors.LinearOpsTensorAlgebra +package space.kscience.kmath.tensors.core.algebras + +import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D -import space.kscience.kmath.tensors.TensorStructure +import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.checkSquareMatrix +import space.kscience.kmath.tensors.core.choleskyHelper +import space.kscience.kmath.tensors.core.cleanSymHelper +import space.kscience.kmath.tensors.core.luHelper +import space.kscience.kmath.tensors.core.luMatrixDet +import space.kscience.kmath.tensors.core.luMatrixInv +import space.kscience.kmath.tensors.core.luPivotHelper +import space.kscience.kmath.tensors.core.pivInit import kotlin.math.min @@ -25,12 +39,11 @@ public class DoubleLinearOpsTensorAlgebra : luTensor: TensorStructure, pivotsTensor: TensorStructure ): Triple { - //todo checks checkSquareMatrix(luTensor.shape) check( luTensor.shape.dropLast(2).toIntArray() contentEquals pivotsTensor.shape.dropLast(1).toIntArray() || luTensor.shape.last() == pivotsTensor.shape.last() - 1 - ) { "Bad shapes ((" } //todo rewrite + ) { "Inappropriate shapes of input tensors" } val n = luTensor.shape.last() val pTensor = luTensor.zeroesLike() @@ -90,10 +103,10 @@ public class DoubleLinearOpsTensorAlgebra : for ((matrix, USV) in tensor.matrixSequence() .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) { - val size = matrix.shape.reduce { acc, i -> acc * i } + val matrixSize = matrix.shape.reduce { acc, i -> acc * i } val curMatrix = DoubleTensor( matrix.shape, - matrix.buffer.array().slice(matrix.bufferStart until matrix.bufferStart + size).toDoubleArray() + matrix.buffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize).toDoubleArray() ) svdHelper(curMatrix, USV, m, n, epsilon) } 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/algebras/DoubleTensorAlgebra.kt similarity index 92% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 7544bf68e..651db2c21 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/algebras/DoubleTensorAlgebra.kt @@ -1,8 +1,24 @@ -package space.kscience.kmath.tensors.core +/* + * 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.algebras import space.kscience.kmath.nd.as2D -import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra -import space.kscience.kmath.tensors.TensorStructure +import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra +import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.broadcastOuterTensors +import space.kscience.kmath.tensors.core.checkBufferShapeConsistency +import space.kscience.kmath.tensors.core.checkEmptyDoubleBuffer +import space.kscience.kmath.tensors.core.checkEmptyShape +import space.kscience.kmath.tensors.core.checkShapesCompatible +import space.kscience.kmath.tensors.core.checkTranspose +import space.kscience.kmath.tensors.core.checkView +import space.kscience.kmath.tensors.core.dotHelper +import space.kscience.kmath.tensors.core.getRandomNormals +import space.kscience.kmath.tensors.core.minusIndexFrom import kotlin.math.abs public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { @@ -263,7 +279,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { if (m1 != m2) { throw RuntimeException("Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)") } - val m = m1 val resShape = newThis.shape.sliceArray(0..(newThis.shape.size - 2)) + intArrayOf(newOther.shape.last()) val resSize = resShape.reduce { acc, i -> acc * i } @@ -271,7 +286,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { for ((res, ab) in resTensor.matrixSequence().zip(newThis.matrixSequence().zip(newOther.matrixSequence()))) { val (a, b) = ab - dotHelper(a.as2D(), b.as2D(), res.as2D(), l, m, n) + dotHelper(a.as2D(), b.as2D(), res.as2D(), l, m1, n) } if (penultimateDim) { @@ -347,7 +362,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return tensor.eq(other) { x, y -> abs(x - y) < delta } } - public fun TensorStructure.eq(other: TensorStructure): Boolean = tensor.eq(other, 1e-5) + public infix fun TensorStructure.eq(other: TensorStructure): Boolean = tensor.eq(other, 1e-5) private fun TensorStructure.eq( other: TensorStructure, diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt similarity index 90% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index 47745c2be..b16739892 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -1,4 +1,9 @@ -package space.kscience.kmath.tensors.core +/* + * 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.algebras import kotlin.math.max 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/broadcastUtils.kt similarity index 52% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt index 53c385197..4378e9ac9 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/broadcastUtils.kt @@ -1,89 +1,31 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.tensors.TensorStructure +import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra import kotlin.math.max -public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { - - override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { - val broadcast = broadcastTensors(tensor, other.tensor) - val newThis = broadcast[0] - val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[i] + newOther.buffer.array()[i] - } - return DoubleTensor(newThis.shape, resBuffer) - } - - override fun TensorStructure.plusAssign(other: TensorStructure) { - val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] += - newOther.buffer.array()[tensor.bufferStart + i] - } - } - - override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { - val broadcast = broadcastTensors(tensor, other.tensor) - val newThis = broadcast[0] - val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[i] - newOther.buffer.array()[i] - } - return DoubleTensor(newThis.shape, resBuffer) - } - - override fun TensorStructure.minusAssign(other: TensorStructure) { - val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] -= - newOther.buffer.array()[tensor.bufferStart + i] - } - } - - override fun TensorStructure.times(other: TensorStructure): DoubleTensor { - val broadcast = broadcastTensors(tensor, other.tensor) - val newThis = broadcast[0] - val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[newThis.bufferStart + i] * - newOther.buffer.array()[newOther.bufferStart + i] - } - return DoubleTensor(newThis.shape, resBuffer) - } - - override fun TensorStructure.timesAssign(other: TensorStructure) { - val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] *= - newOther.buffer.array()[tensor.bufferStart + i] - } - } - - override fun TensorStructure.div(other: TensorStructure): DoubleTensor { - val broadcast = broadcastTensors(tensor, other.tensor) - val newThis = broadcast[0] - val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[newOther.bufferStart + i] / - newOther.buffer.array()[newOther.bufferStart + i] - } - return DoubleTensor(newThis.shape, resBuffer) - } - - override fun TensorStructure.divAssign(other: TensorStructure) { - val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] /= - newOther.buffer.array()[tensor.bufferStart + i] - } - } - -} - public inline fun BroadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorAlgebra.() -> R): R = BroadcastDoubleTensorAlgebra().block() +internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) { + for (linearIndex in 0 until linearSize) { + val totalMultiIndex = resTensor.linearStructure.index(linearIndex) + val curMultiIndex = tensor.shape.copyOf() + + val offset = totalMultiIndex.size - curMultiIndex.size + + for (i in curMultiIndex.indices) { + if (curMultiIndex[i] != 1) { + curMultiIndex[i] = totalMultiIndex[i + offset] + } else { + curMultiIndex[i] = 0 + } + } + + val curLinearIndex = tensor.linearStructure.offset(curMultiIndex) + resTensor.buffer.array()[linearIndex] = + tensor.buffer.array()[tensor.bufferStart + curLinearIndex] + } +} internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { var totalDim = 0 @@ -129,24 +71,7 @@ internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): Doubl } } - for (linearIndex in 0 until n) { - val totalMultiIndex = resTensor.linearStructure.index(linearIndex) - val curMultiIndex = tensor.shape.copyOf() - - val offset = totalMultiIndex.size - curMultiIndex.size - - for (i in curMultiIndex.indices) { - if (curMultiIndex[i] != 1) { - curMultiIndex[i] = totalMultiIndex[i + offset] - } else { - curMultiIndex[i] = 0 - } - } - - val curLinearIndex = tensor.linearStructure.offset(curMultiIndex) - resTensor.buffer.array()[linearIndex] = - tensor.buffer.array()[tensor.bufferStart + curLinearIndex] - } + multiIndexBroadCasting(tensor, resTensor, n) return resTensor } @@ -157,25 +82,7 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List(0) for (tensor in tensors) { val resTensor = DoubleTensor(totalShape, DoubleArray(n)) - - for (linearIndex in 0 until n) { - val totalMultiIndex = resTensor.linearStructure.index(linearIndex) - val curMultiIndex = tensor.shape.copyOf() - - val offset = totalMultiIndex.size - curMultiIndex.size - - for (i in curMultiIndex.indices) { - if (curMultiIndex[i] != 1) { - curMultiIndex[i] = totalMultiIndex[i + offset] - } else { - curMultiIndex[i] = 0 - } - } - - val curLinearIndex = tensor.linearStructure.offset(curMultiIndex) - resTensor.buffer.array()[linearIndex] = - tensor.buffer.array()[tensor.bufferStart + curLinearIndex] - } + multiIndexBroadCasting(tensor, resTensor, n) res.add(resTensor) } @@ -208,7 +115,7 @@ internal inline fun broadcastOuterTensors(vararg tensors: DoubleTensor): List BufferedTensor.matrixSequence(): Sequence BufferedTensor.forEachVector(vectorAction: (BufferedTensor) -> Unit): Unit { +internal inline fun BufferedTensor.forEachVector(vectorAction: (BufferedTensor) -> Unit) { for (vector in vectorSequence()) { vectorAction(vector) } } -internal inline fun BufferedTensor.forEachMatrix(matrixAction: (BufferedTensor) -> Unit): Unit { +internal inline fun BufferedTensor.forEachMatrix(matrixAction: (BufferedTensor) -> Unit) { for (matrix in matrixSequence()) { matrixAction(matrix) } @@ -284,7 +286,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( matrix: DoubleTensor, USV: Pair, Pair, BufferedTensor>>, m: Int, n: Int, epsilon: Double -): Unit { +) { val res = ArrayList>(0) val (matrixU, SV) = USV val (matrixS, matrixV) = SV @@ -332,7 +334,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( } } -internal inline fun cleanSymHelper(matrix: MutableStructure2D, n: Int): Unit { +internal inline fun cleanSymHelper(matrix: MutableStructure2D, n: Int) { for (i in 0 until n) for (j in 0 until n) { if (i == j) { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index ac823185b..d7d006e42 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -110,7 +110,6 @@ internal inline fun DoubleTensor.toPrettyString(): String = buildString { charOffset -=1 } offset += vectorSize - // todo refactor if (this@toPrettyString.numElements == offset) { break } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 41c9b72f7..d677f6966 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.test.Test import kotlin.test.assertTrue diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 4dcdb7848..060bc1607 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import kotlin.math.abs import kotlin.math.exp import kotlin.test.Test 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 d19d0b6f6..6120f0e4a 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 @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra import kotlin.math.abs import kotlin.test.Test import kotlin.test.assertEquals @@ -125,8 +126,6 @@ class TestDoubleLinearOpsTensorAlgebra { val (lu, pivots) = tensor.lu() - // todo check lu - val (p, l, u) = luPivot(lu, pivots) assertTrue { p.shape contentEquals shape } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 4de69e1ad..5c068ce83 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -3,7 +3,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray -import kotlin.test.Ignore +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index fa7a8fd32..10a9176dc 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -1,7 +1,9 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.test.Test +import kotlin.test.assertFalse import kotlin.test.assertTrue class TestDoubleTensorAlgebra { @@ -133,9 +135,9 @@ class TestDoubleTensorAlgebra { assertTrue(diagonal1.buffer.array() contentEquals doubleArrayOf(10.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 30.0)) - val diagonal1_offset = diagonalEmbedding(tensor1, 1, 1, 0) - assertTrue(diagonal1_offset.shape contentEquals intArrayOf(4, 4)) - assertTrue(diagonal1_offset.buffer.array() contentEquals + val diagonal1Offset = diagonalEmbedding(tensor1, 1, 1, 0) + assertTrue(diagonal1Offset.shape contentEquals intArrayOf(4, 4)) + assertTrue(diagonal1Offset.buffer.array() contentEquals doubleArrayOf(0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 30.0, 0.0)) val diagonal2 = diagonalEmbedding(tensor2, 1, 0, 2) @@ -149,7 +151,15 @@ class TestDoubleTensorAlgebra { } @Test - fun testContentEqual() = DoubleTensorAlgebra { - //TODO() + fun testEq() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor3 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) + val tensor4 = fromArray(intArrayOf(6, 1), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + + assertTrue(tensor1 eq tensor1) + assertTrue(tensor1 eq tensor2) + assertFalse(tensor1.eq(tensor3)) + } } \ No newline at end of file From 287e2aeba2ba274508f42f1ab0a839ed69861bc1 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 23 Apr 2021 14:22:52 +0100 Subject: [PATCH 127/211] div operator --- .../kmath/tensors/api/TensorPartialDivisionAlgebra.kt | 1 + .../kmath/tensors/core/algebras/DoubleTensorAlgebra.kt | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt index 075e86e61..4dab3dd07 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt @@ -8,6 +8,7 @@ package space.kscience.kmath.tensors.api // https://proofwiki.org/wiki/Definition:Division_Algebra public interface TensorPartialDivisionAlgebra : TensorAlgebra { + public operator fun T.div(other: TensorStructure): TensorStructure public operator fun TensorStructure.div(value: T): TensorStructure public operator fun TensorStructure.div(other: TensorStructure): TensorStructure public operator fun TensorStructure.divAssign(value: T) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 651db2c21..b61a484d0 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -178,13 +178,15 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } } - override fun TensorStructure.div(value: Double): DoubleTensor { - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[tensor.bufferStart + i] / value + override fun Double.div(other: TensorStructure): DoubleTensor { + val resBuffer = DoubleArray(other.tensor.numElements) { i -> + other.tensor.buffer.array()[other.tensor.bufferStart + i] / this } - return DoubleTensor(tensor.shape, resBuffer) + return DoubleTensor(other.shape, resBuffer) } + override fun TensorStructure.div(value: Double): DoubleTensor = value / tensor + override fun TensorStructure.div(other: TensorStructure): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> From 077c2b4e3b7168a297f5518876dca8ca9a390578 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov <38042667+CommanderTvis@users.noreply.github.com> Date: Fri, 23 Apr 2021 08:49:01 +0700 Subject: [PATCH 128/211] Update README.md in kmath-ast --- kmath-ast/README.md | 5 +++-- kmath-ast/docs/README-TEMPLATE.md | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/kmath-ast/README.md b/kmath-ast/README.md index eedba16fa..1ee78956e 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -50,7 +50,7 @@ For example, the following builder: MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -… leads to generation of bytecode, which can be decompiled to the following Java class: +... leads to generation of bytecode, which can be decompiled to the following Java class: ```java package space.kscience.kmath.asm.generated; @@ -97,6 +97,7 @@ var executable = function (constants, arguments) { }; ``` +JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported. ```kotlin import space.kscience.kmath.wasm.* @@ -104,7 +105,7 @@ import space.kscience.kmath.wasm.* MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -An example of emitted WASM IR in the form of WAT: +An example of emitted Wasm IR in the form of WAT: ```lisp (func $executable (param $0 f64) (result f64) diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index b38311ea1..1ecf477ef 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -19,7 +19,7 @@ For example, the following builder: MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -… leads to generation of bytecode, which can be decompiled to the following Java class: +... leads to generation of bytecode, which can be decompiled to the following Java class: ```java package space.kscience.kmath.asm.generated; @@ -66,6 +66,7 @@ var executable = function (constants, arguments) { }; ``` +JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported. ```kotlin import space.kscience.kmath.wasm.* @@ -73,7 +74,7 @@ import space.kscience.kmath.wasm.* MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -An example of emitted WASM IR in the form of WAT: +An example of emitted Wasm IR in the form of WAT: ```lisp (func \$executable (param \$0 f64) (result f64) From 4f593aec63cd931ebe2d254baf6cee0ef3ca342c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sat, 24 Apr 2021 18:53:21 +0100 Subject: [PATCH 129/211] Buffer mini-protocol --- kmath-core/api/kmath-core.api | 8 ++++- .../space/kscience/kmath/nd/BufferND.kt | 35 ++++++++++++++++++- .../kmath/tensors/core/BufferedTensor.kt | 2 ++ .../kscience/kmath/tensors/core/utils.kt | 23 +++--------- .../kmath/tensors/core/TestDoubleTensor.kt | 34 ++++++++++++++++++ 5 files changed, 81 insertions(+), 21 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 38cfbd58d..41b85b3bb 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -748,7 +748,7 @@ public final class space/kscience/kmath/nd/BufferAlgebraNDKt { public static final fun ring (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedRingND; } -public final class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/StructureND { +public class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/StructureND { public fun (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/Buffer;)V public fun elements ()Lkotlin/sequences/Sequence; public fun get ([I)Ljava/lang/Object; @@ -876,6 +876,12 @@ public abstract interface class space/kscience/kmath/nd/GroupND : space/kscience public final class space/kscience/kmath/nd/GroupND$Companion { } +public final class space/kscience/kmath/nd/MutableBufferND : space/kscience/kmath/nd/BufferND, space/kscience/kmath/nd/MutableStructureND { + public fun (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/MutableBuffer;)V + public final fun getMutableBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun set ([ILjava/lang/Object;)V +} + public abstract interface class space/kscience/kmath/nd/MutableStructure1D : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/Structure1D, space/kscience/kmath/structures/MutableBuffer { public fun set ([ILjava/lang/Object;)V } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt index 23d961a7e..1f608f478 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt @@ -7,6 +7,8 @@ package space.kscience.kmath.nd import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory +import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.MutableBufferFactory /** * Represents [StructureND] over [Buffer]. @@ -15,7 +17,7 @@ import space.kscience.kmath.structures.BufferFactory * @param strides The strides to access elements of [Buffer] by linear indices. * @param buffer The underlying buffer. */ -public class BufferND( +public open class BufferND( public val strides: Strides, public val buffer: Buffer, ) : StructureND { @@ -50,4 +52,35 @@ public inline fun StructureND.mapToBuffer( val strides = DefaultStrides(shape) BufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) } +} + +/** + * Represents [MutableStructureND] over [MutableBuffer]. + * + * @param T the type of items. + * @param strides The strides to access elements of [MutableBuffer] by linear indices. + * @param mutableBuffer The underlying buffer. + */ +public class MutableBufferND( + strides: Strides, + public val mutableBuffer: MutableBuffer, +) : MutableStructureND, BufferND(strides, mutableBuffer) { + override fun set(index: IntArray, value: T) { + mutableBuffer[strides.offset(index)] = value + } +} + +/** + * Transform structure to a new structure using provided [MutableBufferFactory] and optimizing if argument is [MutableBufferND] + */ +public inline fun MutableStructureND.mapToMutableBuffer( + factory: MutableBufferFactory = MutableBuffer.Companion::auto, + crossinline transform: (T) -> R, +): MutableBufferND { + return if (this is MutableBufferND) + MutableBufferND(this.strides, factory.invoke(strides.linearSize) { transform(mutableBuffer[it]) }) + else { + val strides = DefaultStrides(shape) + MutableBufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) + } } \ No newline at end of file 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 5c0d9c4ea..1e9b458b1 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,5 +1,6 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.api.TensorStructure import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure @@ -60,6 +61,7 @@ internal inline fun BufferedTensor.asTensor(): DoubleTensor = DoubleTens internal inline fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { is BufferedTensor -> this + is MutableBufferND -> BufferedTensor(this.shape, this.mutableBuffer, 0) else -> BufferedTensor(this.shape, this.elements().map{ it.second }.toMutableList().asMutableBuffer(), 0) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index d7d006e42..89e9d0d96 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -7,35 +7,20 @@ import space.kscience.kmath.structures.* import kotlin.math.* /** - * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. + * Returns a reference to [IntArray] containing all of the elements of this [Buffer] or copy the data. */ internal fun Buffer.array(): IntArray = when (this) { is IntBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to IntArray") + else -> this.toIntArray() } -/** - * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. - */ -internal fun Buffer.array(): LongArray = when (this) { - is LongBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to LongArray") -} /** - * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. - */ -internal fun Buffer.array(): FloatArray = when (this) { - is FloatBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to FloatArray") -} - -/** - * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. + * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer] or copy the data. */ internal fun Buffer.array(): DoubleArray = when (this) { is DoubleBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") + else -> this.toDoubleArray() } internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 5c068ce83..f9d15c216 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,7 +1,11 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.DefaultStrides +import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.asMutableBuffer import space.kscience.kmath.structures.toDoubleArray import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.test.Test @@ -47,4 +51,34 @@ class TestDoubleTensor { assertEquals(secondRow[1], secondColumn[1]) } } + + @Test + fun bufferProtocol() { + + // create buffers + val doubleBuffer = DoubleBuffer(doubleArrayOf(1.0,2.0,3.0)) + val doubleList = MutableList(3, doubleBuffer::get) + + // create ND buffers + val ndBuffer = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleBuffer) + val ndList = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleList.asMutableBuffer()) + + // map to tensors + val bufferedTensorBuffer = ndBuffer.toBufferedTensor() // strides are flipped + val tensorBuffer = bufferedTensorBuffer.asTensor() // no data copied + + val bufferedTensorList = ndList.toBufferedTensor() // strides are flipped + val tensorList = bufferedTensorList.asTensor() // data copied + + tensorBuffer[intArrayOf(0)] = 55.9 + assertEquals(ndBuffer[intArrayOf(0)], 55.9) + assertEquals(doubleBuffer[0], 55.9) + + tensorList[intArrayOf(0)] = 55.9 + assertEquals(ndList[intArrayOf(0)], 1.0) + assertEquals(doubleList[0], 1.0) + + ndList[intArrayOf(0)] = 55.9 + assertEquals(doubleList[0], 55.9) + } } \ No newline at end of file From 2c001cb1b32f25dc4c245bc32b4046bf78e85cca Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Mon, 26 Apr 2021 17:07:49 +0300 Subject: [PATCH 130/211] fix div + simple tests --- .../tensors/core/algebras/DoubleTensorAlgebra.kt | 9 +++++++-- .../kmath/tensors/core/TestDoubleTensorAlgebra.kt | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index b61a484d0..7414a4469 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -180,12 +180,17 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun Double.div(other: TensorStructure): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> - other.tensor.buffer.array()[other.tensor.bufferStart + i] / this + this / other.tensor.buffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } - override fun TensorStructure.div(value: Double): DoubleTensor = value / tensor + override fun TensorStructure.div(value: Double): DoubleTensor { + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[tensor.bufferStart + i] / value + } + return DoubleTensor(shape, resBuffer) + } override fun TensorStructure.div(other: TensorStructure): DoubleTensor { checkShapesCompatible(tensor, other) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 10a9176dc..1333a7a1f 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -15,6 +15,20 @@ class TestDoubleTensorAlgebra { assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0, 12.0)) } + @Test + fun doubleDiv() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0)) + val res = 2.0/tensor + assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 0.5)) + } + + @Test + fun divDouble() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0)) + val res = tensor / 2.5 + assertTrue(res.buffer.array() contentEquals doubleArrayOf(4.0, 2.0)) + } + @Test fun transpose1x1() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1), doubleArrayOf(0.0)) From 30ca333c040b09ca65d528b052fa27492161654a Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Mon, 26 Apr 2021 17:27:50 +0300 Subject: [PATCH 131/211] OLS/SVD example --- examples/build.gradle.kts | 1 + .../kscience/kmath/tensors/OLSWithSVD.kt | 68 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 56feee9dc..a4eabc2b8 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { implementation(project(":kmath-dimensions")) implementation(project(":kmath-ejml")) implementation(project(":kmath-nd4j")) + implementation(project(":kmath-tensors")) implementation(project(":kmath-for-real")) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt new file mode 100644 index 000000000..063a1d1c4 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -0,0 +1,68 @@ +/* + * 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 + +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra + +// OLS estimator using SVD + +fun main() { + //seed for random + val randSeed = 100500L + + // work in context with linear operations + DoubleLinearOpsTensorAlgebra { + // take coefficient vector from normal distribution + val alpha = randNormal( + intArrayOf(5), + randSeed + ) + fromArray( + intArrayOf(5), + doubleArrayOf(1.0, 2.5, 3.4, 5.0, 10.1) + ) + + println("Real alpha:\n" + + "$alpha") + + // also take sample of size 20 from normal distribution for x TODO rename + val x = randNormal( + intArrayOf(20, 5), + randSeed + ) + + // calculate y and add gaussian noise (N(0, 0.05)) TODO rename + val y = x dot alpha + y += y.randNormalLike(randSeed) * 0.05 + + // now restore the coefficient vector with OSL estimator with SVD + val (u, singValues, v) = x.svd() + + // we have to make sure the singular values of the matrix are not close to zero + println("Singular values:\n" + + "$singValues") + // TODO something with Boolean tensors + + // inverse Sigma matrix can be restored from singular values with diagonalEmbedding function + val sigma = diagonalEmbedding(1.0/singValues) + + val alphaOLS = v dot sigma dot u.transpose() dot y + println("Estimated alpha:\n" + + "$alphaOLS") + + // figure out MSE of approximation + fun mse(yTrue: DoubleTensor, yPred: DoubleTensor): Double = DoubleAnalyticTensorAlgebra{ + require(yTrue.shape.size == 1) + require(yTrue.shape contentEquals yPred.shape) + + val diff = yTrue - yPred + diff.dot(diff).sqrt().value() + } + + println("MSE: ${mse(alpha, alphaOLS)}") + } +} \ No newline at end of file From c2db3a23e1e6a14463d3dadac6d279ccabb49272 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 26 Apr 2021 16:24:26 +0100 Subject: [PATCH 132/211] Feedback for SVD --- .../space/kscience/kmath/tensors/OLSWithSVD.kt | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 063a1d1c4..a9b154017 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -9,6 +9,8 @@ import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra +import kotlin.math.abs + // OLS estimator using SVD fun main() { @@ -26,8 +28,7 @@ fun main() { doubleArrayOf(1.0, 2.5, 3.4, 5.0, 10.1) ) - println("Real alpha:\n" + - "$alpha") + println("Real alpha:\n$alpha") // also take sample of size 20 from normal distribution for x TODO rename val x = randNormal( @@ -35,20 +36,22 @@ fun main() { randSeed ) - // calculate y and add gaussian noise (N(0, 0.05)) TODO rename + // calculate y and add gaussian noise (N(0, 0.05)) + // TODO: please add an intercept: Y = beta * X + alpha + N(0,0.5) val y = x dot alpha y += y.randNormalLike(randSeed) * 0.05 // now restore the coefficient vector with OSL estimator with SVD + // TODO: you need to change accordingly [X 1] [alpha beta] = Y + // TODO: inverting [X 1] via SVD val (u, singValues, v) = x.svd() // we have to make sure the singular values of the matrix are not close to zero - println("Singular values:\n" + - "$singValues") - // TODO something with Boolean tensors + println("Singular values:\n$singValues") + // inverse Sigma matrix can be restored from singular values with diagonalEmbedding function - val sigma = diagonalEmbedding(1.0/singValues) + val sigma = diagonalEmbedding(singValues.map{ x -> if (abs(x) < 1e-3) 0.0 else 1.0/x }) val alphaOLS = v dot sigma dot u.transpose() dot y println("Estimated alpha:\n" + From 23ea4a95a151e8ce1a70566a4ede3c7d343e5caa Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 27 Apr 2021 19:01:54 +0100 Subject: [PATCH 133/211] Fixed strides flipping --- .../kmath/tensors/core/BufferedTensor.kt | 23 +++++--- .../kmath/tensors/core/TestDoubleTensor.kt | 58 ++++++++++--------- 2 files changed, 45 insertions(+), 36 deletions(-) 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 1e9b458b1..6e1cab11a 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 @@ -37,9 +37,8 @@ public class IntTensor internal constructor( shape: IntArray, buffer: IntArray, offset: Int = 0 -) : BufferedTensor(shape, IntBuffer(buffer), offset) -{ - internal constructor(bufferedTensor: BufferedTensor): +) : BufferedTensor(shape, IntBuffer(buffer), offset) { + internal constructor(bufferedTensor: BufferedTensor) : this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) } @@ -47,9 +46,8 @@ public class DoubleTensor internal constructor( shape: IntArray, buffer: DoubleArray, offset: Int = 0 -) : BufferedTensor(shape, DoubleBuffer(buffer), offset) -{ - internal constructor(bufferedTensor: BufferedTensor): +) : BufferedTensor(shape, DoubleBuffer(buffer), offset) { + internal constructor(bufferedTensor: BufferedTensor) : this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) override fun toString(): String = toPrettyString() @@ -59,10 +57,17 @@ public class DoubleTensor internal constructor( internal inline fun BufferedTensor.asTensor(): IntTensor = IntTensor(this) internal inline fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this) +internal inline fun TensorStructure.copyToBufferedTensor(): BufferedTensor = + BufferedTensor( + this.shape, + TensorLinearStructure(this.shape).indices().map(this::get).toMutableList().asMutableBuffer(), 0 + ) + internal inline fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { is BufferedTensor -> this - is MutableBufferND -> BufferedTensor(this.shape, this.mutableBuffer, 0) - else -> BufferedTensor(this.shape, this.elements().map{ it.second }.toMutableList().asMutableBuffer(), 0) + is MutableBufferND -> if (this.strides.strides.toIntArray() contentEquals TensorLinearStructure(this.shape).strides) + BufferedTensor(this.shape, this.mutableBuffer, 0) else this.copyToBufferedTensor() + else -> this.copyToBufferedTensor() } internal val TensorStructure.tensor: DoubleTensor @@ -77,3 +82,5 @@ internal val TensorStructure.tensor: IntTensor else -> this.toBufferedTensor().asTensor() } +public fun TensorStructure.toTypedTensor(): DoubleTensor = this.tensor +public fun TensorStructure.toTypedTensor(): IntTensor = this.tensor \ No newline at end of file diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index f9d15c216..7103eafaa 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -23,62 +23,64 @@ class TestDoubleTensor { @Test fun stridesTest() = DoubleTensorAlgebra { - val tensor = fromArray(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) - assertEquals(tensor[intArrayOf(0,1)], 5.8) - assertTrue(tensor.elements().map{ it.second }.toList().toDoubleArray() contentEquals tensor.buffer.toDoubleArray()) + val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) + assertEquals(tensor[intArrayOf(0, 1)], 5.8) + assertTrue( + tensor.elements().map { it.second }.toList().toDoubleArray() contentEquals tensor.buffer.toDoubleArray() + ) } @Test fun getTest() = DoubleTensorAlgebra { - val tensor = fromArray(intArrayOf(1,2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) + val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) val matrix = tensor[0].as2D() - assertEquals(matrix[0,1], 5.8) + assertEquals(matrix[0, 1], 5.8) val vector = tensor[0][1].as1D() assertEquals(vector[0], 58.4) - matrix[0,1] = 77.89 - assertEquals(tensor[intArrayOf(0,0,1)], 77.89) + matrix[0, 1] = 77.89 + assertEquals(tensor[intArrayOf(0, 0, 1)], 77.89) vector[0] = 109.56 - assertEquals(tensor[intArrayOf(0,1,0)], 109.56) + assertEquals(tensor[intArrayOf(0, 1, 0)], 109.56) tensor.matrixSequence().forEach { val a = it.asTensor() val secondRow = a[1].as1D() - val secondColumn = a.transpose(0,1)[1].as1D() + val secondColumn = a.transpose(0, 1)[1].as1D() assertEquals(secondColumn[0], 77.89) assertEquals(secondRow[1], secondColumn[1]) } } @Test - fun bufferProtocol() { + fun noBufferProtocol() { - // create buffers - val doubleBuffer = DoubleBuffer(doubleArrayOf(1.0,2.0,3.0)) - val doubleList = MutableList(3, doubleBuffer::get) + // create buffer + val doubleArray = DoubleBuffer(doubleArrayOf(1.0, 2.0, 3.0)) - // create ND buffers - val ndBuffer = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleBuffer) - val ndList = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleList.asMutableBuffer()) + // create ND buffers, no data is copied + val ndArray = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleArray) // map to tensors - val bufferedTensorBuffer = ndBuffer.toBufferedTensor() // strides are flipped - val tensorBuffer = bufferedTensorBuffer.asTensor() // no data copied + val bufferedTensorArray = ndArray.toBufferedTensor() // strides are flipped so data copied + val tensorArray = bufferedTensorArray.asTensor() // data not contiguous so copied again - val bufferedTensorList = ndList.toBufferedTensor() // strides are flipped - val tensorList = bufferedTensorList.asTensor() // data copied + val tensorArrayPublic = ndArray.toTypedTensor() // public API, data copied twice + val sharedTensorArray = tensorArrayPublic.toTypedTensor() // no data copied by matching type - tensorBuffer[intArrayOf(0)] = 55.9 - assertEquals(ndBuffer[intArrayOf(0)], 55.9) - assertEquals(doubleBuffer[0], 55.9) + assertTrue(tensorArray.buffer.array() contentEquals sharedTensorArray.buffer.array()) - tensorList[intArrayOf(0)] = 55.9 - assertEquals(ndList[intArrayOf(0)], 1.0) - assertEquals(doubleList[0], 1.0) + tensorArray[intArrayOf(0)] = 55.9 + assertEquals(tensorArrayPublic[intArrayOf(0)], 1.0) + + tensorArrayPublic[intArrayOf(0)] = 55.9 + assertEquals(sharedTensorArray[intArrayOf(0)], 55.9) + assertEquals(bufferedTensorArray[intArrayOf(0)], 1.0) + + bufferedTensorArray[intArrayOf(0)] = 55.9 + assertEquals(ndArray[intArrayOf(0)], 1.0) - ndList[intArrayOf(0)] = 55.9 - assertEquals(doubleList[0], 55.9) } } \ No newline at end of file From e3f7b7a5fa560d4084a16a611b0266576d1e5728 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 28 Apr 2021 10:25:03 +0700 Subject: [PATCH 134/211] Promote kmath-ast as experimental, mark AST Rendering and WASM with @UnstableKMathAPI --- kmath-ast/build.gradle.kts | 6 +- .../kotlin/space/kscience/kmath/ast/parser.kt | 1 - .../ast/rendering/LatexSyntaxRenderer.kt | 3 + .../ast/rendering/MathMLSyntaxRenderer.kt | 5 +- .../kmath/ast/rendering/MathRenderer.kt | 4 + .../kmath/ast/rendering/MathSyntax.kt | 25 ++ .../kmath/ast/rendering/SyntaxRenderer.kt | 4 + .../kscience/kmath/ast/rendering/features.kt | 280 ++++++++++++------ .../kscience/kmath/ast/rendering/stages.kt | 4 + .../kmath/ast/ParserPrecedenceTest.kt | 1 - .../kscience/kmath/ast/rendering/TestUtils.kt | 6 +- .../nonDeclarations.WebAssembly.kt | 3 +- .../kmath/wasm/internal/WasmBuilder.kt | 2 +- .../kotlin/space/kscience/kmath/wasm/wasm.kt | 9 + .../kscience/kmath/asm/internal/AsmBuilder.kt | 4 +- .../kmath/asm/internal/codegenUtils.kt | 2 +- 16 files changed, 259 insertions(+), 100 deletions(-) diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index b4a0b28ac..508374d82 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -18,6 +18,10 @@ kotlin.js { } kotlin.sourceSets { + filter { it.name.contains("test", true) } + .map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings) + .forEach { it.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") } + commonMain { dependencies { api("com.github.h0tk3y.betterParse:better-parse:0.4.2") @@ -54,7 +58,7 @@ tasks.dokkaHtml { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt index d2e92c37f..246625d29 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt @@ -29,7 +29,6 @@ import space.kscience.kmath.operations.RingOperations * @author Iaroslav Postovalov */ public object ArithmeticsEvaluator : Grammar() { - // TODO replace with "...".toRegex() when better-parse 0.4.1 is released private val num: Token by regexToken("[\\d.]+(?:[eE][-+]?\\d+)?".toRegex()) private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*".toRegex()) private val lpar: Token by literalToken("(") diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt index 1c82bd6e7..5909f1f9d 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -5,6 +5,8 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI + /** * [SyntaxRenderer] implementation for LaTeX. * @@ -23,6 +25,7 @@ package space.kscience.kmath.ast.rendering * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object LatexSyntaxRenderer : SyntaxRenderer { public override fun render(node: MathSyntax, output: Appendable): Unit = output.run { fun render(syntax: MathSyntax) = render(syntax, output) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index decd4ba46..517ec0dc9 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -5,6 +5,8 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI + /** * [SyntaxRenderer] implementation for MathML. * @@ -12,9 +14,10 @@ package space.kscience.kmath.ast.rendering * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object MathMLSyntaxRenderer : SyntaxRenderer { public override fun render(node: MathSyntax, output: Appendable) { - output.append("") + output.append("") render0(node, output) output.append("") } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index 9df2c54dd..6b22ac519 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -6,12 +6,14 @@ package space.kscience.kmath.ast.rendering import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.UnstableKMathAPI /** * Renders [MST] to [MathSyntax]. * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun interface MathRenderer { /** * Renders [MST] to [MathSyntax]. @@ -25,6 +27,7 @@ public fun interface MathRenderer { * @property features The applied features. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public open class FeaturedMathRenderer(public val features: List) : MathRenderer { public override fun render(mst: MST): MathSyntax { for (feature in features) feature.render(this, mst)?.let { return it } @@ -48,6 +51,7 @@ public open class FeaturedMathRenderer(public val features: List) * @property stages The applied stages. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public open class FeaturedMathRendererWithPostProcess( features: List, public val stages: List, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt index 6a46bf535..3c023e342 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -5,11 +5,14 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI + /** * Mathematical typography syntax node. * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class MathSyntax { /** * The parent node of this syntax node. @@ -22,6 +25,7 @@ public sealed class MathSyntax { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class TerminalSyntax : MathSyntax() /** @@ -29,6 +33,7 @@ public sealed class TerminalSyntax : MathSyntax() * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class OperationSyntax : MathSyntax() { /** * The operation token. @@ -41,6 +46,7 @@ public sealed class OperationSyntax : MathSyntax() { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class UnarySyntax : OperationSyntax() { /** * The operand of this node. @@ -53,6 +59,7 @@ public sealed class UnarySyntax : OperationSyntax() { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class BinarySyntax : OperationSyntax() { /** * The left-hand side operand. @@ -71,6 +78,7 @@ public sealed class BinarySyntax : OperationSyntax() { * @property string The digits of number. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class NumberSyntax(public var string: String) : TerminalSyntax() /** @@ -79,6 +87,7 @@ public data class NumberSyntax(public var string: String) : TerminalSyntax() * @property string The symbol. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class SymbolSyntax(public var string: String) : TerminalSyntax() /** @@ -89,6 +98,7 @@ public data class SymbolSyntax(public var string: String) : TerminalSyntax() * @see UnaryOperatorSyntax * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class OperatorNameSyntax(public var name: String) : TerminalSyntax() /** @@ -97,6 +107,7 @@ public data class OperatorNameSyntax(public var name: String) : TerminalSyntax() * @property kind The kind of symbol. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() { /** * The kind of symbol. @@ -121,6 +132,7 @@ public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() * @property parentheses Whether the operand should be wrapped with parentheses. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class OperandSyntax( public val operand: MathSyntax, public var parentheses: Boolean, @@ -136,6 +148,7 @@ public data class OperandSyntax( * @property prefix The prefix. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class UnaryOperatorSyntax( public override val operation: String, public var prefix: MathSyntax, @@ -151,6 +164,7 @@ public data class UnaryOperatorSyntax( * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class UnaryPlusSyntax( public override val operation: String, public override val operand: OperandSyntax, @@ -165,6 +179,7 @@ public data class UnaryPlusSyntax( * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class UnaryMinusSyntax( public override val operation: String, public override val operand: OperandSyntax, @@ -180,6 +195,7 @@ public data class UnaryMinusSyntax( * @property operand The radicand. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class RadicalSyntax( public override val operation: String, public override val operand: MathSyntax, @@ -197,6 +213,7 @@ public data class RadicalSyntax( * (*ex*). * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class ExponentSyntax( public override val operation: String, public override val operand: OperandSyntax, @@ -214,6 +231,7 @@ public data class ExponentSyntax( * @property right The superscript. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class SuperscriptSyntax( public override val operation: String, public override val left: MathSyntax, @@ -232,6 +250,7 @@ public data class SuperscriptSyntax( * @property right The subscript. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class SubscriptSyntax( public override val operation: String, public override val left: MathSyntax, @@ -249,6 +268,7 @@ public data class SubscriptSyntax( * @property prefix The prefix. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class BinaryOperatorSyntax( public override val operation: String, public var prefix: MathSyntax, @@ -268,6 +288,7 @@ public data class BinaryOperatorSyntax( * @param right The addend. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class BinaryPlusSyntax( public override val operation: String, public override val left: OperandSyntax, @@ -286,6 +307,7 @@ public data class BinaryPlusSyntax( * @param right The subtrahend. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class BinaryMinusSyntax( public override val operation: String, public override val left: OperandSyntax, @@ -304,6 +326,7 @@ public data class BinaryMinusSyntax( * @property right The denominator. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class FractionSyntax( public override val operation: String, public override val left: MathSyntax, @@ -322,6 +345,7 @@ public data class FractionSyntax( * @property right The radicand. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class RadicalWithIndexSyntax( public override val operation: String, public override val left: MathSyntax, @@ -341,6 +365,7 @@ public data class RadicalWithIndexSyntax( * @property times whether the times (×) symbol should be used. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class MultiplicationSyntax( public override val operation: String, public override val left: OperandSyntax, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt index 7fa91e158..fb2b3b66f 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt @@ -5,12 +5,15 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI + /** * Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should * involve traversal of MathSyntax with handling each its subtype. * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun interface SyntaxRenderer { /** * Renders the [MathSyntax] to [output]. @@ -23,6 +26,7 @@ public fun interface SyntaxRenderer { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun SyntaxRenderer.renderWithStringBuilder(node: MathSyntax): String { val sb = StringBuilder() render(node, sb) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index c09282bb6..c1b513345 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -7,6 +7,7 @@ package space.kscience.kmath.ast.rendering import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import kotlin.reflect.KClass @@ -15,11 +16,12 @@ import kotlin.reflect.KClass * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object PrintSymbolic : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Symbolic) return null - return SymbolSyntax(string = node.value) - } + public override fun render(renderer: FeaturedMathRenderer, node: MST): SymbolSyntax? = + if (node !is MST.Symbolic) null + else + SymbolSyntax(string = node.value) } /** @@ -27,25 +29,25 @@ public object PrintSymbolic : RenderFeature { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object PrintNumeric : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Numeric) return null - return NumberSyntax(string = node.value.toString()) - } + public override fun render(renderer: FeaturedMathRenderer, node: MST): NumberSyntax? = if (node !is MST.Numeric) + null + else + NumberSyntax(string = node.value.toString()) } -private fun printSignedNumberString(s: String): MathSyntax { - if (s.startsWith('-')) - return UnaryMinusSyntax( - operation = GroupOperations.MINUS_OPERATION, - operand = OperandSyntax( - operand = NumberSyntax(string = s.removePrefix("-")), - parentheses = true, - ), - ) - - return NumberSyntax(string = s) -} +@UnstableKMathAPI +private fun printSignedNumberString(s: String): MathSyntax = if (s.startsWith('-')) + UnaryMinusSyntax( + operation = GroupOperations.MINUS_OPERATION, + operand = OperandSyntax( + operand = NumberSyntax(string = s.removePrefix("-")), + parentheses = true, + ), + ) +else + NumberSyntax(string = s) /** * Special printing for numeric types which are printed in form of @@ -53,9 +55,11 @@ private fun printSignedNumberString(s: String): MathSyntax { * * @property types The suitable types. */ +@UnstableKMathAPI public class PrettyPrintFloats(public val types: Set>) : RenderFeature { public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { if (node !is MST.Numeric || node.value::class !in types) return null + val toString = when (val v = node.value) { is Float -> v.multiplatformToString() is Double -> v.multiplatformToString() @@ -110,11 +114,13 @@ public class PrettyPrintFloats(public val types: Set>) : Rend * * @property types The suitable types. */ +@UnstableKMathAPI public class PrettyPrintIntegers(public val types: Set>) : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Numeric || node.value::class !in types) return null - return printSignedNumberString(node.value.toString()) - } + public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? = + if (node !is MST.Numeric || node.value::class !in types) + null + else + printSignedNumberString(node.value.toString()) public companion object { /** @@ -130,11 +136,13 @@ public class PrettyPrintIntegers(public val types: Set>) : Re * * @property symbols The allowed symbols. */ +@UnstableKMathAPI public class PrettyPrintPi(public val symbols: Set) : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Symbolic || node.value !in symbols) return null - return SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI) - } + public override fun render(renderer: FeaturedMathRenderer, node: MST): SpecialSymbolSyntax? = + if (node !is MST.Symbolic || node.value !in symbols) + null + else + SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI) public companion object { /** @@ -150,16 +158,18 @@ public class PrettyPrintPi(public val symbols: Set) : RenderFeature { * * @param operations the allowed operations. If `null`, any operation is accepted. */ +@UnstableKMathAPI public abstract class Unary(public val operations: Collection?) : RenderFeature { /** - * The actual render function. + * The actual render function specialized for [MST.Unary]. */ - protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax? + protected abstract fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax? - public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Unary || operations != null && node.operation !in operations) return null - return render0(renderer, node) - } + public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? = + if (node !is MST.Unary || operations != null && node.operation !in operations) + null + else + renderUnary(renderer, node) } /** @@ -168,164 +178,258 @@ public abstract class Unary(public val operations: Collection?) : Render * * @property operations the allowed operations. If `null`, any operation is accepted. */ +@UnstableKMathAPI public abstract class Binary(public val operations: Collection?) : RenderFeature { /** - * The actual render function. + * The actual render function specialized for [MST.Binary]. */ - protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax? + protected abstract fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax? public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { if (node !is MST.Binary || operations != null && node.operation !in operations) return null - return render0(renderer, node) + return renderBinary(renderer, node) } } +/** + * Handles binary nodes by producing [BinaryPlusSyntax]. + */ +@UnstableKMathAPI public class BinaryPlus(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryPlusSyntax( - operation = node.operation, - left = OperandSyntax(parent.render(node.left), true), - right = OperandSyntax(parent.render(node.right), true), - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryPlusSyntax = + BinaryPlusSyntax( + operation = node.operation, + left = OperandSyntax(parent.render(node.left), true), + right = OperandSyntax(parent.render(node.right), true), + ) public companion object { + /** + * The default instance configured with [GroupOperations.PLUS_OPERATION]. + */ public val Default: BinaryPlus = BinaryPlus(setOf(GroupOperations.PLUS_OPERATION)) } } +/** + * Handles binary nodes by producing [BinaryMinusSyntax]. + */ +@UnstableKMathAPI public class BinaryMinus(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryMinusSyntax( - operation = node.operation, - left = OperandSyntax(operand = parent.render(node.left), parentheses = true), - right = OperandSyntax(operand = parent.render(node.right), parentheses = true), - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryMinusSyntax = + BinaryMinusSyntax( + operation = node.operation, + left = OperandSyntax(operand = parent.render(node.left), parentheses = true), + right = OperandSyntax(operand = parent.render(node.right), parentheses = true), + ) public companion object { + /** + * The default instance configured with [GroupOperations.MINUS_OPERATION]. + */ public val Default: BinaryMinus = BinaryMinus(setOf(GroupOperations.MINUS_OPERATION)) } } +/** + * Handles unary nodes by producing [UnaryPlusSyntax]. + */ +@UnstableKMathAPI public class UnaryPlus(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax( + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryPlusSyntax = UnaryPlusSyntax( operation = node.operation, operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), ) public companion object { + /** + * The default instance configured with [GroupOperations.PLUS_OPERATION]. + */ public val Default: UnaryPlus = UnaryPlus(setOf(GroupOperations.PLUS_OPERATION)) } } +/** + * Handles binary nodes by producing [UnaryMinusSyntax]. + */ +@UnstableKMathAPI public class UnaryMinus(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax( + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryMinusSyntax = UnaryMinusSyntax( operation = node.operation, operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), ) public companion object { + /** + * The default instance configured with [GroupOperations.MINUS_OPERATION]. + */ public val Default: UnaryMinus = UnaryMinus(setOf(GroupOperations.MINUS_OPERATION)) } } +/** + * Handles binary nodes by producing [FractionSyntax]. + */ +@UnstableKMathAPI public class Fraction(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax( + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = FractionSyntax( operation = node.operation, left = parent.render(node.left), right = parent.render(node.right), ) public companion object { + /** + * The default instance configured with [FieldOperations.DIV_OPERATION]. + */ public val Default: Fraction = Fraction(setOf(FieldOperations.DIV_OPERATION)) } } +/** + * Handles binary nodes by producing [BinaryOperatorSyntax]. + */ +@UnstableKMathAPI public class BinaryOperator(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryOperatorSyntax( - operation = node.operation, - prefix = OperatorNameSyntax(name = node.operation), - left = parent.render(node.left), - right = parent.render(node.right), - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryOperatorSyntax = + BinaryOperatorSyntax( + operation = node.operation, + prefix = OperatorNameSyntax(name = node.operation), + left = parent.render(node.left), + right = parent.render(node.right), + ) public companion object { + /** + * The default instance configured with `null`. + */ public val Default: BinaryOperator = BinaryOperator(null) } } +/** + * Handles unary nodes by producing [UnaryOperatorSyntax]. + */ +@UnstableKMathAPI public class UnaryOperator(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( - operation = node.operation, - prefix = OperatorNameSyntax(node.operation), - operand = OperandSyntax(parent.render(node.value), true), - ) + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = + UnaryOperatorSyntax( + operation = node.operation, + prefix = OperatorNameSyntax(node.operation), + operand = OperandSyntax(parent.render(node.value), true), + ) public companion object { + /** + * The default instance configured with `null`. + */ public val Default: UnaryOperator = UnaryOperator(null) } } +/** + * Handles binary nodes by producing [SuperscriptSyntax]. + */ +@UnstableKMathAPI public class Power(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = SuperscriptSyntax( - operation = node.operation, - left = OperandSyntax(parent.render(node.left), true), - right = OperandSyntax(parent.render(node.right), true), - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): SuperscriptSyntax = + SuperscriptSyntax( + operation = node.operation, + left = OperandSyntax(parent.render(node.left), true), + right = OperandSyntax(parent.render(node.right), true), + ) public companion object { + /** + * The default instance configured with [PowerOperations.POW_OPERATION]. + */ public val Default: Power = Power(setOf(PowerOperations.POW_OPERATION)) } } +/** + * Handles binary nodes by producing [RadicalSyntax] with no index. + */ +@UnstableKMathAPI public class SquareRoot(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): RadicalSyntax = RadicalSyntax(operation = node.operation, operand = parent.render(node.value)) public companion object { + /** + * The default instance configured with [PowerOperations.SQRT_OPERATION]. + */ public val Default: SquareRoot = SquareRoot(setOf(PowerOperations.SQRT_OPERATION)) } } +/** + * Handles unary nodes by producing [ExponentSyntax]. + */ +@UnstableKMathAPI public class Exponent(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax( + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): ExponentSyntax = ExponentSyntax( operation = node.operation, operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), useOperatorForm = true, ) public companion object { + /** + * The default instance configured with [ExponentialOperations.EXP_OPERATION]. + */ public val Default: Exponent = Exponent(setOf(ExponentialOperations.EXP_OPERATION)) } } +/** + * Handles binary nodes by producing [MultiplicationSyntax]. + */ +@UnstableKMathAPI public class Multiplication(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = MultiplicationSyntax( - operation = node.operation, - left = OperandSyntax(operand = parent.render(node.left), parentheses = true), - right = OperandSyntax(operand = parent.render(node.right), parentheses = true), - times = true, - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MultiplicationSyntax = + MultiplicationSyntax( + operation = node.operation, + left = OperandSyntax(operand = parent.render(node.left), parentheses = true), + right = OperandSyntax(operand = parent.render(node.right), parentheses = true), + times = true, + ) public companion object { - public val Default: Multiplication = Multiplication(setOf( - RingOperations.TIMES_OPERATION, - )) + /** + * The default instance configured with [RingOperations.TIMES_OPERATION]. + */ + public val Default: Multiplication = Multiplication(setOf(RingOperations.TIMES_OPERATION)) } } +/** + * Handles binary nodes by producing inverse [UnaryOperatorSyntax] (like *sin-1*) with removing the `a` + * prefix of operation ID. + */ +@UnstableKMathAPI public class InverseTrigonometricOperations(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( - operation = node.operation, - prefix = SuperscriptSyntax( - operation = PowerOperations.POW_OPERATION, - left = OperatorNameSyntax(name = node.operation.removePrefix("a")), - right = UnaryMinusSyntax( - operation = GroupOperations.MINUS_OPERATION, - operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true), + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = + UnaryOperatorSyntax( + operation = node.operation, + prefix = SuperscriptSyntax( + operation = PowerOperations.POW_OPERATION, + left = OperatorNameSyntax(name = node.operation.removePrefix("a")), + right = UnaryMinusSyntax( + operation = GroupOperations.MINUS_OPERATION, + operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true), + ), ), - ), - operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), - ) + operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), + ) public companion object { + /** + * The default instance configured with [TrigonometricOperations.ACOS_OPERATION], + * [TrigonometricOperations.ASIN_OPERATION], [TrigonometricOperations.ATAN_OPERATION], + * [ExponentialOperations.ACOSH_OPERATION], [ExponentialOperations.ASINH_OPERATION], and + * [ExponentialOperations.ATANH_OPERATION]. + */ public val Default: InverseTrigonometricOperations = InverseTrigonometricOperations(setOf( TrigonometricOperations.ACOS_OPERATION, TrigonometricOperations.ASIN_OPERATION, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt index a08f089f1..7eb75b9ff 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.FieldOperations import space.kscience.kmath.operations.GroupOperations import space.kscience.kmath.operations.PowerOperations @@ -15,6 +16,7 @@ import space.kscience.kmath.operations.RingOperations * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage { public override fun perform(node: MathSyntax): Unit = when (node) { is NumberSyntax -> Unit @@ -88,6 +90,7 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage { private fun perform0(node: MathSyntax): Boolean { return when (node) { @@ -129,6 +132,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt * @property precedenceFunction Returns the precedence number for syntax node. Higher number is lower priority. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) : FeaturedMathRendererWithPostProcess.PostProcessStage { public override fun perform(node: MathSyntax): Unit = when (node) { diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt index ca3a95bc8..67d77839a 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.ast -import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.evaluate import space.kscience.kmath.operations.DoubleField import kotlin.test.Test diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt index 7c9400532..bf87b6fd0 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt @@ -30,17 +30,17 @@ internal object TestUtils { ) internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", + expected = "$expectedMathML", actual = mathML(mst), ) internal fun testMathML(expression: String, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", + expected = "$expectedMathML", actual = mathML(expression.parseMath()), ) internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", + expected = "$expectedMathML", actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression), ) } diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt index 59733299a..c5023c384 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt @@ -3,7 +3,8 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -@file:Suppress("INTERFACE_WITH_SUPERCLASS", +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt index bd2b340a0..8fd3c9fb9 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -26,7 +26,7 @@ internal sealed class WasmBuilder( val keys: MutableList = mutableListOf() lateinit var ctx: BinaryenModule - open fun visitSymbolic(mst: MST.Symbolic): ExpressionRef { + open fun visitSymbolic(mst: Symbolic): ExpressionRef { try { algebra.bindSymbol(mst.value) } catch (ignored: Throwable) { diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt index d44c4e49d..394a0567e 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt @@ -10,6 +10,7 @@ import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.invoke import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing import space.kscience.kmath.wasm.internal.DoubleWasmBuilder @@ -20,6 +21,7 @@ import space.kscience.kmath.wasm.internal.IntWasmBuilder * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun DoubleField.expression(mst: MST): Expression = DoubleWasmBuilder(mst).instance @@ -28,6 +30,7 @@ public fun DoubleField.expression(mst: MST): Expression = * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun IntRing.expression(mst: MST): Expression = IntWasmBuilder(mst).instance @@ -36,6 +39,7 @@ public fun IntRing.expression(mst: MST): Expression = * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compileToExpression(algebra: IntRing): Expression = compileWith(algebra) @@ -44,6 +48,7 @@ public fun MST.compileToExpression(algebra: IntRing): Expression = compileW * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compile(algebra: IntRing, arguments: Map): Int = compileToExpression(algebra).invoke(arguments) @@ -53,6 +58,7 @@ public fun MST.compile(algebra: IntRing, arguments: Map): Int = * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compile(algebra: IntRing, vararg arguments: Pair): Int = compileToExpression(algebra)(*arguments) @@ -61,6 +67,7 @@ public fun MST.compile(algebra: IntRing, vararg arguments: Pair): I * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compileToExpression(algebra: DoubleField): Expression = compileWith(algebra) @@ -69,6 +76,7 @@ public fun MST.compileToExpression(algebra: DoubleField): Expression = c * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compile(algebra: DoubleField, arguments: Map): Double = compileToExpression(algebra).invoke(arguments) @@ -78,5 +86,6 @@ public fun MST.compile(algebra: DoubleField, arguments: Map): Do * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compile(algebra: DoubleField, vararg arguments: Pair): Double = compileToExpression(algebra).invoke(*arguments) diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt index bdd8f52b6..39ebf049d 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt @@ -342,8 +342,8 @@ internal class AsmBuilder( val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("space/kscience/kmath/asm/internal/MapIntrinsics") } /** - * ASM Type for [kscience.kmath.expressions.Symbol]. + * ASM Type for [space.kscience.kmath.misc.Symbol]. */ - val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Symbol") } + val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/misc/Symbol") } } } diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt index 560780f99..cfac59847 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt @@ -52,7 +52,7 @@ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.( * * @author Iaroslav Postovalov */ -internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) } +internal fun MethodVisitor.label(): Label = Label().also(::visitLabel) /** * Creates a class name for [Expression] subclassed to implement [mst] provided. From b65a673173e6b1cd209fa355349bf9b90f718887 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 28 Apr 2021 14:16:57 +0100 Subject: [PATCH 135/211] Fix format for 0.0 --- .../kotlin/space/kscience/kmath/tensors/core/utils.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 89e9d0d96..cb23dbdd6 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -47,17 +47,17 @@ internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexF internal inline fun format(value: Double, digits: Int = 4): String { val ten = 10.0 - val approxOrder = ceil(log10(abs(value))).toInt() + val approxOrder = if(value == 0.0) 0 else ceil(log10(abs(value))).toInt() val order = if( ((value % ten) == 0.0) or (value == 1.0) or ((1/value) % ten == 0.0)) approxOrder else approxOrder - 1 - val lead = value / ten.pow(order) val leadDisplay = round(lead*ten.pow(digits)) / ten.pow(digits) val orderDisplay = if(order == 0) "" else if(order > 0) "E+$order" else "E$order" val valueDisplay = "$leadDisplay$orderDisplay" val res = if(value < 0.0) valueDisplay else " $valueDisplay" + val fLength = digits + 6 val endSpace = " ".repeat(fLength - res.length) return "$res$endSpace" From a0e9180db6da06c2cdac36a25c4b44d951945850 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 28 Apr 2021 18:18:57 +0300 Subject: [PATCH 136/211] example with LUP --- .../tensors/LinearSystemSolvingWithLUP.kt | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt new file mode 100644 index 000000000..526b6781f --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -0,0 +1,97 @@ +/* + * 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 + +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra + +// solving linear system with LUP decomposition + +fun main () { + + // work in context with linear operations + DoubleLinearOpsTensorAlgebra { + + // set true value of x + val trueX = fromArray( + intArrayOf(4), + doubleArrayOf(-2.0, 1.5, 6.8, -2.4) + ) + + // and A matrix + val a = fromArray( + intArrayOf(4, 4), + doubleArrayOf( + 0.5, 10.5, 4.5, 1.0, + 8.5, 0.9, 12.8, 0.1, + 5.56, 9.19, 7.62, 5.45, + 1.0, 2.0, -3.0, -2.5 + ) + ) + + // calculate y value + val b = a dot trueX + + // check out A and b + println("A:\n$a") + println("b:\n$b") + + // solve `Ax = b` system using LUP decomposition + + // get P, L, U such that PA = LU + val (lu, pivots) = a.lu() + val (p, l, u) = luPivot(lu, pivots) + + // check that P is permutation matrix + println("P:\n$p") + // L is lower triangular matrix and U is upper triangular matrix + println("L:\n$l") + println("U:\n$u") + // and PA = LU + println("PA:\n${p dot a}") + println("LU:\n${l dot u}") + + /* Ax = b; + PAx = Pb; + LUx = Pb; + let y = Ux, then + Ly = Pb -- this system can be easily solved, since the matrix L is lower triangular; + Ux = y can be solved the same way, since the matrix L is upper triangular + */ + + + + // this function returns solution x of a system lx = b, l should be lower triangular + fun solveLT(l: DoubleTensor, b: DoubleTensor): DoubleTensor { + val n = l.shape[0] + val x = zeros(intArrayOf(n)) + for (i in 0 until n){ + x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)] + } + return x + } + + val y = solveLT(l, p dot b) + + // solveLT(l, b) function can be easily adapted for upper triangular matrix by the permutation matrix revMat + // create it by placing ones on side diagonal + val revMat = u.zeroesLike() + val n = revMat.shape[0] + for (i in 0 until n) { + revMat[intArrayOf(i, n - 1 - i)] = 1.0 + } + + // solution of system ux = b, u should be upper triangular + fun solveUT(u: DoubleTensor, b: DoubleTensor): DoubleTensor = revMat dot solveLT( + revMat dot u dot revMat, revMat dot b + ) + + val x = solveUT(u, y) + + println("True x:\n$trueX") + println("x founded with LU method:\n$x") + } +} \ No newline at end of file From 51f084d28be21118c403ce5ae29775ab894971ae Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 28 Apr 2021 17:07:10 +0100 Subject: [PATCH 137/211] merge PR --- .../main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index a9b154017..9318fe928 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -30,20 +30,17 @@ fun main() { println("Real alpha:\n$alpha") - // also take sample of size 20 from normal distribution for x TODO rename + // also take sample of size 20 from normal distribution for x val x = randNormal( intArrayOf(20, 5), randSeed ) // calculate y and add gaussian noise (N(0, 0.05)) - // TODO: please add an intercept: Y = beta * X + alpha + N(0,0.5) val y = x dot alpha y += y.randNormalLike(randSeed) * 0.05 // now restore the coefficient vector with OSL estimator with SVD - // TODO: you need to change accordingly [X 1] [alpha beta] = Y - // TODO: inverting [X 1] via SVD val (u, singValues, v) = x.svd() // we have to make sure the singular values of the matrix are not close to zero From 6f5b0f0a03e941b33d4adc22e341bce2f7d8bd00 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 29 Apr 2021 17:09:50 +0300 Subject: [PATCH 138/211] add README and documentation for the main functions of tensor algebra --- README.md | 12 + kmath-tensors/README.md | 37 +++ kmath-tensors/build.gradle.kts | 26 ++- kmath-tensors/docs/README-TEMPLATE.md | 7 + .../tensors/api/LinearOpsTensorAlgebra.kt | 84 ++++++- .../kmath/tensors/api/TensorAlgebra.kt | 211 +++++++++++++++++- .../algebras/BroadcastDoubleTensorAlgebra.kt | 4 + 7 files changed, 365 insertions(+), 16 deletions(-) create mode 100644 kmath-tensors/README.md create mode 100644 kmath-tensors/docs/README-TEMPLATE.md diff --git a/README.md b/README.md index 773eb6398..19c59e79e 100644 --- a/README.md +++ b/README.md @@ -230,6 +230,18 @@ One can still use generic algebras though. > **Maturity**: EXPERIMENTAL
+* ### [kmath-tensors](kmath-tensors) +> +> +> **Maturity**: PROTOTYPE +> +> **Features:** +> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) +> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. +> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. + +
+ * ### [kmath-viktor](kmath-viktor) > > diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md new file mode 100644 index 000000000..3b82829f0 --- /dev/null +++ b/kmath-tensors/README.md @@ -0,0 +1,37 @@ +# Module kmath-tensors + +Common linear algebra operations on tensors. + + - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) + - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. + - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. + + +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-7`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap +} + +dependencies { + implementation 'space.kscience:kmath-tensors:0.3.0-dev-7' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + maven("https://dl.bintray.com/hotkeytlt/maven") // required for a +} + +dependencies { + implementation("space.kscience:kmath-tensors:0.3.0-dev-7") +} +``` diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts index 8e823416b..af5116022 100644 --- a/kmath-tensors/build.gradle.kts +++ b/kmath-tensors/build.gradle.kts @@ -11,6 +11,30 @@ kotlin.sourceSets { } } +tasks.dokkaHtml { + dependsOn(tasks.build) +} + readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + + feature( + id = "tensor algebra", + description = "Basic linear algebra operations on tensors (plus, dot, etc.)", + ref = "src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt" + ) + + feature( + id = "tensor algebra with broadcasting", + description = "Basic linear algebra operations implemented with broadcasting.", + ref = "src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt" + ) + + feature( + id = "linear algebra operations", + description = "Advanced linear algebra operations like LU decomposition, SVD, etc.", + ref = "src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt" + ) + } \ No newline at end of file diff --git a/kmath-tensors/docs/README-TEMPLATE.md b/kmath-tensors/docs/README-TEMPLATE.md new file mode 100644 index 000000000..5fd968afd --- /dev/null +++ b/kmath-tensors/docs/README-TEMPLATE.md @@ -0,0 +1,7 @@ +# Module kmath-tensors + +Common linear algebra operations on tensors. + +${features} + +${artifact} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 5cd48ca78..6735efacb 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -5,33 +5,99 @@ package space.kscience.kmath.tensors.api - +/** + * Common linear algebra operations. Operates on [TensorStructure]. + * + * @param T the type of items in the tensors. + */ public interface LinearOpsTensorAlgebra : TensorPartialDivisionAlgebra { - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det + /** + * Computes the determinant of a square matrix input, or of each square matrix in a batched input. + * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.det + * + * @return the determinant. + */ public fun TensorStructure.det(): TensorStructure - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv + /** + * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input. + * Given a square matrix `a`, return the matrix `aInv` satisfying + * ``a.dot(aInv) = aInv.dot(a) = eye(a.shape[0])``. + * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv + * + * @return the multiplicative inverse of a matrix. + */ public fun TensorStructure.inv(): TensorStructure - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.cholesky + /** + * Cholesky decomposition. + * + * Computes the Cholesky decomposition of a Hermitian (or symmetric for real-valued matrices) + * positive-definite matrix or the Cholesky decompositions for a batch of such matrices. + * Each decomposition has the form: + * Given a tensor `input`, return the tensor `L` satisfying ``input = L * L.H``, + * where L is a lower-triangular matrix and L.H is the conjugate transpose of L, + * which is just a transpose for the case of real-valued input matrices. + * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.cholesky + * + * @return the batch of L matrices. + */ public fun TensorStructure.cholesky(): TensorStructure - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr + /** + * QR decomposition. + * + * Computes the QR decomposition of a matrix or a batch of matrices, and returns a namedtuple `(Q, R)` of tensors. + * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q * R``, + * with `Q` being an orthogonal matrix or batch of orthogonal matrices + * and `R` being an upper triangular matrix or batch of upper triangular matrices. + * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr + * + * @return tuple of Q and R tensors. + */ public fun TensorStructure.qr(): Pair, TensorStructure> - //https://pytorch.org/docs/stable/generated/torch.lu.html + /** + * TODO('Andrew') + * For more information: https://pytorch.org/docs/stable/generated/torch.lu.html + * + * @return ... + */ public fun TensorStructure.lu(): Pair, TensorStructure> - //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html + /** + * TODO('Andrew') + * For more information: https://pytorch.org/docs/stable/generated/torch.lu_unpack.html + * + * @param luTensor ... + * @param pivotsTensor ... + * @return ... + */ public fun luPivot(luTensor: TensorStructure, pivotsTensor: TensorStructure): Triple, TensorStructure, TensorStructure> - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd + /** + * Singular Value Decomposition. + * + * Computes the singular value decomposition of either a matrix or batch of matrices `input`. + * The singular value decomposition is represented as a namedtuple `(U, S, V)`, + * such that ``input = U.dot(diagonalEmbedding(S).dot(V.T))``. + * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. + * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd + * + * @return the determinant. + */ public fun TensorStructure.svd(): Triple, TensorStructure, TensorStructure> - //https://pytorch.org/docs/stable/generated/torch.symeig.html + /** + * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, + * represented by a namedtuple (eigenvalues, eigenvectors). + * For more information: https://pytorch.org/docs/stable/generated/torch.symeig.html + * + * @return a namedtuple (eigenvalues, eigenvectors) + */ public fun TensorStructure.symEig(): Pair, TensorStructure> } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index c1657d916..92aafb8ea 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -5,44 +5,243 @@ package space.kscience.kmath.tensors.api -// https://proofwiki.org/wiki/Definition:Algebra_over_Ring +/** + * Basic linear algebra operations on [TensorStructure]. + * For more information: https://proofwiki.org/wiki/Definition:Algebra_over_Ring + * + * @param T the type of items in the tensors. + */ public interface TensorAlgebra { + /** + * Returns a single tensor value of unit dimension. The tensor shape must be equal to [1]. + * + * @return the value of a scalar tensor. + */ public fun TensorStructure.value(): T + /** + * Each element of the tensor [other] is added to this value. + * The resulting tensor is returned. + * + * @param other tensor to be added. + * @return the sum of this value and tensor [other]. + */ public operator fun T.plus(other: TensorStructure): TensorStructure + + /** + * Adds the scalar [value] to each element of this tensor and returns a new resulting tensor. + * + * @param value the number to be added to each element of this tensor. + * @return the sum of this tensor and [value]. + */ public operator fun TensorStructure.plus(value: T): TensorStructure + + /** + * Each element of the tensor [other] is added to each element of this tensor. + * The resulting tensor is returned. + * + * @param other tensor to be added. + * @return the sum of this tensor and [other]. + */ public operator fun TensorStructure.plus(other: TensorStructure): TensorStructure + + /** + * Adds the scalar [value] to each element of this tensor. + * + * @param value the number to be added to each element of this tensor. + */ public operator fun TensorStructure.plusAssign(value: T): Unit + + /** + * Each element of the tensor [other] is added to each element of this tensor. + * + * @param other tensor to be added. + */ public operator fun TensorStructure.plusAssign(other: TensorStructure): Unit + + /** + * Each element of the tensor [other] is subtracted from this value. + * The resulting tensor is returned. + * + * @param other tensor to be subtracted. + * @return the difference between this value and tensor [other]. + */ public operator fun T.minus(other: TensorStructure): TensorStructure + + /** + * Subtracts the scalar [value] from each element of this tensor and returns a new resulting tensor. + * + * @param value the number to be subtracted from each element of this tensor. + * @return the difference between this tensor and [value]. + */ public operator fun TensorStructure.minus(value: T): TensorStructure + + /** + * Each element of the tensor [other] is subtracted from each element of this tensor. + * The resulting tensor is returned. + * + * @param other tensor to be subtracted. + * @return the difference between this tensor and [other]. + */ public operator fun TensorStructure.minus(other: TensorStructure): TensorStructure + + /** + * Subtracts the scalar [value] from each element of this tensor. + * + * @param value the number to be subtracted from each element of this tensor. + */ public operator fun TensorStructure.minusAssign(value: T): Unit + + /** + * Each element of the tensor [other] is subtracted from each element of this tensor. + * + * @param other tensor to be subtracted. + */ public operator fun TensorStructure.minusAssign(other: TensorStructure): Unit + + /** + * Each element of the tensor [other] is multiplied by this value. + * The resulting tensor is returned. + * + * @param other tensor to be multiplied. + * @return the product of this value and tensor [other]. + */ public operator fun T.times(other: TensorStructure): TensorStructure + + /** + * Multiplies the scalar [value] by each element of this tensor and returns a new resulting tensor. + * + * @param value the number to be multiplied by each element of this tensor. + * @return the product of this tensor and [value]. + */ public operator fun TensorStructure.times(value: T): TensorStructure + + /** + * Each element of the tensor [other] is multiplied by each element of this tensor. + * The resulting tensor is returned. + * + * @param other tensor to be multiplied. + * @return the product of this tensor and [other]. + */ public operator fun TensorStructure.times(other: TensorStructure): TensorStructure + + /** + * Multiplies the scalar [value] by each element of this tensor. + * + * @param value the number to be multiplied by each element of this tensor. + */ public operator fun TensorStructure.timesAssign(value: T): Unit + + /** + * Each element of the tensor [other] is multiplied by each element of this tensor. + * + * @param other tensor to be multiplied. + */ public operator fun TensorStructure.timesAssign(other: TensorStructure): Unit + + /** + * Numerical negative, element-wise. + * + * @return tensor - negation of the original tensor. + */ public operator fun TensorStructure.unaryMinus(): TensorStructure - //https://pytorch.org/cppdocs/notes/tensor_indexing.html + /** + * Returns the tensor at index i + * For more information: https://pytorch.org/cppdocs/notes/tensor_indexing.html + * + * @param i index of the extractable tensor + * @return subtensor of the original tensor with index [i] + */ public operator fun TensorStructure.get(i: Int): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.transpose.html + /** + * Returns a tensor that is a transposed version of this tensor. The given dimensions [i] and [j] are swapped. + * For more information: https://pytorch.org/docs/stable/generated/torch.transpose.html + * + * @param i the first dimension to be transposed + * @param j the second dimension to be transposed + * @return transposed tensor + */ public fun TensorStructure.transpose(i: Int = -2, j: Int = -1): TensorStructure - //https://pytorch.org/docs/stable/tensor_view.html + /** + * Returns a new tensor with the same data as the self tensor but of a different shape. + * The returned tensor shares the same data and must have the same number of elements, but may have a different size + * For more information: https://pytorch.org/docs/stable/tensor_view.html + * + * @param shape the desired size + * @return tensor with new shape + */ public fun TensorStructure.view(shape: IntArray): TensorStructure + + /** + * View this tensor as the same size as [other]. + * ``this.viewAs(other) is equivalent to this.view(other.shape)``. + * For more information: https://pytorch.org/cppdocs/notes/tensor_indexing.html + * + * @param other the result tensor has the same size as other. + * @return the result tensor with the same size as other. + */ public fun TensorStructure.viewAs(other: TensorStructure): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.matmul.html + /** + * Matrix product of two tensors. + * + * The behavior depends on the dimensionality of the tensors as follows: + * 1. If both tensors are 1-dimensional, the dot product (scalar) is returned. + * + * 2. If both arguments are 2-dimensional, the matrix-matrix product is returned. + * + * 3. If the first argument is 1-dimensional and the second argument is 2-dimensional, + * a 1 is prepended to its dimension for the purpose of the matrix multiply. + * After the matrix multiply, the prepended dimension is removed. + * + * 4. If the first argument is 2-dimensional and the second argument is 1-dimensional, + * the matrix-vector product is returned. + * + * 5. If both arguments are at least 1-dimensional and at least one argument is N-dimensional (where N > 2), + * then a batched matrix multiply is returned. If the first argument is 1-dimensional, + * a 1 is prepended to its dimension for the purpose of the batched matrix multiply and removed after. + * If the second argument is 1-dimensional, a 1 is appended to its dimension for the purpose of the batched matrix + * multiple and removed after. + * The non-matrix (i.e. batch) dimensions are broadcasted (and thus must be broadcastable). + * For example, if `input` is a (j \times 1 \times n \times n) tensor and `other` is a + * (k \times n \times n) tensor, out will be a (j \times k \times n \times n) tensor. + * + * For more information: https://pytorch.org/docs/stable/generated/torch.matmul.html + * + * @param other tensor to be multiplied + * @return mathematical product of two tensors + */ public infix fun TensorStructure.dot(other: TensorStructure): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.diag_embed.html + /** + * Creates a tensor whose diagonals of certain 2D planes (specified by [dim1] and [dim2]) + * are filled by [diagonalEntries]. + * To facilitate creating batched diagonal matrices, + * the 2D planes formed by the last two dimensions of the returned tensor are chosen by default. + * + * The argument [offset] controls which diagonal to consider: + * 1. If [offset] = 0, it is the main diagonal. + * 2. If [offset] > 0, it is above the main diagonal. + * 3. If [offset] < 0, it is below the main diagonal. + * + * The size of the new matrix will be calculated + * to make the specified diagonal of the size of the last input dimension. + * For more information: https://pytorch.org/docs/stable/generated/torch.diag_embed.html + * + * @param diagonalEntries - the input tensor. Must be at least 1-dimensional. + * @param offset - which diagonal to consider. Default: 0 (main diagonal). + * @param dim1 - first dimension with respect to which to take diagonal. Default: -2. + * @param dim2 - second dimension with respect to which to take diagonal. Default: -1. + * + * @return tensor whose diagonals of certain 2D planes (specified by [dim1] and [dim2]) + * are filled by [diagonalEntries] + */ public fun diagonalEmbedding( diagonalEntries: TensorStructure, offset: Int = 0, diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt index 1b00197ff..a49d9ab29 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -10,6 +10,10 @@ import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.broadcastTensors import space.kscience.kmath.tensors.core.broadcastTo +/** + * Basic linear algebra operations implemented with broadcasting. + * For more information: https://pytorch.org/docs/stable/notes/broadcasting.html + */ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { From 64c6cbf8603a267f7a85af65f16d567c448eeb0a Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 29 Apr 2021 17:21:29 +0300 Subject: [PATCH 139/211] change tuple to pair/triple --- .../kmath/tensors/api/LinearOpsTensorAlgebra.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 6735efacb..aa10ae49b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -49,13 +49,13 @@ public interface LinearOpsTensorAlgebra : /** * QR decomposition. * - * Computes the QR decomposition of a matrix or a batch of matrices, and returns a namedtuple `(Q, R)` of tensors. + * Computes the QR decomposition of a matrix or a batch of matrices, and returns a pair `(Q, R)` of tensors. * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q * R``, * with `Q` being an orthogonal matrix or batch of orthogonal matrices * and `R` being an upper triangular matrix or batch of upper triangular matrices. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr * - * @return tuple of Q and R tensors. + * @return pair of Q and R tensors. */ public fun TensorStructure.qr(): Pair, TensorStructure> @@ -82,7 +82,7 @@ public interface LinearOpsTensorAlgebra : * Singular Value Decomposition. * * Computes the singular value decomposition of either a matrix or batch of matrices `input`. - * The singular value decomposition is represented as a namedtuple `(U, S, V)`, + * The singular value decomposition is represented as a triple `(U, S, V)`, * such that ``input = U.dot(diagonalEmbedding(S).dot(V.T))``. * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd @@ -93,10 +93,10 @@ public interface LinearOpsTensorAlgebra : /** * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, - * represented by a namedtuple (eigenvalues, eigenvectors). + * represented by a pair (eigenvalues, eigenvectors). * For more information: https://pytorch.org/docs/stable/generated/torch.symeig.html * - * @return a namedtuple (eigenvalues, eigenvectors) + * @return a pair (eigenvalues, eigenvectors) */ public fun TensorStructure.symEig(): Pair, TensorStructure> From b9f1f0e5259b771727a4cdbdfbefc5d5047cf08e Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 29 Apr 2021 20:00:05 +0300 Subject: [PATCH 140/211] fixes --- .../kmath/tensors/api/TensorAlgebra.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 92aafb8ea..62d4a1b89 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -145,7 +145,7 @@ public interface TensorAlgebra { /** * Numerical negative, element-wise. * - * @return tensor - negation of the original tensor. + * @return tensor negation of the original tensor. */ public operator fun TensorStructure.unaryMinus(): TensorStructure @@ -209,8 +209,8 @@ public interface TensorAlgebra { * If the second argument is 1-dimensional, a 1 is appended to its dimension for the purpose of the batched matrix * multiple and removed after. * The non-matrix (i.e. batch) dimensions are broadcasted (and thus must be broadcastable). - * For example, if `input` is a (j \times 1 \times n \times n) tensor and `other` is a - * (k \times n \times n) tensor, out will be a (j \times k \times n \times n) tensor. + * For example, if `input` is a (j × 1 × n × n) tensor and `other` is a + * (k × n × n) tensor, out will be a (j × k × n × n) tensor. * * For more information: https://pytorch.org/docs/stable/generated/torch.matmul.html * @@ -227,17 +227,17 @@ public interface TensorAlgebra { * * The argument [offset] controls which diagonal to consider: * 1. If [offset] = 0, it is the main diagonal. - * 2. If [offset] > 0, it is above the main diagonal. - * 3. If [offset] < 0, it is below the main diagonal. + * 1. If [offset] > 0, it is above the main diagonal. + * 1. If [offset] < 0, it is below the main diagonal. * * The size of the new matrix will be calculated * to make the specified diagonal of the size of the last input dimension. * For more information: https://pytorch.org/docs/stable/generated/torch.diag_embed.html * - * @param diagonalEntries - the input tensor. Must be at least 1-dimensional. - * @param offset - which diagonal to consider. Default: 0 (main diagonal). - * @param dim1 - first dimension with respect to which to take diagonal. Default: -2. - * @param dim2 - second dimension with respect to which to take diagonal. Default: -1. + * @param diagonalEntries the input tensor. Must be at least 1-dimensional. + * @param offset which diagonal to consider. Default: 0 (main diagonal). + * @param dim1 first dimension with respect to which to take diagonal. Default: -2. + * @param dim2 second dimension with respect to which to take diagonal. Default: -1. * * @return tensor whose diagonals of certain 2D planes (specified by [dim1] and [dim2]) * are filled by [diagonalEntries] From 432f404d7c00c4d090f5496ae8ffb5e69d9330d8 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 29 Apr 2021 18:45:46 +0100 Subject: [PATCH 141/211] More descriptions --- kmath-tensors/README.md | 13 +++--- .../tensors/api/AnalyticTensorAlgebra.kt | 38 +++++++++-------- .../tensors/api/LinearOpsTensorAlgebra.kt | 2 +- .../kmath/tensors/api/TensorAlgebra.kt | 2 +- .../api/TensorPartialDivisionAlgebra.kt | 42 ++++++++++++++++++- 5 files changed, 72 insertions(+), 25 deletions(-) diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 3b82829f0..24d46cd16 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -1,12 +1,15 @@ # Module kmath-tensors -Common linear algebra operations on tensors. - - - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) - - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. - - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. +Common operations on tensors, the API consists of: + - [TensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic algebra operations on tensors (plus, dot, etc.) + - [TensorPartialDivisionAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt) : Emulates an algebra over a field + - [LinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Linear algebra operations including LU, QR, Cholesky LL and SVD decompositions + - [AnalyticTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt) : Element-wise analytic operations +The library offers a multiplatform implementation for this interface over the `Double`'s. As the highlight, the user can find: + - [BroadcastDoubleTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic algebra operations implemented with broadcasting. + - [DoubleLinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt) : Includes the power method for SVD and the spectrum of symmetric matrices. ## Artifact: The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-7`. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 315f39027..5c92c56c4 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -5,59 +5,63 @@ package space.kscience.kmath.tensors.api - +/** + * Element-wise analytic operations on [TensorStructure]. + * + * @param T the type of items closed under analytic functions in the tensors. + */ public interface AnalyticTensorAlgebra : TensorPartialDivisionAlgebra { - //https://pytorch.org/docs/stable/generated/torch.exp.html + //For information: https://pytorch.org/docs/stable/generated/torch.exp.html public fun TensorStructure.exp(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.log.html + //For information: https://pytorch.org/docs/stable/generated/torch.log.html public fun TensorStructure.log(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.sqrt.html + //For information: https://pytorch.org/docs/stable/generated/torch.sqrt.html public fun TensorStructure.sqrt(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos + //For information: https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos public fun TensorStructure.cos(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.acos + //For information: https://pytorch.org/docs/stable/generated/torch.acos.html#torch.acos public fun TensorStructure.acos(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.cosh + //For information: https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.cosh public fun TensorStructure.cosh(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.acosh + //For information: https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.acosh public fun TensorStructure.acosh(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sin + //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sin public fun TensorStructure.sin(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asin + //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asin public fun TensorStructure.asin(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sinh + //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sinh public fun TensorStructure.sinh(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asinh + //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asinh public fun TensorStructure.asinh(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.tan + //For information: https://pytorch.org/docs/stable/generated/torch.atan.html#torch.tan public fun TensorStructure.tan(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.atan public fun TensorStructure.atan(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.tanh + //For information: https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.tanh public fun TensorStructure.tanh(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.atanh + //For information: https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.atanh public fun TensorStructure.atanh(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.ceil.html#torch.ceil + //For information: https://pytorch.org/docs/stable/generated/torch.ceil.html#torch.ceil public fun TensorStructure.ceil(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor + //For information: https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor public fun TensorStructure.floor(): TensorStructure } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index aa10ae49b..7a19c5d5a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.tensors.api /** * Common linear algebra operations. Operates on [TensorStructure]. * - * @param T the type of items in the tensors. + * @param T the type of items closed under division in the tensors. */ public interface LinearOpsTensorAlgebra : TensorPartialDivisionAlgebra { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 62d4a1b89..338064231 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.api /** - * Basic linear algebra operations on [TensorStructure]. + * Algebra over a ring on [TensorStructure]. * For more information: https://proofwiki.org/wiki/Definition:Algebra_over_Ring * * @param T the type of items in the tensors. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt index 4dab3dd07..eccc6fa0d 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt @@ -5,12 +5,52 @@ package space.kscience.kmath.tensors.api -// https://proofwiki.org/wiki/Definition:Division_Algebra +/** + * Algebra over a field with partial division on [TensorStructure]. + * For more information: https://proofwiki.org/wiki/Definition:Division_Algebra + * + * @param T the type of items closed under division in the tensors. + */ public interface TensorPartialDivisionAlgebra : TensorAlgebra { + + /** + * Each element of the tensor [other] is divided by this value. + * The resulting tensor is returned. + * + * @param other tensor to divide by. + * @return the division of this value by the tensor [other]. + */ public operator fun T.div(other: TensorStructure): TensorStructure + + /** + * Divide by the scalar [value] each element of this tensor returns a new resulting tensor. + * + * @param value the number to divide by each element of this tensor. + * @return the division of this tensor by the [value]. + */ public operator fun TensorStructure.div(value: T): TensorStructure + + /** + * Each element of the tensor [other] is divided by each element of this tensor. + * The resulting tensor is returned. + * + * @param other tensor to be divided by. + * @return the division of this tensor by [other]. + */ public operator fun TensorStructure.div(other: TensorStructure): TensorStructure + + /** + * Divides by the scalar [value] each element of this tensor. + * + * @param value the number to divide by each element of this tensor. + */ public operator fun TensorStructure.divAssign(value: T) + + /** + * Each element of this tensor is divided by each element of the [other] tensor. + * + * @param other tensor to be divide by. + */ public operator fun TensorStructure.divAssign(other: TensorStructure) } From cba62a9468c84bb476dbf905bd44c4df90d9b735 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 29 Apr 2021 18:48:41 +0100 Subject: [PATCH 142/211] English typo --- kmath-tensors/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 24d46cd16..a81b7277c 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -7,9 +7,9 @@ Common operations on tensors, the API consists of: - [LinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Linear algebra operations including LU, QR, Cholesky LL and SVD decompositions - [AnalyticTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt) : Element-wise analytic operations -The library offers a multiplatform implementation for this interface over the `Double`'s. As the highlight, the user can find: +The library offers a multiplatform implementation for this interface over the `Double`'s. As a highlight, the user can find: - [BroadcastDoubleTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic algebra operations implemented with broadcasting. - - [DoubleLinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt) : Includes the power method for SVD and the spectrum of symmetric matrices. + - [DoubleLinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt) : Contains the power method for SVD and the spectrum of symmetric matrices. ## Artifact: The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-7`. From 09f0a2879e50c364ee969930576af8e453e32748 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 30 Apr 2021 11:08:22 +0300 Subject: [PATCH 143/211] refactor lu + docs --- .../tensors/LinearSystemSolvingWithLUP.kt | 3 +-- .../tensors/api/LinearOpsTensorAlgebra.kt | 22 +++++++------------ .../algebras/DoubleLinearOpsTensorAlgebra.kt | 17 ++++++++++---- .../core/TestDoubleLinearOpsAlgebra.kt | 4 +--- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index 526b6781f..38d8c1437 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -42,8 +42,7 @@ fun main () { // solve `Ax = b` system using LUP decomposition // get P, L, U such that PA = LU - val (lu, pivots) = a.lu() - val (p, l, u) = luPivot(lu, pivots) + val (p, l, u) = a.lu() // check that P is permutation matrix println("P:\n$p") diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 7a19c5d5a..bcbb52a1b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -60,23 +60,17 @@ public interface LinearOpsTensorAlgebra : public fun TensorStructure.qr(): Pair, TensorStructure> /** - * TODO('Andrew') - * For more information: https://pytorch.org/docs/stable/generated/torch.lu.html + * LUP decomposition * - * @return ... - */ - public fun TensorStructure.lu(): Pair, TensorStructure> - - /** - * TODO('Andrew') - * For more information: https://pytorch.org/docs/stable/generated/torch.lu_unpack.html + * Computes the LUP decomposition of a matrix or a batch of matrices. + * Given a tensor `input`, return tensors (P, L, U) satisfying ``P * input = L * U``, + * with `P` being a permutation matrix or batch of matrices, + * `L` being a lower triangular matrix or batch of matrices, + * `U` being an upper triangular matrix or batch of matrices. * - * @param luTensor ... - * @param pivotsTensor ... - * @return ... + * * @return triple of P, L and U tensors */ - public fun luPivot(luTensor: TensorStructure, pivotsTensor: TensorStructure): - Triple, TensorStructure, TensorStructure> + public fun TensorStructure.lu(): Triple, TensorStructure, TensorStructure> /** * Singular Value Decomposition. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 62629f3db..97eed289a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -29,13 +29,13 @@ public class DoubleLinearOpsTensorAlgebra : override fun TensorStructure.det(): DoubleTensor = detLU(1e-9) - public fun TensorStructure.lu(epsilon: Double): Pair = + public fun TensorStructure.luFactor(epsilon: Double): Pair = computeLU(tensor, epsilon) ?: throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon") - override fun TensorStructure.lu(): Pair = lu(1e-9) + public fun TensorStructure.luFactor(): Pair = luFactor(1e-9) - override fun luPivot( + public fun luPivot( luTensor: TensorStructure, pivotsTensor: TensorStructure ): Triple { @@ -156,7 +156,7 @@ public class DoubleLinearOpsTensorAlgebra : } public fun TensorStructure.invLU(epsilon: Double = 1e-9): DoubleTensor { - val (luTensor, pivotsTensor) = lu(epsilon) + val (luTensor, pivotsTensor) = luFactor(epsilon) val invTensor = luTensor.zeroesLike() val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) @@ -167,6 +167,15 @@ public class DoubleLinearOpsTensorAlgebra : return invTensor } + + public fun TensorStructure.lu(epsilon: Double = 1e-9): Triple { + val (lu, pivots) = this.luFactor(epsilon) + return luPivot(lu, pivots) + } + + override fun TensorStructure.lu(): Triple = lu(1e-9) + + } public inline fun DoubleLinearOpsTensorAlgebra(block: DoubleLinearOpsTensorAlgebra.() -> R): R = 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 6120f0e4a..1f7e955d4 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 @@ -124,9 +124,7 @@ class TestDoubleLinearOpsTensorAlgebra { ) val tensor = fromArray(shape, buffer) - val (lu, pivots) = tensor.lu() - - val (p, l, u) = luPivot(lu, pivots) + val (p, l, u) = tensor.lu() assertTrue { p.shape contentEquals shape } assertTrue { l.shape contentEquals shape } From b546f3f78bf019c65b6bf4e1dda7cf521da46884 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 09:19:30 +0100 Subject: [PATCH 144/211] Merge PR --- .../kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 97eed289a..03f383728 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -116,7 +116,7 @@ public class DoubleLinearOpsTensorAlgebra : override fun TensorStructure.symEig(): Pair = symEig(epsilon = 1e-15) - //http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html + //For information: http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html public fun TensorStructure.symEig(epsilon: Double): Pair { checkSymmetric(tensor, epsilon) val (u, s, v) = tensor.svd(epsilon) From bd068b2c1438e912a1a0b96bab72ffe55478374e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 09:54:25 +0100 Subject: [PATCH 145/211] Smaller SVD test --- .../kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 1f7e955d4..b2ef6b4c4 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 @@ -163,7 +163,7 @@ class TestDoubleLinearOpsTensorAlgebra { @Test fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { - val tensor = randNormal(intArrayOf(1, 15, 4, 7, 5, 3), 0) + val tensor = randNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) assertTrue(tensor.eq(tensorSVD)) @@ -171,7 +171,7 @@ class TestDoubleLinearOpsTensorAlgebra { @Test fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { - val tensor = randNormal(shape = intArrayOf(5, 3, 3), 0) + val tensor = randNormal(shape = intArrayOf(2, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) From 598b2e158724e4d9dd73d8d80a361684893071cd Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 28 Apr 2021 18:03:28 +0700 Subject: [PATCH 146/211] Rewrite EJML module by dropping ejml-simple abstraction level; multiple build script changes --- .github/workflows/pages.yml | 4 +- CHANGELOG.md | 3 +- benchmarks/build.gradle.kts | 6 +- .../kscience/kmath/benchmarks/DotBenchmark.kt | 10 +- .../benchmarks/MatrixInverseBenchmark.kt | 21 +- build.gradle.kts | 30 +-- docs/templates/ARTIFACT-TEMPLATE.md | 6 +- examples/build.gradle.kts | 7 +- kmath-ast/README.md | 6 +- kmath-complex/README.md | 6 +- kmath-core/README.md | 6 +- kmath-ejml/README.md | 12 +- kmath-ejml/build.gradle.kts | 8 +- .../kscience/kmath/ejml/EjmlLinearSpace.kt | 251 +++++++++++------- .../space/kscience/kmath/ejml/EjmlMatrix.kt | 24 +- .../space/kscience/kmath/ejml/EjmlVector.kt | 36 +-- .../kscience/kmath/ejml/EjmlMatrixTest.kt | 53 ++-- .../kscience/kmath/ejml/EjmlVectorTest.kt | 23 +- kmath-for-real/README.md | 2 - kmath-functions/README.md | 2 - kmath-kotlingrad/build.gradle.kts | 4 +- kmath-nd4j/README.md | 6 +- kmath-viktor/build.gradle.kts | 4 +- 23 files changed, 281 insertions(+), 249 deletions(-) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 82b0fb303..c70227fce 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -30,9 +30,7 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - name: Build - run: | - ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace - mv build/dokka/htmlMultiModule/-modules.html build/dokka/htmlMultiModule/index.html + run: ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace - name: Deploy to GitHub Pages uses: JamesIves/github-pages-deploy-action@4.1.0 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 7464695ec..4266c5b70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ - Blocking chains and Statistics - Multiplatform integration - Integration for any Field element -- Extendend operations for ND4J fields +- Extended operations for ND4J fields ### Changed - Exponential operations merged with hyperbolic functions @@ -24,6 +24,7 @@ - Redesign MST. Remove MSTExpression. - Move MST to core - Separated benchmarks and examples +- Rewritten EJML module without ejml-simple ### Deprecated diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 88f034a2a..98ffc5a96 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -9,14 +9,10 @@ sourceSets.register("benchmarks") repositories { mavenCentral() - jcenter() maven("https://repo.kotlin.link") maven("https://clojars.org/repo") - maven("https://dl.bintray.com/egor-bogomolov/astminer/") - maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://jitpack.io") - maven { - setUrl("http://logicrunch.research.it.uu.se/maven/") + maven("http://logicrunch.research.it.uu.se/maven") { isAllowInsecureProtocol = true } } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt index 23e73cb5f..2c5a03a97 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt @@ -10,7 +10,7 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import space.kscience.kmath.commons.linear.CMLinearSpace -import space.kscience.kmath.ejml.EjmlLinearSpace +import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.invoke import space.kscience.kmath.operations.DoubleField @@ -29,8 +29,8 @@ internal class DotBenchmark { val cmMatrix1 = CMLinearSpace { matrix1.toCM() } val cmMatrix2 = CMLinearSpace { matrix2.toCM() } - val ejmlMatrix1 = EjmlLinearSpace { matrix1.toEjml() } - val ejmlMatrix2 = EjmlLinearSpace { matrix2.toEjml() } + val ejmlMatrix1 = EjmlLinearSpaceDDRM { matrix1.toEjml() } + val ejmlMatrix2 = EjmlLinearSpaceDDRM { matrix2.toEjml() } } @Benchmark @@ -42,14 +42,14 @@ internal class DotBenchmark { @Benchmark fun ejmlDot(blackhole: Blackhole) { - EjmlLinearSpace { + EjmlLinearSpaceDDRM { blackhole.consume(ejmlMatrix1 dot ejmlMatrix2) } } @Benchmark fun ejmlDotWithConversion(blackhole: Blackhole) { - EjmlLinearSpace { + EjmlLinearSpaceDDRM { blackhole.consume(matrix1 dot matrix2) } } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt index d1803e389..7bb32af28 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt @@ -11,25 +11,26 @@ import kotlinx.benchmark.Scope import kotlinx.benchmark.State import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.commons.linear.inverse -import space.kscience.kmath.ejml.EjmlLinearSpace -import space.kscience.kmath.ejml.inverse +import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM +import space.kscience.kmath.linear.InverseMatrixFeature import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.inverseWithLup import space.kscience.kmath.linear.invoke +import space.kscience.kmath.nd.getFeature import kotlin.random.Random @State(Scope.Benchmark) internal class MatrixInverseBenchmark { - companion object { - val random = Random(1224) - const val dim = 100 + private companion object { + private val random = Random(1224) + private const val dim = 100 private val space = LinearSpace.real //creating invertible matrix - val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } - val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 } - val matrix = space { l dot u } + private val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } + private val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 } + private val matrix = space { l dot u } } @Benchmark @@ -46,8 +47,8 @@ internal class MatrixInverseBenchmark { @Benchmark fun ejmlInverse(blackhole: Blackhole) { - with(EjmlLinearSpace) { - blackhole.consume(inverse(matrix)) + with(EjmlLinearSpaceDDRM) { + blackhole.consume(matrix.getFeature>()?.inverse) } } } diff --git a/build.gradle.kts b/build.gradle.kts index 4e0b6f256..506f51a0e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,14 +4,12 @@ plugins { allprojects { repositories { - jcenter() maven("https://clojars.org/repo") - maven("https://dl.bintray.com/egor-bogomolov/astminer/") - maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://jitpack.io") - maven("http://logicrunch.research.it.uu.se/maven/") { + maven("http://logicrunch.research.it.uu.se/maven") { isAllowInsecureProtocol = true } + maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven") mavenCentral() } @@ -23,22 +21,16 @@ subprojects { if (name.startsWith("kmath")) apply() afterEvaluate { - tasks.withType { - dokkaSourceSets.all { - val readmeFile = File(this@subprojects.projectDir, "./README.md") - if (readmeFile.exists()) - includes.setFrom(includes + readmeFile.absolutePath) + tasks.withType { + dependsOn(tasks.getByName("assemble")) - arrayOf( - "http://ejml.org/javadoc/", - "https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/", - "https://deeplearning4j.org/api/latest/" - ).map { java.net.URL("${it}package-list") to java.net.URL(it) }.forEach { (a, b) -> - externalDocumentationLink { - packageListUrl.set(a) - url.set(b) - } - } + dokkaSourceSets.all { + val readmeFile = File(this@subprojects.projectDir, "README.md") + if (readmeFile.exists()) includes.setFrom(includes + readmeFile.absolutePath) + externalDocumentationLink("http://ejml.org/javadoc/") + externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/") + externalDocumentationLink("https://deeplearning4j.org/api/latest/") + externalDocumentationLink("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/") } } } diff --git a/docs/templates/ARTIFACT-TEMPLATE.md b/docs/templates/ARTIFACT-TEMPLATE.md index 01d9c51da..1bac2a8ff 100644 --- a/docs/templates/ARTIFACT-TEMPLATE.md +++ b/docs/templates/ARTIFACT-TEMPLATE.md @@ -6,8 +6,7 @@ The Maven coordinates of this project are `${group}:${name}:${version}`. ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -18,8 +17,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 56feee9dc..571949b7b 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -4,14 +4,11 @@ plugins { repositories { mavenCentral() - jcenter() maven("https://repo.kotlin.link") maven("https://clojars.org/repo") - maven("https://dl.bintray.com/egor-bogomolov/astminer/") - maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://jitpack.io") - maven{ - setUrl("http://logicrunch.research.it.uu.se/maven/") + maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers") + maven("http://logicrunch.research.it.uu.se/maven") { isAllowInsecureProtocol = true } } diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 1ee78956e..4de165e72 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -16,8 +16,7 @@ The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-7` ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -28,8 +27,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 70beab95a..06e10fa7a 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -14,8 +14,7 @@ The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-de ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -26,8 +25,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { diff --git a/kmath-core/README.md b/kmath-core/README.md index e28873045..36b30efcc 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -21,8 +21,7 @@ The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-7 ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -33,8 +32,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index 3bf29f803..97c5ae115 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -2,9 +2,9 @@ EJML based linear algebra implementation. - - [ejml-vector](src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix. - - [ejml-matrix](src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix. - - [ejml-linear-space](src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix. + - [ejml-vector](src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : Point implementations. + - [ejml-matrix](src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : Matrix implementation. + - [ejml-linear-space](src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : LinearSpace implementations. ## Artifact: @@ -15,8 +15,7 @@ The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-7 ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -27,8 +26,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index d3a49aeb0..c8e2ecd8b 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } dependencies { - api("org.ejml:ejml-simple:0.40") + api("org.ejml:ejml-ddense:0.40") api(project(":kmath-core")) } @@ -14,19 +14,19 @@ readme { feature( id = "ejml-vector", - description = "The Point implementation using SimpleMatrix.", + description = "Point implementations.", ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt" ) feature( id = "ejml-matrix", - description = "The Matrix implementation using SimpleMatrix.", + description = "Matrix implementation.", ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt" ) feature( id = "ejml-linear-space", - description = "The LinearSpace implementation using SimpleMatrix.", + description = "LinearSpace implementations.", ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt" ) } diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index 4b6421c9b..71cae4829 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -5,45 +5,71 @@ package space.kscience.kmath.ejml +import org.ejml.data.DMatrix +import org.ejml.data.DMatrixD1 +import org.ejml.data.DMatrixRMaj +import org.ejml.dense.row.CommonOps_DDRM import org.ejml.dense.row.factory.DecompositionFactory_DDRM -import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureFeature -import space.kscience.kmath.nd.getFeature import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.Ring import space.kscience.kmath.structures.DoubleBuffer import kotlin.reflect.KClass import kotlin.reflect.cast /** - * Represents context of basic operations operating with [EjmlMatrix]. + * [LinearSpace] implementation specialized for a certain EJML type. + * + * @param T the type of items in the matrices. + * @param A the element context type. + * @param M the EJML matrix type. + * @author Iaroslav Postovalov + */ +public abstract class EjmlLinearSpace, M : org.ejml.data.Matrix> : LinearSpace { + /** + * Converts this matrix to EJML one. + */ + public abstract fun Matrix.toEjml(): EjmlMatrix + + /** + * Converts this vector to EJML one. + */ + public abstract fun Point.toEjml(): EjmlVector + + public abstract override fun buildMatrix( + rows: Int, + columns: Int, + initializer: A.(i: Int, j: Int) -> T, + ): EjmlMatrix + + public abstract override fun buildVector(size: Int, initializer: A.(Int) -> T): EjmlVector +} + +/** + * [EjmlLinearSpace] implementation based on [CommonOps_DDRM], [DecompositionFactory_DDRM] operations and + * [DMatrixRMaj] matrices. * * @author Iaroslav Postovalov - * @author Alexander Nozik */ -public object EjmlLinearSpace : LinearSpace { +public object EjmlLinearSpaceDDRM : EjmlLinearSpace() { /** * The [DoubleField] reference. */ public override val elementAlgebra: DoubleField get() = DoubleField - /** - * Converts this matrix to EJML one. - */ - @OptIn(UnstableKMathAPI::class) - public fun Matrix.toEjml(): EjmlMatrix = when (val matrix = origin) { - is EjmlMatrix -> matrix + @Suppress("UNCHECKED_CAST") + public override fun Matrix.toEjml(): EjmlDoubleMatrix = when { + this is EjmlDoubleMatrix<*> && origin is DMatrixRMaj -> this as EjmlDoubleMatrix else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } } - /** - * Converts this vector to EJML one. - */ - public fun Point.toEjml(): EjmlVector = when (this) { - is EjmlVector -> this - else -> EjmlVector(SimpleMatrix(size, 1).also { - (0 until it.numRows()).forEach { row -> it[row, 0] = get(row) } + @Suppress("UNCHECKED_CAST") + public override fun Point.toEjml(): EjmlDoubleVector = when { + this is EjmlDoubleVector<*> && origin is DMatrixRMaj -> this as EjmlDoubleVector + else -> EjmlDoubleVector(DMatrixRMaj(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } }) } @@ -51,159 +77,178 @@ public object EjmlLinearSpace : LinearSpace { rows: Int, columns: Int, initializer: DoubleField.(i: Int, j: Int) -> Double, - ): EjmlMatrix = EjmlMatrix(SimpleMatrix(rows, columns).also { + ): EjmlDoubleMatrix = EjmlDoubleMatrix(DMatrixRMaj(rows, columns).also { (0 until rows).forEach { row -> - (0 until columns).forEach { col -> it[row, col] = DoubleField.initializer(row, col) } + (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } } }) - public override fun buildVector(size: Int, initializer: DoubleField.(Int) -> Double): Point = - EjmlVector(SimpleMatrix(size, 1).also { - (0 until it.numRows()).forEach { row -> it[row, 0] = DoubleField.initializer(row) } - }) + public override fun buildVector( + size: Int, + initializer: DoubleField.(Int) -> Double, + ): EjmlDoubleVector = EjmlDoubleVector(DMatrixRMaj(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } + }) - private fun SimpleMatrix.wrapMatrix() = EjmlMatrix(this) - private fun SimpleMatrix.wrapVector() = EjmlVector(this) + private fun T.wrapMatrix() = EjmlDoubleMatrix(this) + private fun T.wrapVector() = EjmlDoubleVector(this) public override fun Matrix.unaryMinus(): Matrix = this * (-1.0) - public override fun Matrix.dot(other: Matrix): EjmlMatrix = - EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) + public override fun Matrix.dot(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.mult(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } - public override fun Matrix.dot(vector: Point): EjmlVector = - EjmlVector(toEjml().origin.mult(vector.toEjml().origin)) + public override fun Matrix.dot(vector: Point): EjmlDoubleVector { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.mult(toEjml().origin, vector.toEjml().origin, out) + return out.wrapVector() + } - public override operator fun Matrix.minus(other: Matrix): EjmlMatrix = - (toEjml().origin - other.toEjml().origin).wrapMatrix() + public override operator fun Matrix.minus(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.subtract(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } - public override operator fun Matrix.times(value: Double): EjmlMatrix = - toEjml().origin.scale(value).wrapMatrix() + public override operator fun Matrix.times(value: Double): EjmlDoubleMatrix { + val res = this.toEjml().origin.copy() + CommonOps_DDRM.scale(value, res) + return res.wrapMatrix() + } - public override fun Point.unaryMinus(): EjmlVector = - toEjml().origin.negative().wrapVector() + public override fun Point.unaryMinus(): EjmlDoubleVector { + val out = toEjml().origin.copy() + CommonOps_DDRM.changeSign(out) + return out.wrapVector() + } - public override fun Matrix.plus(other: Matrix): EjmlMatrix = - (toEjml().origin + other.toEjml().origin).wrapMatrix() + public override fun Matrix.plus(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.add(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } - public override fun Point.plus(other: Point): EjmlVector = - (toEjml().origin + other.toEjml().origin).wrapVector() + public override fun Point.plus(other: Point): EjmlDoubleVector { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.add(toEjml().origin, other.toEjml().origin, out) + return out.wrapVector() + } - public override fun Point.minus(other: Point): EjmlVector = - (toEjml().origin - other.toEjml().origin).wrapVector() + public override fun Point.minus(other: Point): EjmlDoubleVector { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.subtract(toEjml().origin, other.toEjml().origin, out) + return out.wrapVector() + } - public override fun Double.times(m: Matrix): EjmlMatrix = - m.toEjml().origin.scale(this).wrapMatrix() + public override fun Double.times(m: Matrix): EjmlDoubleMatrix = m * this - public override fun Point.times(value: Double): EjmlVector = - toEjml().origin.scale(value).wrapVector() + public override fun Point.times(value: Double): EjmlDoubleVector { + val res = this.toEjml().origin.copy() + CommonOps_DDRM.scale(value, res) + return res.wrapVector() + } - public override fun Double.times(v: Point): EjmlVector = - v.toEjml().origin.scale(this).wrapVector() + public override fun Double.times(v: Point): EjmlDoubleVector = v * this @UnstableKMathAPI public override fun getFeature(structure: Matrix, type: KClass): F? { - //Return the feature if it is intrinsic to the structure + // Return the feature if it is intrinsic to the structure structure.getFeature(type)?.let { return it } val origin = structure.toEjml().origin return when (type) { InverseMatrixFeature::class -> object : InverseMatrixFeature { - override val inverse: Matrix by lazy { EjmlMatrix(origin.invert()) } + override val inverse: Matrix by lazy { + val res = origin.copy() + CommonOps_DDRM.invert(res) + EjmlDoubleMatrix(res) + } } DeterminantFeature::class -> object : DeterminantFeature { - override val determinant: Double by lazy(origin::determinant) + override val determinant: Double by lazy { CommonOps_DDRM.det(DMatrixRMaj(origin)) } } SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { private val svd by lazy { - DecompositionFactory_DDRM.svd(origin.numRows(), origin.numCols(), true, true, false) - .apply { decompose(origin.ddrm.copy()) } + DecompositionFactory_DDRM.svd(origin.numRows, origin.numCols, true, true, false) + .apply { decompose(origin.copy()) } } - override val u: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getU(null, false))) } - override val s: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getW(null))) } - override val v: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getV(null, false))) } + override val u: Matrix by lazy { EjmlDoubleMatrix(svd.getU(null, false)) } + override val s: Matrix by lazy { EjmlDoubleMatrix(svd.getW(null)) } + override val v: Matrix by lazy { EjmlDoubleMatrix(svd.getV(null, false)) } override val singularValues: Point by lazy { DoubleBuffer(svd.singularValues) } } QRDecompositionFeature::class -> object : QRDecompositionFeature { private val qr by lazy { - DecompositionFactory_DDRM.qr().apply { decompose(origin.ddrm.copy()) } + DecompositionFactory_DDRM.qr().apply { decompose(origin.copy()) } } override val q: Matrix by lazy { - EjmlMatrix(SimpleMatrix(qr.getQ(null, false))) + OrthogonalFeature + EjmlDoubleMatrix(qr.getQ(null, false)) + OrthogonalFeature } - override val r: Matrix by lazy { EjmlMatrix(SimpleMatrix(qr.getR(null, false))) + UFeature } + override val r: Matrix by lazy { EjmlDoubleMatrix(qr.getR(null, false)) + UFeature } } CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { override val l: Matrix by lazy { val cholesky = - DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.ddrm.copy()) } + DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) } - EjmlMatrix(SimpleMatrix(cholesky.getT(null))) + LFeature + EjmlDoubleMatrix(cholesky.getT(null)) + LFeature } } LupDecompositionFeature::class -> object : LupDecompositionFeature { private val lup by lazy { - DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols()) - .apply { decompose(origin.ddrm.copy()) } + DecompositionFactory_DDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) } } override val l: Matrix by lazy { - EjmlMatrix(SimpleMatrix(lup.getLower(null))) + LFeature + EjmlDoubleMatrix(lup.getLower(null)) + LFeature } override val u: Matrix by lazy { - EjmlMatrix(SimpleMatrix(lup.getUpper(null))) + UFeature + EjmlDoubleMatrix(lup.getUpper(null)) + UFeature } - override val p: Matrix by lazy { EjmlMatrix(SimpleMatrix(lup.getRowPivot(null))) } + override val p: Matrix by lazy { EjmlDoubleMatrix(lup.getRowPivot(null)) } } else -> null }?.let(type::cast) } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for 'x' that is n by p. + */ + public fun solve(a: Matrix, b: Matrix): EjmlDoubleMatrix { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res) + return EjmlDoubleMatrix(res) + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for 'x' that is n by p. + */ + public fun solve(a: Matrix, b: Point): EjmlDoubleVector { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res) + return EjmlDoubleVector(res) + } } - -/** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p matrix. - * @return the solution for 'x' that is n by p. - * @author Iaroslav Postovalov - */ -public fun EjmlLinearSpace.solve(a: Matrix, b: Matrix): EjmlMatrix = - EjmlMatrix(a.toEjml().origin.solve(b.toEjml().origin)) - -/** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p vector. - * @return the solution for 'x' that is n by p. - * @author Iaroslav Postovalov - */ -public fun EjmlLinearSpace.solve(a: Matrix, b: Point): EjmlVector = - EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) - -/** - * Inverts this matrix. - * - * @author Alexander Nozik - */ -@OptIn(UnstableKMathAPI::class) -public fun EjmlMatrix.inverted(): EjmlMatrix = getFeature>()!!.inverse as EjmlMatrix - -/** - * Inverts the given matrix. - * - * @author Alexander Nozik - */ -public fun EjmlLinearSpace.inverse(matrix: Matrix): Matrix = matrix.toEjml().inverted() \ No newline at end of file diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index 32907d199..92c4d1cf0 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -5,18 +5,28 @@ package space.kscience.kmath.ejml -import org.ejml.simple.SimpleMatrix -import space.kscience.kmath.linear.Matrix +import org.ejml.data.DMatrix +import org.ejml.data.Matrix +import space.kscience.kmath.nd.Structure2D /** - * The matrix implementation over EJML [SimpleMatrix]. + * [space.kscience.kmath.linear.Matrix] implementation based on EJML [Matrix]. * - * @property origin the underlying [SimpleMatrix]. + * @param T the type of elements contained in the buffer. + * @param M the type of EJML matrix. + * @property origin The underlying EJML matrix. * @author Iaroslav Postovalov */ -public class EjmlMatrix(public val origin: SimpleMatrix) : Matrix { - public override val rowNum: Int get() = origin.numRows() - public override val colNum: Int get() = origin.numCols() +public abstract class EjmlMatrix(public open val origin: M) : Structure2D { + public override val rowNum: Int get() = origin.numRows + public override val colNum: Int get() = origin.numCols +} +/** + * [EjmlMatrix] specialization for [Double]. + * + * @author Iaroslav Postovalov + */ +public class EjmlDoubleMatrix(public override val origin: M) : EjmlMatrix(origin) { public override operator fun get(i: Int, j: Int): Double = origin[i, j] } diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt index 2f4b4a8e2..81502d6d0 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt @@ -5,35 +5,41 @@ package space.kscience.kmath.ejml -import org.ejml.simple.SimpleMatrix +import org.ejml.data.DMatrixD1 +import org.ejml.data.Matrix import space.kscience.kmath.linear.Point /** - * Represents point over EJML [SimpleMatrix]. + * [Point] implementation based on EJML [Matrix]. * - * @property origin the underlying [SimpleMatrix]. + * @param T the type of elements contained in the buffer. + * @param M the type of EJML matrix. + * @property origin The underlying matrix. * @author Iaroslav Postovalov */ -public class EjmlVector internal constructor(public val origin: SimpleMatrix) : Point { +public abstract class EjmlVector(public open val origin: M) : Point { public override val size: Int - get() = origin.numRows() + get() = origin.numRows - init { - require(origin.numCols() == 1) { "Only single column matrices are allowed" } - } - - public override operator fun get(index: Int): Double = origin[index] - - public override operator fun iterator(): Iterator = object : Iterator { + public override operator fun iterator(): Iterator = object : Iterator { private var cursor: Int = 0 - override fun next(): Double { + override fun next(): T { cursor += 1 - return origin[cursor - 1] + return this@EjmlVector[cursor - 1] } - override fun hasNext(): Boolean = cursor < origin.numCols() * origin.numRows() + override fun hasNext(): Boolean = cursor < origin.numCols * origin.numRows } public override fun toString(): String = "EjmlVector(origin=$origin)" } + +/** + * [EjmlVector] specialization for [Double]. + * + * @author Iaroslav Postovalov + */ +public class EjmlDoubleVector(public override val origin: M) : EjmlVector(origin) { + public override operator fun get(index: Int): Double = origin[index] +} diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt index 59f9602d6..485c53c38 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -5,12 +5,15 @@ package space.kscience.kmath.ejml +import org.ejml.data.DMatrixRMaj +import org.ejml.dense.row.CommonOps_DDRM +import org.ejml.dense.row.RandomMatrices_DDRM import org.ejml.dense.row.factory.DecompositionFactory_DDRM -import org.ejml.simple.SimpleMatrix -import space.kscience.kmath.linear.* +import space.kscience.kmath.linear.DeterminantFeature +import space.kscience.kmath.linear.LupDecompositionFeature +import space.kscience.kmath.linear.getFeature import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND -import space.kscience.kmath.nd.getFeature import kotlin.random.Random import kotlin.random.asJavaRandom import kotlin.test.* @@ -22,65 +25,59 @@ fun assertMatrixEquals(expected: StructureND, actual: StructureND = EjmlLinearSpace.getFeature(w) ?: fail() - assertEquals(m.determinant(), det.determinant) - val lup: LupDecompositionFeature = EjmlLinearSpace.getFeature(w) ?: fail() + val w = EjmlDoubleMatrix(m) + val det: DeterminantFeature = EjmlLinearSpaceDDRM.getFeature(w) ?: fail() + assertEquals(CommonOps_DDRM.det(m), det.determinant) + val lup: LupDecompositionFeature = EjmlLinearSpaceDDRM.getFeature(w) ?: fail() - val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows(), m.numCols()) - .also { it.decompose(m.ddrm.copy()) } + val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows, m.numCols) + .also { it.decompose(m.copy()) } - assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getLower(null))), lup.l) - assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getUpper(null))), lup.u) - assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getRowPivot(null))), lup.p) - } - - private object SomeFeature : MatrixFeature {} - - @OptIn(UnstableKMathAPI::class) - @Test - fun suggestFeature() { - assertNotNull((EjmlMatrix(randomMatrix) + SomeFeature).getFeature()) + assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getLower(null)), lup.l) + assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getUpper(null)), lup.u) + assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getRowPivot(null)), lup.p) } @Test fun get() { val m = randomMatrix - assertEquals(m[0, 0], EjmlMatrix(m)[0, 0]) + assertEquals(m[0, 0], EjmlDoubleMatrix(m)[0, 0]) } @Test fun origin() { val m = randomMatrix - assertSame(m, EjmlMatrix(m).origin) + assertSame(m, EjmlDoubleMatrix(m).origin) } } diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt index e1bcd269e..9bf76033d 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt @@ -5,7 +5,8 @@ package space.kscience.kmath.ejml -import org.ejml.simple.SimpleMatrix +import org.ejml.data.DMatrixRMaj +import org.ejml.dense.row.RandomMatrices_DDRM import kotlin.random.Random import kotlin.random.asJavaRandom import kotlin.test.Test @@ -15,30 +16,34 @@ import kotlin.test.assertSame internal class EjmlVectorTest { private val random = Random(0) - private val randomMatrix: SimpleMatrix - get() = SimpleMatrix.random_DDRM(random.nextInt(2, 100), 1, 0.0, 10.0, random.asJavaRandom()) + private val randomMatrix: DMatrixRMaj + get() { + val d = DMatrixRMaj(random.nextInt(2, 100), 1) + RandomMatrices_DDRM.fillUniform(d, random.asJavaRandom()) + return d + } @Test fun size() { val m = randomMatrix - val w = EjmlVector(m) - assertEquals(m.numRows(), w.size) + val w = EjmlDoubleVector(m) + assertEquals(m.numRows, w.size) } @Test fun get() { val m = randomMatrix - val w = EjmlVector(m) + val w = EjmlDoubleVector(m) assertEquals(m[0, 0], w[0]) } @Test fun iterator() { val m = randomMatrix - val w = EjmlVector(m) + val w = EjmlDoubleVector(m) assertEquals( - m.iterator(true, 0, 0, m.numRows() - 1, 0).asSequence().toList(), + m.iterator(true, 0, 0, m.numRows - 1, 0).asSequence().toList(), w.iterator().asSequence().toList() ) } @@ -46,7 +51,7 @@ internal class EjmlVectorTest { @Test fun origin() { val m = randomMatrix - val w = EjmlVector(m) + val w = EjmlDoubleVector(m) assertSame(m, w.origin) } } diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 20e52deb2..46bf657c3 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -15,7 +15,6 @@ The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-d ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap } @@ -28,7 +27,6 @@ dependencies { repositories { maven("https://repo.kotlin.link") maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a } dependencies { diff --git a/kmath-functions/README.md b/kmath-functions/README.md index d5907f1c5..c7c30f1a1 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -17,7 +17,6 @@ The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0- ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap } @@ -30,7 +29,6 @@ dependencies { repositories { maven("https://repo.kotlin.link") maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a } dependencies { diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index f627beec9..ed5b5bcb4 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -4,8 +4,8 @@ plugins { } dependencies { - implementation("com.github.breandan:kaliningraph:0.1.4") - implementation("com.github.breandan:kotlingrad:0.4.0") + api("com.github.breandan:kaliningraph:0.1.4") + api("com.github.breandan:kotlingrad:0.4.5") api(project(":kmath-ast")) } diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 66e0483a4..b4b586ea9 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -15,8 +15,7 @@ The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-7 ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -27,8 +26,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 232bd1388..2e932b441 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -7,9 +7,9 @@ description = "Binding for https://github.com/JetBrains-Research/viktor" dependencies { api(project(":kmath-core")) - api("org.jetbrains.bio:viktor:1.0.1") + api("org.jetbrains.bio:viktor:1.1.0") } readme { maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT -} \ No newline at end of file +} From 2aed0316f4a38f32ed53e2895d6d7f5a74c779f5 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 30 Apr 2021 20:28:55 +0700 Subject: [PATCH 147/211] Use GraalVM as CI JDK --- .github/workflows/build.yml | 6 ++++-- .github/workflows/pages.yml | 6 ++++-- .github/workflows/publish.yml | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f39e12a12..9a9f04621 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,9 +13,11 @@ jobs: - name: Checkout the repo uses: actions/checkout@v2 - name: Set up JDK 11 - uses: actions/setup-java@v1 + uses: DeLaGuardo/setup-graalvm@4.0 with: - java-version: 11 + graalvm: 21.1.0 + java: java11 + arch: amd64 - name: Add msys to path if: matrix.os == 'windows-latest' run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index c70227fce..5892b3c4c 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -12,9 +12,11 @@ jobs: - name: Checkout the repo uses: actions/checkout@v2 - name: Set up JDK 11 - uses: actions/setup-java@v1 + uses: DeLaGuardo/setup-graalvm@4.0 with: - java-version: 11 + graalvm: 21.1.0 + java: java11 + arch: amd64 - name: Cache gradle uses: actions/cache@v2 with: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ca374574e..c5c110e89 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,9 +18,11 @@ jobs: - name: Checkout the repo uses: actions/checkout@v2 - name: Set up JDK 11 - uses: actions/setup-java@v1 + uses: DeLaGuardo/setup-graalvm@4.0 with: - java-version: 11 + graalvm: 21.1.0 + java: java11 + arch: amd64 - name: Add msys to path if: matrix.os == 'windows-latest' run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" From e5e62bc544143ef4f341257c7d143a5b8a813656 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 14:38:03 +0100 Subject: [PATCH 148/211] Extending from Algebra --- .../kmath/tensors/api/TensorAlgebra.kt | 4 ++- .../algebras/BroadcastDoubleTensorAlgebra.kt | 3 +- .../algebras/DoubleAnalyticTensorAlgebra.kt | 10 ++----- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 12 +++----- .../core/algebras/DoubleTensorAlgebra.kt | 5 +--- .../kmath/tensors/core/broadcastUtils.kt | 4 --- .../kscience/kmath/tensors/core/linUtils.kt | 3 +- .../kmath/tensors/core/TestBroadcasting.kt | 16 ++++++----- .../core/TestDoubleAnalyticTensorAlgebra.kt | 5 ++-- .../core/TestDoubleLinearOpsAlgebra.kt | 28 +++++++++---------- .../kmath/tensors/core/TestDoubleTensor.kt | 9 +++--- .../tensors/core/TestDoubleTensorAlgebra.kt | 21 +++++++------- 12 files changed, 56 insertions(+), 64 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 338064231..96d6985d8 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -5,13 +5,15 @@ package space.kscience.kmath.tensors.api +import space.kscience.kmath.operations.Algebra + /** * Algebra over a ring on [TensorStructure]. * For more information: https://proofwiki.org/wiki/Definition:Algebra_over_Ring * * @param T the type of items in the tensors. */ -public interface TensorAlgebra { +public interface TensorAlgebra: Algebra> { /** * Returns a single tensor value of unit dimension. The tensor shape must be equal to [1]. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt index a49d9ab29..fa64092d6 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -14,7 +14,7 @@ import space.kscience.kmath.tensors.core.broadcastTo * Basic linear algebra operations implemented with broadcasting. * For more information: https://pytorch.org/docs/stable/notes/broadcasting.html */ -public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { +public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { val broadcast = broadcastTensors(tensor, other.tensor) @@ -89,5 +89,4 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { newOther.buffer.array()[tensor.bufferStart + i] } } - } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 7d1cceb15..4a942df84 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -11,10 +11,9 @@ import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.tensor import kotlin.math.* -public class DoubleAnalyticTensorAlgebra: +public object DoubleAnalyticTensorAlgebra : AnalyticTensorAlgebra, - DoubleTensorAlgebra() -{ + DoubleTensorAlgebra() { override fun TensorStructure.exp(): DoubleTensor = tensor.map(::exp) override fun TensorStructure.log(): DoubleTensor = tensor.map(::ln) @@ -49,7 +48,4 @@ public class DoubleAnalyticTensorAlgebra: override fun TensorStructure.floor(): DoubleTensor = tensor.map(::floor) -} - -public inline fun DoubleAnalyticTensorAlgebra(block: DoubleAnalyticTensorAlgebra.() -> R): R = - DoubleAnalyticTensorAlgebra().block() \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 03f383728..975755656 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -21,7 +21,7 @@ import space.kscience.kmath.tensors.core.pivInit import kotlin.math.min -public class DoubleLinearOpsTensorAlgebra : +public object DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, DoubleTensorAlgebra() { @@ -30,8 +30,8 @@ public class DoubleLinearOpsTensorAlgebra : override fun TensorStructure.det(): DoubleTensor = detLU(1e-9) public fun TensorStructure.luFactor(epsilon: Double): Pair = - computeLU(tensor, epsilon) ?: - throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon") + computeLU(tensor, epsilon) + ?: throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon") public fun TensorStructure.luFactor(): Pair = luFactor(1e-9) @@ -175,8 +175,4 @@ public class DoubleLinearOpsTensorAlgebra : override fun TensorStructure.lu(): Triple = lu(1e-9) - -} - -public inline fun DoubleLinearOpsTensorAlgebra(block: DoubleLinearOpsTensorAlgebra.() -> R): R = - DoubleLinearOpsTensorAlgebra().block() \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 7414a4469..8729358cc 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -23,6 +23,7 @@ import kotlin.math.abs public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { + public companion object : DoubleTensorAlgebra() override fun TensorStructure.value(): Double { check(tensor.shape contentEquals intArrayOf(1)) { @@ -395,7 +396,3 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) } - - -public inline fun DoubleTensorAlgebra(block: DoubleTensorAlgebra.() -> R): R = - DoubleTensorAlgebra().block() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt index 4378e9ac9..71ccbf97b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt @@ -1,11 +1,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra import kotlin.math.max -public inline fun BroadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorAlgebra.() -> R): R = - BroadcastDoubleTensorAlgebra().block() - internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) { for (linearIndex in 0 until linearSize) { val totalMultiIndex = resTensor.linearStructure.index(linearIndex) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt index 3a130c71e..c7a730018 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt @@ -4,6 +4,7 @@ import space.kscience.kmath.nd.MutableStructure1D import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra import kotlin.math.abs @@ -251,7 +252,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper( } } } - r[j, j] = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + r[j, j] = DoubleAnalyticTensorAlgebra.invoke { (v dot v).sqrt().value() } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index d677f6966..207dd1c98 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -1,13 +1,15 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.test.Test import kotlin.test.assertTrue -class TestBroadcasting { +internal class TestBroadcasting { @Test - fun broadcastShapes() = DoubleTensorAlgebra { + fun broadcastShapes() = DoubleTensorAlgebra.invoke { assertTrue( broadcastShapes( intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) @@ -22,7 +24,7 @@ class TestBroadcasting { } @Test - fun broadcastTo() = DoubleTensorAlgebra { + fun broadcastTo() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) @@ -32,7 +34,7 @@ class TestBroadcasting { } @Test - fun broadcastTensors() = DoubleTensorAlgebra { + fun broadcastTensors() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -49,7 +51,7 @@ class TestBroadcasting { } @Test - fun broadcastOuterTensors() = DoubleTensorAlgebra { + fun broadcastOuterTensors() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -66,7 +68,7 @@ class TestBroadcasting { } @Test - fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra { + fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) {0.0}) val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) {0.0}) val tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0)) @@ -79,7 +81,7 @@ class TestBroadcasting { } @Test - fun minusTensor() = BroadcastDoubleTensorAlgebra { + fun minusTensor() = BroadcastDoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 060bc1607..3b3e22acc 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -1,12 +1,13 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import kotlin.math.abs import kotlin.math.exp import kotlin.test.Test import kotlin.test.assertTrue -class TestDoubleAnalyticTensorAlgebra { +internal class TestDoubleAnalyticTensorAlgebra { val shape = intArrayOf(2, 1, 3, 2) val buffer = doubleArrayOf(27.1, 20.0, 19.84, 23.123, 0.0, 1.0, 3.23, 133.7, 25.3, 100.3, 11.0, 12.012) @@ -26,7 +27,7 @@ class TestDoubleAnalyticTensorAlgebra { } @Test - fun testExp() = DoubleAnalyticTensorAlgebra { + fun testExp() = DoubleAnalyticTensorAlgebra.invoke { tensor.exp().let { assertTrue { shape contentEquals it.shape } assertTrue { buffer.fmap(::exp).epsEqual(it.buffer.array())} 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 b2ef6b4c4..aa68340d4 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 @@ -1,15 +1,16 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra import kotlin.math.abs import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue -class TestDoubleLinearOpsTensorAlgebra { +internal class TestDoubleLinearOpsTensorAlgebra { @Test - fun testDetLU() = DoubleLinearOpsTensorAlgebra { + fun testDetLU() = DoubleLinearOpsTensorAlgebra.invoke { val tensor = fromArray( intArrayOf(2, 2, 2), doubleArrayOf( @@ -34,7 +35,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testDet() = DoubleLinearOpsTensorAlgebra { + fun testDet() = DoubleLinearOpsTensorAlgebra.invoke { val expectedValue = 0.019827417 val m = fromArray( intArrayOf(3, 3), doubleArrayOf( @@ -48,7 +49,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testDetSingle() = DoubleLinearOpsTensorAlgebra { + fun testDetSingle() = DoubleLinearOpsTensorAlgebra.invoke { val expectedValue = 48.151623 val m = fromArray( intArrayOf(1, 1), doubleArrayOf( @@ -60,7 +61,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testInvLU() = DoubleLinearOpsTensorAlgebra { + fun testInvLU() = DoubleLinearOpsTensorAlgebra.invoke { val tensor = fromArray( intArrayOf(2, 2, 2), doubleArrayOf( @@ -85,14 +86,14 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testScalarProduct() = DoubleLinearOpsTensorAlgebra { + fun testScalarProduct() = DoubleLinearOpsTensorAlgebra.invoke { val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) assertEquals(a.dot(b).value(), 59.92) } @Test - fun testQR() = DoubleLinearOpsTensorAlgebra { + fun testQR() = DoubleLinearOpsTensorAlgebra.invoke { val shape = intArrayOf(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, @@ -110,11 +111,10 @@ class TestDoubleLinearOpsTensorAlgebra { assertTrue((q dot r).eq(tensor)) - //todo check orthogonality/upper triang. } @Test - fun testLU() = DoubleLinearOpsTensorAlgebra { + fun testLU() = DoubleLinearOpsTensorAlgebra.invoke { val shape = intArrayOf(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, @@ -134,7 +134,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testCholesky() = DoubleLinearOpsTensorAlgebra { + fun testCholesky() = DoubleLinearOpsTensorAlgebra.invoke { val tensor = randNormal(intArrayOf(2, 5, 5), 0) val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) @@ -145,7 +145,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testSVD1D() = DoubleLinearOpsTensorAlgebra { + fun testSVD1D() = DoubleLinearOpsTensorAlgebra.invoke { val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = svd1d(tensor2) @@ -156,13 +156,13 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testSVD() = DoubleLinearOpsTensorAlgebra { + fun testSVD() = DoubleLinearOpsTensorAlgebra.invoke{ testSVDFor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } @Test - fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { + fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra.invoke { val tensor = randNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) @@ -170,7 +170,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { + fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra.invoke { val tensor = randNormal(shape = intArrayOf(2, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 7103eafaa..20acc0901 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -4,6 +4,7 @@ import space.kscience.kmath.nd.DefaultStrides import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asMutableBuffer import space.kscience.kmath.structures.toDoubleArray @@ -12,17 +13,17 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue -class TestDoubleTensor { +internal class TestDoubleTensor { @Test - fun valueTest() = DoubleTensorAlgebra { + fun valueTest() = DoubleTensorAlgebra.invoke { val value = 12.5 val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @Test - fun stridesTest() = DoubleTensorAlgebra { + fun stridesTest() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) assertEquals(tensor[intArrayOf(0, 1)], 5.8) assertTrue( @@ -31,7 +32,7 @@ class TestDoubleTensor { } @Test - fun getTest() = DoubleTensorAlgebra { + fun getTest() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) val matrix = tensor[0].as2D() assertEquals(matrix[0, 1], 5.8) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 1333a7a1f..115016974 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -1,29 +1,30 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.test.Test import kotlin.test.assertFalse import kotlin.test.assertTrue -class TestDoubleTensorAlgebra { +internal class TestDoubleTensorAlgebra { @Test - fun doublePlus() = DoubleTensorAlgebra { + fun doublePlus() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0, 12.0)) } @Test - fun doubleDiv() = DoubleTensorAlgebra { + fun doubleDiv() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0)) val res = 2.0/tensor assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 0.5)) } @Test - fun divDouble() = DoubleTensorAlgebra { + fun divDouble() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0)) val res = tensor / 2.5 assertTrue(res.buffer.array() contentEquals doubleArrayOf(4.0, 2.0)) @@ -39,7 +40,7 @@ class TestDoubleTensorAlgebra { } @Test - fun transpose3x2() = DoubleTensorAlgebra { + fun transpose3x2() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) @@ -48,7 +49,7 @@ class TestDoubleTensorAlgebra { } @Test - fun transpose1x2x3() = DoubleTensorAlgebra { + fun transpose1x2x3() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transpose(0, 1) val res02 = tensor.transpose(-3, 2) @@ -64,7 +65,7 @@ class TestDoubleTensorAlgebra { } @Test - fun linearStructure() = DoubleTensorAlgebra { + fun linearStructure() = DoubleTensorAlgebra.invoke { val shape = intArrayOf(3) val tensorA = full(value = -4.5, shape = shape) val tensorB = full(value = 10.9, shape = shape) @@ -96,7 +97,7 @@ class TestDoubleTensorAlgebra { } @Test - fun dot() = DoubleTensorAlgebra { + fun dot() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor11 = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) @@ -132,7 +133,7 @@ class TestDoubleTensorAlgebra { } @Test - fun diagonalEmbedding() = DoubleTensorAlgebra { + fun diagonalEmbedding() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = zeros(intArrayOf(2, 3, 4, 5)) @@ -165,7 +166,7 @@ class TestDoubleTensorAlgebra { } @Test - fun testEq() = DoubleTensorAlgebra { + fun testEq() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) From 6be5caa93f4086e222677a55d15edaca707b16f0 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 14:44:42 +0100 Subject: [PATCH 149/211] No secondary constructors --- .../kmath/tensors/core/BufferedTensor.kt | 25 +++---- .../algebras/BroadcastDoubleTensorAlgebra.kt | 28 ++++---- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 2 +- .../core/algebras/DoubleTensorAlgebra.kt | 68 +++++++++---------- .../kmath/tensors/core/broadcastUtils.kt | 10 +-- .../kscience/kmath/tensors/core/linUtils.kt | 14 ++-- .../kmath/tensors/core/TestBroadcasting.kt | 20 +++--- .../core/TestDoubleAnalyticTensorAlgebra.kt | 2 +- .../core/TestDoubleLinearOpsAlgebra.kt | 4 +- .../kmath/tensors/core/TestDoubleTensor.kt | 5 +- .../tensors/core/TestDoubleTensorAlgebra.kt | 34 +++++----- 11 files changed, 103 insertions(+), 109 deletions(-) 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 6e1cab11a..fae59804d 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 @@ -8,7 +8,7 @@ import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure public open class BufferedTensor( override val shape: IntArray, - internal val buffer: MutableBuffer, + internal val mutableBuffer: MutableBuffer, internal val bufferStart: Int ) : TensorStructure { public val linearStructure: TensorLinearStructure @@ -17,10 +17,10 @@ public open class BufferedTensor( public val numElements: Int get() = linearStructure.size - override fun get(index: IntArray): T = buffer[bufferStart + linearStructure.offset(index)] + override fun get(index: IntArray): T = mutableBuffer[bufferStart + linearStructure.offset(index)] override fun set(index: IntArray, value: T) { - buffer[bufferStart + linearStructure.offset(index)] = value + mutableBuffer[bufferStart + linearStructure.offset(index)] = value } override fun elements(): Sequence> = linearStructure.indices().map { @@ -37,33 +37,28 @@ public class IntTensor internal constructor( shape: IntArray, buffer: IntArray, offset: Int = 0 -) : BufferedTensor(shape, IntBuffer(buffer), offset) { - internal constructor(bufferedTensor: BufferedTensor) : - this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) -} +) : BufferedTensor(shape, IntBuffer(buffer), offset) public class DoubleTensor internal constructor( shape: IntArray, buffer: DoubleArray, offset: Int = 0 ) : BufferedTensor(shape, DoubleBuffer(buffer), offset) { - internal constructor(bufferedTensor: BufferedTensor) : - this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) - override fun toString(): String = toPrettyString() - } -internal inline fun BufferedTensor.asTensor(): IntTensor = IntTensor(this) -internal inline fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this) +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 inline fun TensorStructure.copyToBufferedTensor(): BufferedTensor = +internal fun TensorStructure.copyToBufferedTensor(): BufferedTensor = BufferedTensor( this.shape, TensorLinearStructure(this.shape).indices().map(this::get).toMutableList().asMutableBuffer(), 0 ) -internal inline fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { +internal fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { is BufferedTensor -> this is MutableBufferND -> if (this.strides.strides.toIntArray() contentEquals TensorLinearStructure(this.shape).strides) BufferedTensor(this.shape, this.mutableBuffer, 0) else this.copyToBufferedTensor() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt index fa64092d6..350d939af 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -21,7 +21,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[i] + newOther.buffer.array()[i] + newThis.mutableBuffer.array()[i] + newOther.mutableBuffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -29,8 +29,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.plusAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] += - newOther.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] += + newOther.mutableBuffer.array()[tensor.bufferStart + i] } } @@ -39,7 +39,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[i] - newOther.buffer.array()[i] + newThis.mutableBuffer.array()[i] - newOther.mutableBuffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -47,8 +47,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.minusAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] -= - newOther.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] -= + newOther.mutableBuffer.array()[tensor.bufferStart + i] } } @@ -57,8 +57,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[newThis.bufferStart + i] * - newOther.buffer.array()[newOther.bufferStart + i] + newThis.mutableBuffer.array()[newThis.bufferStart + i] * + newOther.mutableBuffer.array()[newOther.bufferStart + i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -66,8 +66,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.timesAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] *= - newOther.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] *= + newOther.mutableBuffer.array()[tensor.bufferStart + i] } } @@ -76,8 +76,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[newOther.bufferStart + i] / - newOther.buffer.array()[newOther.bufferStart + i] + newThis.mutableBuffer.array()[newOther.bufferStart + i] / + newOther.mutableBuffer.array()[newOther.bufferStart + i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -85,8 +85,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.divAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] /= - newOther.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] /= + newOther.mutableBuffer.array()[tensor.bufferStart + i] } } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 975755656..ab73b25b1 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -106,7 +106,7 @@ public object DoubleLinearOpsTensorAlgebra : val matrixSize = matrix.shape.reduce { acc, i -> acc * i } val curMatrix = DoubleTensor( matrix.shape, - matrix.buffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize).toDoubleArray() + matrix.mutableBuffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize).toDoubleArray() ) svdHelper(curMatrix, USV, m, n, epsilon) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 8729358cc..f428b9d2e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -29,7 +29,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { check(tensor.shape contentEquals intArrayOf(1)) { "Inconsistent value for tensor of shape ${shape.toList()}" } - return tensor.buffer.array()[tensor.bufferStart] + return tensor.mutableBuffer.array()[tensor.bufferStart] } public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor { @@ -43,7 +43,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { val lastShape = tensor.shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) val newStart = newShape.reduce(Int::times) * i + tensor.bufferStart - return DoubleTensor(newShape, tensor.buffer.array(), newStart) + return DoubleTensor(newShape, tensor.mutableBuffer.array(), newStart) } public fun full(value: Double, shape: IntArray): DoubleTensor { @@ -77,12 +77,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } public fun TensorStructure.copy(): DoubleTensor { - return DoubleTensor(tensor.shape, tensor.buffer.array().copyOf(), tensor.bufferStart) + return DoubleTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart) } override fun Double.plus(other: TensorStructure): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> - other.tensor.buffer.array()[other.tensor.bufferStart + i] + this + other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] + this } return DoubleTensor(other.shape, resBuffer) } @@ -92,35 +92,35 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { checkShapesCompatible(tensor, other.tensor) val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[i] + other.tensor.buffer.array()[i] + tensor.mutableBuffer.array()[i] + other.tensor.mutableBuffer.array()[i] } return DoubleTensor(tensor.shape, resBuffer) } override fun TensorStructure.plusAssign(value: Double) { for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] += value + tensor.mutableBuffer.array()[tensor.bufferStart + i] += value } } override fun TensorStructure.plusAssign(other: TensorStructure) { checkShapesCompatible(tensor, other.tensor) for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] += - other.tensor.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] += + other.tensor.mutableBuffer.array()[tensor.bufferStart + i] } } override fun Double.minus(other: TensorStructure): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> - this - other.tensor.buffer.array()[other.tensor.bufferStart + i] + this - other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } override fun TensorStructure.minus(value: Double): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[tensor.bufferStart + i] - value + tensor.mutableBuffer.array()[tensor.bufferStart + i] - value } return DoubleTensor(tensor.shape, resBuffer) } @@ -128,28 +128,28 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[i] - other.tensor.buffer.array()[i] + tensor.mutableBuffer.array()[i] - other.tensor.mutableBuffer.array()[i] } return DoubleTensor(tensor.shape, resBuffer) } override fun TensorStructure.minusAssign(value: Double) { for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] -= value + tensor.mutableBuffer.array()[tensor.bufferStart + i] -= value } } override fun TensorStructure.minusAssign(other: TensorStructure) { checkShapesCompatible(tensor, other) for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] -= - other.tensor.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] -= + other.tensor.mutableBuffer.array()[tensor.bufferStart + i] } } override fun Double.times(other: TensorStructure): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> - other.tensor.buffer.array()[other.tensor.bufferStart + i] * this + other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) } @@ -159,36 +159,36 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun TensorStructure.times(other: TensorStructure): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[tensor.bufferStart + i] * - other.tensor.buffer.array()[other.tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] * + other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(tensor.shape, resBuffer) } override fun TensorStructure.timesAssign(value: Double) { for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] *= value + tensor.mutableBuffer.array()[tensor.bufferStart + i] *= value } } override fun TensorStructure.timesAssign(other: TensorStructure) { checkShapesCompatible(tensor, other) for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] *= - other.tensor.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] *= + other.tensor.mutableBuffer.array()[tensor.bufferStart + i] } } override fun Double.div(other: TensorStructure): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> - this / other.tensor.buffer.array()[other.tensor.bufferStart + i] + this / other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } override fun TensorStructure.div(value: Double): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[tensor.bufferStart + i] / value + tensor.mutableBuffer.array()[tensor.bufferStart + i] / value } return DoubleTensor(shape, resBuffer) } @@ -196,29 +196,29 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun TensorStructure.div(other: TensorStructure): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[other.tensor.bufferStart + i] / - other.tensor.buffer.array()[other.tensor.bufferStart + i] + tensor.mutableBuffer.array()[other.tensor.bufferStart + i] / + other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(tensor.shape, resBuffer) } override fun TensorStructure.divAssign(value: Double) { for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] /= value + tensor.mutableBuffer.array()[tensor.bufferStart + i] /= value } } override fun TensorStructure.divAssign(other: TensorStructure) { checkShapesCompatible(tensor, other) for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] /= - other.tensor.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] /= + other.tensor.mutableBuffer.array()[tensor.bufferStart + i] } } override fun TensorStructure.unaryMinus(): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[tensor.bufferStart + i].unaryMinus() + tensor.mutableBuffer.array()[tensor.bufferStart + i].unaryMinus() } return DoubleTensor(tensor.shape, resBuffer) } @@ -241,8 +241,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } val linearIndex = resTensor.linearStructure.offset(newMultiIndex) - resTensor.buffer.array()[linearIndex] = - tensor.buffer.array()[tensor.bufferStart + offset] + resTensor.mutableBuffer.array()[linearIndex] = + tensor.mutableBuffer.array()[tensor.bufferStart + offset] } return resTensor } @@ -250,7 +250,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun TensorStructure.view(shape: IntArray): DoubleTensor { checkView(tensor, shape) - return DoubleTensor(shape, tensor.buffer.array(), tensor.bufferStart) + return DoubleTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart) } override fun TensorStructure.viewAs(other: TensorStructure): DoubleTensor { @@ -259,7 +259,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override infix fun TensorStructure.dot(other: TensorStructure): DoubleTensor { if (tensor.shape.size == 1 && other.shape.size == 1) { - return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.buffer.array().sum())) + return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.mutableBuffer.array().sum())) } var newThis = tensor.copy() @@ -361,7 +361,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun TensorStructure.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( tensor.shape, - tensor.buffer.array().map { transform(it) }.toDoubleArray(), + tensor.mutableBuffer.array().map { transform(it) }.toDoubleArray(), tensor.bufferStart ) } @@ -382,7 +382,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return false } for (i in 0 until n) { - if (!eqFunction(tensor.buffer[tensor.bufferStart + i], other.tensor.buffer[other.tensor.bufferStart + i])) { + if (!eqFunction(tensor.mutableBuffer[tensor.bufferStart + i], other.tensor.mutableBuffer[other.tensor.bufferStart + i])) { return false } } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt index 71ccbf97b..2d4d6f0f7 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt @@ -18,8 +18,8 @@ internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: Doub } val curLinearIndex = tensor.linearStructure.offset(curMultiIndex) - resTensor.buffer.array()[linearIndex] = - tensor.buffer.array()[tensor.bufferStart + curLinearIndex] + resTensor.mutableBuffer.array()[linearIndex] = + tensor.mutableBuffer.array()[tensor.bufferStart + curLinearIndex] } } @@ -113,7 +113,7 @@ internal inline fun broadcastOuterTensors(vararg tensors: DoubleTensor): List BufferedTensor.vectorSequence(): Sequence BufferedTensor.matrixSequence(): Sequence Date: Wed, 31 Mar 2021 19:39:34 +0700 Subject: [PATCH 150/211] Add Jupyter integration --- CHANGELOG.md | 1 + build.gradle.kts | 1 + .../ast/rendering/MathMLSyntaxRenderer.kt | 9 +- kmath-core/api/kmath-core.api | 2 + .../kscience/kmath/expressions/MstAlgebra.kt | 1 + kmath-jupyter/build.gradle.kts | 19 +++ .../kscience/kmath/jupyter/KMathJupyter.kt | 120 ++++++++++++++++++ settings.gradle.kts | 4 + 8 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 kmath-jupyter/build.gradle.kts create mode 100644 kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 4266c5b70..cdc82753c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Multiplatform integration - Integration for any Field element - Extended operations for ND4J fields +- Jupyter Notebook integration module (kmath-jupyter) ### Changed - Exponential operations merged with hyperbolic functions diff --git a/build.gradle.kts b/build.gradle.kts index 506f51a0e..760bf1aee 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("ru.mipt.npm.gradle.project") + kotlin("jupyter.api") apply false } allprojects { diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index 517ec0dc9..5b44e660d 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -18,11 +18,14 @@ import space.kscience.kmath.misc.UnstableKMathAPI public object MathMLSyntaxRenderer : SyntaxRenderer { public override fun render(node: MathSyntax, output: Appendable) { output.append("") - render0(node, output) + renderPart(node, output) output.append("") } - private fun render0(node: MathSyntax, output: Appendable): Unit = output.run { + /** + * Renders a part of syntax returning a correct MathML tag not the whole MathML instance. + */ + public fun renderPart(node: MathSyntax, output: Appendable): Unit = output.run { fun tag(tagName: String, vararg attr: Pair, block: () -> Unit = {}) { append('<') append(tagName) @@ -47,7 +50,7 @@ public object MathMLSyntaxRenderer : SyntaxRenderer { append('>') } - fun render(syntax: MathSyntax) = render0(syntax, output) + fun render(syntax: MathSyntax) = renderPart(syntax, output) when (node) { is NumberSyntax -> tag("mn") { append(node.string) } diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 6b300123c..82b44d275 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -272,6 +272,8 @@ public final class space/kscience/kmath/expressions/MstExtendedField : space/ksc public fun sin (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; + public fun sqrt (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; public fun tan (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt index 32a7efc1e..53124b777 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt @@ -135,6 +135,7 @@ public object MstExtendedField : ExtendedField, NumericAlgebra { public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ACOSH_OPERATION)(arg) public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ATANH_OPERATION)(arg) public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b) + public override fun sqrt(arg: MST): MST = unaryOperationFunction(PowerOperations.SQRT_OPERATION)(arg) public override fun scale(a: MST, value: Double): MST = binaryOperation(GroupOperations.PLUS_OPERATION, a, number(value)) diff --git a/kmath-jupyter/build.gradle.kts b/kmath-jupyter/build.gradle.kts new file mode 100644 index 000000000..815cb9b8c --- /dev/null +++ b/kmath-jupyter/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + id("ru.mipt.npm.gradle.jvm") + kotlin("jupyter.api") +} + +dependencies { + api(project(":kmath-ast")) + api(project(":kmath-complex")) + api(project(":kmath-for-real")) + implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.3") +} + +readme { + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE +} + +kotlin.sourceSets.all { + languageSettings.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") +} diff --git a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt new file mode 100644 index 000000000..e13c92f75 --- /dev/null +++ b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt @@ -0,0 +1,120 @@ +package space.kscience.kmath.jupyter + +import kotlinx.html.Unsafe +import kotlinx.html.div +import kotlinx.html.stream.createHTML +import kotlinx.html.unsafe +import org.jetbrains.kotlinx.jupyter.api.DisplayResult +import org.jetbrains.kotlinx.jupyter.api.HTML +import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary +import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess +import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer +import space.kscience.kmath.ast.rendering.renderWithStringBuilder +import space.kscience.kmath.complex.Complex +import space.kscience.kmath.nd.Structure2D +import space.kscience.kmath.operations.GroupOperations +import space.kscience.kmath.operations.RingOperations +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asSequence + +@JupyterLibrary +internal class KMathJupyter : JupyterIntegration() { + private val mathRender = FeaturedMathRendererWithPostProcess.Default + private val syntaxRender = MathMLSyntaxRenderer + + override fun Builder.onLoaded() { + import( + "space.kscience.kmath.ast.*", + "space.kscience.kmath.ast.rendering.*", + "space.kscience.kmath.operations.*", + "space.kscience.kmath.expressions.*", + "space.kscience.kmath.misc.*", + "space.kscience.kmath.real.*", + ) + + fun MST.toDisplayResult(): DisplayResult = HTML(createHTML().div { + unsafe { + +syntaxRender.renderWithStringBuilder(mathRender.render(this@toDisplayResult)) + } + }) + + render { it.toDisplayResult() } + render { MST.Numeric(it).toDisplayResult() } + + fun Unsafe.appendCellValue(it: Any?) { + when (it) { + is Number -> { + val s = StringBuilder() + syntaxRender.renderPart(mathRender.render(MST.Numeric(it)), s) + +s.toString() + } + is MST -> { + val s = StringBuilder() + syntaxRender.renderPart(mathRender.render(it), s) + +s.toString() + } + else -> { + +"" + +it.toString() + +"" + } + } + } + + render> { structure -> + HTML(createHTML().div { + unsafe { + +"" + +"" + +"" + +"" + structure.rows.forEach { row -> + +"" + row.asSequence().forEach { + +"" + appendCellValue(it) + +"" + } + +"" + } + +"" + +"" + +"" + +"" + } + }) + } + + render> { buffer -> + HTML(createHTML().div { + unsafe { + +"" + +"" + +"" + +"" + buffer.asSequence().forEach { + +"" + +"" + appendCellValue(it) + +"" + +"" + } + +"" + +"" + +"" + +"" + } + }) + } + + render { + MST.Binary( + operation = GroupOperations.PLUS_OPERATION, + left = MST.Numeric(it.re), + right = MST.Binary(RingOperations.TIMES_OPERATION, MST.Numeric(it.im), MST.Symbolic("i")), + ).toDisplayResult() + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index ca36168e1..b7613d589 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,6 +17,9 @@ pluginManagement { id("ru.mipt.npm.gradle.project") version toolsVersion id("ru.mipt.npm.gradle.mpp") version toolsVersion id("ru.mipt.npm.gradle.jvm") version toolsVersion + kotlin("jupyter.api") version "0.9.0.12" + kotlin("jvm") version kotlinVersion + kotlin("plugin.allopen") version kotlinVersion } } @@ -39,6 +42,7 @@ include( ":kmath-ast", ":kmath-ejml", ":kmath-kotlingrad", + ":kmath-jupyter", ":examples", ":benchmarks" ) From 86c2816cfde632cdb734d18d75e7245e3ae54f0c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 14:53:02 +0100 Subject: [PATCH 151/211] Fixed strides code duplication --- kmath-core/api/kmath-core.api | 4 ++-- .../space/kscience/kmath/nd/StructureND.kt | 6 +++--- .../kmath/tensors/core/BufferedTensor.kt | 4 ++-- .../algebras/BroadcastDoubleTensorAlgebra.kt | 16 +++++++------- .../core/algebras/TensorLinearStructure.kt | 21 ++++++++++--------- 5 files changed, 26 insertions(+), 25 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 41b85b3bb..1b98f547c 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -789,7 +789,7 @@ public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath public fun equals (Ljava/lang/Object;)Z public fun getLinearSize ()I public fun getShape ()[I - public fun getStrides ()Ljava/util/List; + public fun getStrides ()[I public fun hashCode ()I public fun index (I)[I public fun offset ([I)I @@ -931,7 +931,7 @@ public final class space/kscience/kmath/nd/ShortRingNDKt { public abstract interface class space/kscience/kmath/nd/Strides { public abstract fun getLinearSize ()I public abstract fun getShape ()[I - public abstract fun getStrides ()Ljava/util/List; + public abstract fun getStrides ()[I public abstract fun index (I)[I public fun indices ()Lkotlin/sequences/Sequence; public abstract fun offset ([I)I diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index 0656b1f7f..65c233012 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -184,7 +184,7 @@ public interface Strides { /** * Array strides */ - public val strides: List + public val strides: IntArray /** * Get linear index from multidimensional index @@ -221,7 +221,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) : /** * Strides for memory access */ - override val strides: List by lazy { + override val strides: IntArray by lazy { sequence { var current = 1 yield(1) @@ -230,7 +230,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) : current *= it yield(current) } - }.toList() + }.toList().toIntArray() } override fun offset(index: IntArray): Int = index.mapIndexed { i, value -> 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 fae59804d..21030bbc7 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 @@ -15,7 +15,7 @@ public open class BufferedTensor( get() = TensorLinearStructure(shape) public val numElements: Int - get() = linearStructure.size + get() = linearStructure.linearSize override fun get(index: IntArray): T = mutableBuffer[bufferStart + linearStructure.offset(index)] @@ -60,7 +60,7 @@ internal fun TensorStructure.copyToBufferedTensor(): BufferedTensor = internal fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { is BufferedTensor -> this - is MutableBufferND -> if (this.strides.strides.toIntArray() contentEquals TensorLinearStructure(this.shape).strides) + is MutableBufferND -> if (this.strides.strides contentEquals TensorLinearStructure(this.shape).strides) BufferedTensor(this.shape, this.mutableBuffer, 0) else this.copyToBufferedTensor() else -> this.copyToBufferedTensor() } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt index 350d939af..9b97d5ef2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -20,7 +20,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.linearSize) { i -> newThis.mutableBuffer.array()[i] + newOther.mutableBuffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) @@ -28,7 +28,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.plusAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { + for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] += newOther.mutableBuffer.array()[tensor.bufferStart + i] } @@ -38,7 +38,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.linearSize) { i -> newThis.mutableBuffer.array()[i] - newOther.mutableBuffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) @@ -46,7 +46,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.minusAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { + for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] -= newOther.mutableBuffer.array()[tensor.bufferStart + i] } @@ -56,7 +56,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.linearSize) { i -> newThis.mutableBuffer.array()[newThis.bufferStart + i] * newOther.mutableBuffer.array()[newOther.bufferStart + i] } @@ -65,7 +65,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.timesAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { + for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] *= newOther.mutableBuffer.array()[tensor.bufferStart + i] } @@ -75,7 +75,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.linearSize) { i -> newThis.mutableBuffer.array()[newOther.bufferStart + i] / newOther.mutableBuffer.array()[newOther.bufferStart + i] } @@ -84,7 +84,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.divAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { + for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] /= newOther.mutableBuffer.array()[tensor.bufferStart + i] } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index b16739892..8e83dafd6 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -5,16 +5,17 @@ package space.kscience.kmath.tensors.core.algebras +import space.kscience.kmath.nd.Strides import kotlin.math.max -internal inline fun offsetFromIndex(index: IntArray, shape: IntArray, strides: IntArray): Int = +internal fun offsetFromIndex(index: IntArray, shape: IntArray, strides: IntArray): Int = index.mapIndexed { i, value -> if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})") value * strides[i] }.sum() -internal inline fun stridesFromShape(shape: IntArray): IntArray { +internal fun stridesFromShape(shape: IntArray): IntArray { val nDim = shape.size val res = IntArray(nDim) if (nDim == 0) @@ -31,7 +32,7 @@ internal inline fun stridesFromShape(shape: IntArray): IntArray { } -internal inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { +internal fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { val res = IntArray(nDim) var current = offset var strideIndex = 0 @@ -44,7 +45,7 @@ internal inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): return res } -internal inline fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { +internal fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { val res = index.copyOf() var current = nDim - 1 var carry = 0 @@ -62,26 +63,26 @@ internal inline fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntA } -public class TensorLinearStructure(public val shape: IntArray) +public class TensorLinearStructure(override val shape: IntArray) : Strides { - public val strides: IntArray + override val strides: IntArray get() = stridesFromShape(shape) - public fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides) + override fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides) - public fun index(offset: Int): IntArray = + override fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) public fun stepIndex(index: IntArray): IntArray = stepIndex(index, shape, shape.size) - public val size: Int + override val linearSize: Int get() = shape.reduce(Int::times) public val dim: Int get() = shape.size - public fun indices(): Sequence = (0 until size).asSequence().map { + override fun indices(): Sequence = (0 until linearSize).asSequence().map { index(it) } } \ No newline at end of file From 42ddd2e5692156ac4263f28fa9848e62180f2b38 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 15:08:32 +0100 Subject: [PATCH 152/211] MutableBufferFromGenerator --- kmath-core/api/kmath-core.api | 18 +++++++++--------- .../space/kscience/kmath/nd/Structure1D.kt | 4 ++-- .../space/kscience/kmath/nd/Structure2D.kt | 6 +++--- .../space/kscience/kmath/structures/Buffer.kt | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 1b98f547c..687de9cc8 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -1882,6 +1882,15 @@ public final class space/kscience/kmath/structures/MutableBuffer$Companion { public final fun short-1yRgbGw (ILkotlin/jvm/functions/Function1;)[S } +public final class space/kscience/kmath/structures/MutableBufferFromGenerator : space/kscience/kmath/structures/MutableBuffer { + public fun (ILkotlin/jvm/functions/Function1;)V + public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun get (I)Ljava/lang/Object; + public fun getSize ()I + public fun iterator ()Ljava/util/Iterator; + public fun set (ILjava/lang/Object;)V +} + public final class space/kscience/kmath/structures/MutableListBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/MutableListBuffer; public static fun constructor-impl (ILkotlin/jvm/functions/Function1;)Ljava/util/List; @@ -1990,12 +1999,3 @@ public final class space/kscience/kmath/structures/VirtualBuffer : space/kscienc public fun iterator ()Ljava/util/Iterator; } -public final class space/kscience/kmath/structures/VirtualMutableBuffer : space/kscience/kmath/structures/MutableBuffer { - public fun (ILkotlin/jvm/functions/Function1;)V - public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; - public fun get (I)Ljava/lang/Object; - public fun getSize ()I - public fun iterator ()Ljava/util/Iterator; - public fun set (ILjava/lang/Object;)V -} - diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 93fc48713..8ea6d0f02 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -52,7 +52,7 @@ private value class Structure1DWrapper(val structure: StructureND) : Struc /** * A 1D wrapper for a mutable nd-structure */ -private inline class MutableStructure1DWrapper(val structure: MutableStructureND) : MutableStructure1D { +private class MutableStructure1DWrapper(val structure: MutableStructureND) : MutableStructure1D { override val shape: IntArray get() = structure.shape override val size: Int get() = structure.shape[0] override fun elements(): Sequence> = structure.elements() @@ -81,7 +81,7 @@ private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D { override operator fun get(index: Int): T = buffer[index] } -internal inline class MutableBuffer1DWrapper(val buffer: MutableBuffer) : MutableStructure1D { +internal class MutableBuffer1DWrapper(val buffer: MutableBuffer) : MutableStructure1D { override val shape: IntArray get() = intArrayOf(buffer.size) override val size: Int get() = buffer.size diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 4c17d25d0..d987d8cf4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.VirtualBuffer -import space.kscience.kmath.structures.VirtualMutableBuffer +import space.kscience.kmath.structures.MutableBufferFromGenerator import kotlin.jvm.JvmInline import kotlin.reflect.KClass @@ -81,13 +81,13 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { * The buffer of rows of this structure. It gets elements from the structure dynamically. */ override val rows: List> - get() = List(rowNum) { i -> MutableBuffer1DWrapper(VirtualMutableBuffer(colNum) { j -> get(i, j) })} + get() = List(rowNum) { i -> MutableBuffer1DWrapper(MutableBufferFromGenerator(colNum) { j -> get(i, j) })} /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ override val columns: List> - get() = List(colNum) { j -> MutableBuffer1DWrapper(VirtualMutableBuffer(rowNum) { i -> get(i, j) }) } + get() = List(colNum) { j -> MutableBuffer1DWrapper(MutableBufferFromGenerator(rowNum) { i -> get(i, j) }) } } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 980fe698e..19018ffb5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -292,7 +292,7 @@ public class VirtualBuffer(override val size: Int, private val generator: (In override operator fun iterator(): Iterator = (0 until size).asSequence().map(generator).iterator() } -public class VirtualMutableBuffer(override val size: Int, private val generator: (Int) -> T) : MutableBuffer { +public class MutableBufferFromGenerator(override val size: Int, private val generator: (Int) -> T) : MutableBuffer { private val bufferHolder: MutableListBuffer = (0 until size).map(generator).toMutableList().asMutableBuffer() From 1695fc5075712c1c89121c0860c7c1e985737dbf Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 15:25:45 +0100 Subject: [PATCH 153/211] Fix examples --- .../space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt | 3 ++- .../src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index 38d8c1437..a84224bcf 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra @@ -13,7 +14,7 @@ import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra fun main () { // work in context with linear operations - DoubleLinearOpsTensorAlgebra { + DoubleLinearOpsTensorAlgebra.invoke { // set true value of x val trueX = fromArray( diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 9318fe928..0408bba63 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra @@ -18,7 +19,7 @@ fun main() { val randSeed = 100500L // work in context with linear operations - DoubleLinearOpsTensorAlgebra { + DoubleLinearOpsTensorAlgebra.invoke { // take coefficient vector from normal distribution val alpha = randNormal( intArrayOf(5), From e2c7751c7eb146641cec0bba6e10e51e849e8371 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 30 Apr 2021 19:45:31 +0300 Subject: [PATCH 154/211] refactor linops --- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index ab73b25b1..700fafbeb 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -53,14 +53,15 @@ public object DoubleLinearOpsTensorAlgebra : val lTensor = luTensor.zeroesLike() val uTensor = luTensor.zeroesLike() - for ((pairLU, lu) in lTensor.matrixSequence().zip(uTensor.matrixSequence()) - .zip(luTensor.tensor.matrixSequence())) { - val (l, u) = pairLU - luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) - } + lTensor.matrixSequence() + .zip(uTensor.matrixSequence()) + .zip(luTensor.tensor.matrixSequence()) + .forEach { (pairLU, lu) -> + val (l, u) = pairLU + luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) + } return Triple(pTensor, lTensor, uTensor) - } public fun TensorStructure.cholesky(epsilon: Double): DoubleTensor { @@ -82,11 +83,13 @@ public object DoubleLinearOpsTensorAlgebra : checkSquareMatrix(shape) val qTensor = zeroesLike() val rTensor = zeroesLike() - val seq = tensor.matrixSequence().zip((qTensor.matrixSequence().zip(rTensor.matrixSequence()))) - for ((matrix, qr) in seq) { + tensor.matrixSequence() + .zip((qTensor.matrixSequence() + .zip(rTensor.matrixSequence()))).forEach { (matrix, qr) -> val (q, r) = qr qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) } + return qTensor to rTensor } @@ -97,20 +100,24 @@ public object DoubleLinearOpsTensorAlgebra : val size = tensor.linearStructure.dim val commonShape = tensor.shape.sliceArray(0 until size - 2) val (n, m) = tensor.shape.sliceArray(size - 2 until size) - val resU = zeros(commonShape + intArrayOf(min(n, m), n)) - val resS = zeros(commonShape + intArrayOf(min(n, m))) - val resV = zeros(commonShape + intArrayOf(min(n, m), m)) + val uTensor = zeros(commonShape + intArrayOf(min(n, m), n)) + val sTensor = zeros(commonShape + intArrayOf(min(n, m))) + val vTensor = zeros(commonShape + intArrayOf(min(n, m), m)) - for ((matrix, USV) in tensor.matrixSequence() - .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) { - val matrixSize = matrix.shape.reduce { acc, i -> acc * i } - val curMatrix = DoubleTensor( - matrix.shape, - matrix.mutableBuffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize).toDoubleArray() - ) - svdHelper(curMatrix, USV, m, n, epsilon) - } - return Triple(resU.transpose(), resS, resV.transpose()) + tensor.matrixSequence() + .zip(uTensor.matrixSequence() + .zip(sTensor.vectorSequence() + .zip(vTensor.matrixSequence()))).forEach { (matrix, USV) -> + val matrixSize = matrix.shape.reduce { acc, i -> acc * i } + val curMatrix = DoubleTensor( + matrix.shape, + matrix.mutableBuffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize) + .toDoubleArray() + ) + svdHelper(curMatrix, USV, m, n, epsilon) + } + + return Triple(uTensor.transpose(), sTensor, vTensor.transpose()) } override fun TensorStructure.symEig(): Pair = @@ -127,7 +134,7 @@ public object DoubleLinearOpsTensorAlgebra : cleanSymHelper(matrix.as2D(), n) val eig = (utv dot s.view(shp)).view(s.shape) - return Pair(eig, v) + return eig to v } public fun TensorStructure.detLU(epsilon: Double = 1e-9): DoubleTensor { From f0cdb9b6571774bd861288f059abaf0571c232bf Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 30 Apr 2021 20:07:59 +0300 Subject: [PATCH 155/211] refactor utils and remove inline --- .../kmath/tensors/core/broadcastUtils.kt | 77 +++++++++---------- .../kscience/kmath/tensors/core/checks.kt | 18 ++--- .../kscience/kmath/tensors/core/linUtils.kt | 41 +++++----- .../kscience/kmath/tensors/core/utils.kt | 45 ++++++----- .../core/TestDoubleLinearOpsAlgebra.kt | 2 +- 5 files changed, 94 insertions(+), 89 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt index 2d4d6f0f7..58d8654af 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.tensors.core import kotlin.math.max -internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) { +internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) { for (linearIndex in 0 until linearSize) { val totalMultiIndex = resTensor.linearStructure.index(linearIndex) val curMultiIndex = tensor.shape.copyOf() @@ -23,7 +23,7 @@ internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: Doub } } -internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { +internal fun broadcastShapes(vararg shapes: IntArray): IntArray { var totalDim = 0 for (shape in shapes) { totalDim = max(totalDim, shape.size) @@ -51,7 +51,7 @@ internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { return totalShape } -internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor { +internal fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor { if (tensor.shape.size > newShape.size) { throw RuntimeException("Tensor is not compatible with the new shape") } @@ -71,7 +71,7 @@ internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): Doubl return resTensor } -internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List { +internal fun broadcastTensors(vararg tensors: DoubleTensor): List { val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) val n = totalShape.reduce { acc, i -> acc * i } @@ -85,7 +85,7 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List { +internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List { val onlyTwoDims = tensors.asSequence().onEach { require(it.shape.size >= 2) { throw RuntimeException("Tensors must have at least 2 dimensions") @@ -99,46 +99,45 @@ internal inline fun broadcastOuterTensors(vararg tensors: DoubleTensor): List acc * i } - val res = ArrayList(0) - for (tensor in tensors) { - val matrixShape = tensor.shape.sliceArray(tensor.shape.size - 2 until tensor.shape.size).copyOf() - val matrixSize = matrixShape[0] * matrixShape[1] - val matrix = DoubleTensor(matrixShape, DoubleArray(matrixSize)) + return buildList { + for (tensor in tensors) { + val matrixShape = tensor.shape.sliceArray(tensor.shape.size - 2 until tensor.shape.size).copyOf() + val matrixSize = matrixShape[0] * matrixShape[1] + val matrix = DoubleTensor(matrixShape, DoubleArray(matrixSize)) - val outerTensor = DoubleTensor(totalShape, DoubleArray(n)) - val resTensor = DoubleTensor(totalShape + matrixShape, DoubleArray(n * matrixSize)) + val outerTensor = DoubleTensor(totalShape, DoubleArray(n)) + val resTensor = DoubleTensor(totalShape + matrixShape, DoubleArray(n * matrixSize)) - for (linearIndex in 0 until n) { - val totalMultiIndex = outerTensor.linearStructure.index(linearIndex) - var curMultiIndex = tensor.shape.sliceArray(0..tensor.shape.size - 3).copyOf() - curMultiIndex = IntArray(totalMultiIndex.size - curMultiIndex.size) { 1 } + curMultiIndex + for (linearIndex in 0 until n) { + val totalMultiIndex = outerTensor.linearStructure.index(linearIndex) + var curMultiIndex = tensor.shape.sliceArray(0..tensor.shape.size - 3).copyOf() + curMultiIndex = IntArray(totalMultiIndex.size - curMultiIndex.size) { 1 } + curMultiIndex - val newTensor = DoubleTensor(curMultiIndex + matrixShape, tensor.mutableBuffer.array()) + val newTensor = DoubleTensor(curMultiIndex + matrixShape, tensor.mutableBuffer.array()) - for (i in curMultiIndex.indices) { - if (curMultiIndex[i] != 1) { - curMultiIndex[i] = totalMultiIndex[i] - } else { - curMultiIndex[i] = 0 + for (i in curMultiIndex.indices) { + if (curMultiIndex[i] != 1) { + curMultiIndex[i] = totalMultiIndex[i] + } else { + curMultiIndex[i] = 0 + } + } + + for (i in 0 until matrixSize) { + val curLinearIndex = newTensor.linearStructure.offset( + curMultiIndex + + matrix.linearStructure.index(i) + ) + val newLinearIndex = resTensor.linearStructure.offset( + totalMultiIndex + + matrix.linearStructure.index(i) + ) + + resTensor.mutableBuffer.array()[resTensor.bufferStart + newLinearIndex] = + newTensor.mutableBuffer.array()[newTensor.bufferStart + curLinearIndex] } } - - for (i in 0 until matrixSize) { - val curLinearIndex = newTensor.linearStructure.offset( - curMultiIndex + - matrix.linearStructure.index(i) - ) - val newLinearIndex = resTensor.linearStructure.offset( - totalMultiIndex + - matrix.linearStructure.index(i) - ) - - resTensor.mutableBuffer.array()[resTensor.bufferStart + newLinearIndex] = - newTensor.mutableBuffer.array()[newTensor.bufferStart + curLinearIndex] - } + add(resTensor) } - res += resTensor } - - return res } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index fd5c8413d..fd98be8b2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -5,38 +5,38 @@ import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra -internal inline fun checkEmptyShape(shape: IntArray): Unit = +internal fun checkEmptyShape(shape: IntArray): Unit = check(shape.isNotEmpty()) { "Illegal empty shape provided" } -internal inline fun checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = +internal fun checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = check(buffer.isNotEmpty()) { "Illegal empty buffer provided" } -internal inline fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = +internal fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = check(buffer.size == shape.reduce(Int::times)) { "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" } -internal inline fun checkShapesCompatible(a: TensorStructure, b: TensorStructure): Unit = +internal fun checkShapesCompatible(a: TensorStructure, b: TensorStructure): Unit = check(a.shape contentEquals b.shape) { "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " } -internal inline fun checkTranspose(dim: Int, i: Int, j: Int): Unit = +internal fun checkTranspose(dim: Int, i: Int, j: Int): Unit = check((i < dim) and (j < dim)) { "Cannot transpose $i to $j for a tensor of dim $dim" } -internal inline fun checkView(a: TensorStructure, shape: IntArray): Unit = +internal fun checkView(a: TensorStructure, shape: IntArray): Unit = check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) -internal inline fun checkSquareMatrix(shape: IntArray): Unit { +internal fun checkSquareMatrix(shape: IntArray): Unit { val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n instead" @@ -46,14 +46,14 @@ internal inline fun checkSquareMatrix(shape: IntArray): Unit { } } -internal inline fun DoubleTensorAlgebra.checkSymmetric( +internal fun DoubleTensorAlgebra.checkSymmetric( tensor: TensorStructure, epsilon: Double = 1e-6 ): Unit = check(tensor.eq(tensor.transpose(), epsilon)) { "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } -internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( +internal fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( tensor: DoubleTensor, epsilon: Double = 1e-6 ): Unit { checkSymmetric(tensor, epsilon) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt index 776a5e4d5..a152b3a17 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt @@ -13,7 +13,7 @@ import kotlin.math.sign import kotlin.math.sqrt -internal inline fun BufferedTensor.vectorSequence(): Sequence> = sequence { +internal fun BufferedTensor.vectorSequence(): Sequence> = sequence { val n = shape.size val vectorOffset = shape[n - 1] val vectorShape = intArrayOf(shape.last()) @@ -23,9 +23,9 @@ internal inline fun BufferedTensor.vectorSequence(): Sequence BufferedTensor.matrixSequence(): Sequence> = sequence { - check(shape.size >= 2) { "todo" } +internal fun BufferedTensor.matrixSequence(): Sequence> = sequence { val n = shape.size + check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } val matrixOffset = shape[n - 1] * shape[n - 2] val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) for (offset in 0 until numElements step matrixOffset) { @@ -46,8 +46,7 @@ internal inline fun BufferedTensor.forEachMatrix(matrixAction: (BufferedT } } - -internal inline fun dotHelper( +internal fun dotHelper( a: MutableStructure2D, b: MutableStructure2D, res: MutableStructure2D, @@ -64,10 +63,11 @@ internal inline fun dotHelper( } } -internal inline fun luHelper( +internal fun luHelper( lu: MutableStructure2D, pivots: MutableStructure1D, - epsilon: Double): Boolean { + epsilon: Double +): Boolean { val m = lu.rowNum @@ -114,7 +114,7 @@ internal inline fun luHelper( return false } -internal inline fun BufferedTensor.setUpPivots(): IntTensor { +internal fun BufferedTensor.setUpPivots(): IntTensor { val n = this.shape.size val m = this.shape.last() val pivotsShape = IntArray(n - 1) { i -> this.shape[i] } @@ -126,22 +126,23 @@ internal inline fun BufferedTensor.setUpPivots(): IntTensor { ) } -internal inline fun DoubleLinearOpsTensorAlgebra.computeLU( +internal fun DoubleLinearOpsTensorAlgebra.computeLU( tensor: DoubleTensor, - epsilon: Double): Pair? { + epsilon: Double +): Pair? { checkSquareMatrix(tensor.shape) val luTensor = tensor.copy() val pivotsTensor = tensor.setUpPivots() for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) - if(luHelper(lu.as2D(), pivots.as1D(), epsilon)) + if (luHelper(lu.as2D(), pivots.as1D(), epsilon)) return null return Pair(luTensor, pivotsTensor) } -internal inline fun pivInit( +internal fun pivInit( p: MutableStructure2D, pivot: MutableStructure1D, n: Int @@ -151,7 +152,7 @@ internal inline fun pivInit( } } -internal inline fun luPivotHelper( +internal fun luPivotHelper( l: MutableStructure2D, u: MutableStructure2D, lu: MutableStructure2D, @@ -172,7 +173,7 @@ internal inline fun luPivotHelper( } } -internal inline fun choleskyHelper( +internal fun choleskyHelper( a: MutableStructure2D, l: MutableStructure2D, n: Int @@ -193,7 +194,7 @@ internal inline fun choleskyHelper( } } -internal inline fun luMatrixDet(lu: MutableStructure2D, pivots: MutableStructure1D): Double { +internal fun luMatrixDet(lu: MutableStructure2D, pivots: MutableStructure1D): Double { if (lu[0, 0] == 0.0) { return 0.0 } @@ -202,7 +203,7 @@ internal inline fun luMatrixDet(lu: MutableStructure2D, pivots: MutableS return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } } -internal inline fun luMatrixInv( +internal fun luMatrixInv( lu: MutableStructure2D, pivots: MutableStructure1D, invMatrix: MutableStructure2D @@ -229,7 +230,7 @@ internal inline fun luMatrixInv( } } -internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper( +internal fun DoubleLinearOpsTensorAlgebra.qrHelper( matrix: DoubleTensor, q: DoubleTensor, r: MutableStructure2D @@ -259,7 +260,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper( } } -internal inline fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { +internal fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { val (n, m) = a.shape var v: DoubleTensor val b: DoubleTensor @@ -283,7 +284,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: } } -internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( +internal fun DoubleLinearOpsTensorAlgebra.svdHelper( matrix: DoubleTensor, USV: Pair, Pair, BufferedTensor>>, m: Int, n: Int, epsilon: Double @@ -335,7 +336,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( } } -internal inline fun cleanSymHelper(matrix: MutableStructure2D, n: Int) { +internal fun cleanSymHelper(matrix: MutableStructure2D, n: Int) { for (i in 0 until n) for (j in 0 until n) { if (i == j) { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index cb23dbdd6..58d280307 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -23,19 +23,19 @@ internal fun Buffer.array(): DoubleArray = when (this) { else -> this.toDoubleArray() } -internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { +internal fun getRandomNormals(n: Int, seed: Long): DoubleArray { val distribution = GaussianSampler(0.0, 1.0) val generator = RandomGenerator.default(seed) return distribution.sample(generator).nextBufferBlocking(n).toDoubleArray() } -internal inline fun getRandomUnitVector(n: Int, seed: Long): DoubleArray { +internal fun getRandomUnitVector(n: Int, seed: Long): DoubleArray { val unnorm = getRandomNormals(n, seed) val norm = sqrt(unnorm.map { it * it }.sum()) return unnorm.map { it / norm }.toDoubleArray() } -internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { +internal fun minusIndexFrom(n: Int, i: Int): Int = if (i >= 0) i else { val ii = n + i check(ii >= 0) { "Out of bound index $i for tensor of dim $n" @@ -43,27 +43,28 @@ internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { ii } -internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.dimension, i) +internal fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.dimension, i) -internal inline fun format(value: Double, digits: Int = 4): String { +internal fun format(value: Double, digits: Int = 4): String { val ten = 10.0 - val approxOrder = if(value == 0.0) 0 else ceil(log10(abs(value))).toInt() - val order = if( + val approxOrder = if (value == 0.0) 0 else ceil(log10(abs(value))).toInt() + val order = if ( ((value % ten) == 0.0) or (value == 1.0) or - ((1/value) % ten == 0.0)) approxOrder else approxOrder - 1 + ((1 / value) % ten == 0.0) + ) approxOrder else approxOrder - 1 val lead = value / ten.pow(order) - val leadDisplay = round(lead*ten.pow(digits)) / ten.pow(digits) - val orderDisplay = if(order == 0) "" else if(order > 0) "E+$order" else "E$order" + val leadDisplay = round(lead * ten.pow(digits)) / ten.pow(digits) + val orderDisplay = if (order == 0) "" else if (order > 0) "E+$order" else "E$order" val valueDisplay = "$leadDisplay$orderDisplay" - val res = if(value < 0.0) valueDisplay else " $valueDisplay" + val res = if (value < 0.0) valueDisplay else " $valueDisplay" val fLength = digits + 6 val endSpace = " ".repeat(fLength - res.length) return "$res$endSpace" } -internal inline fun DoubleTensor.toPrettyString(): String = buildString { +internal fun DoubleTensor.toPrettyString(): String = buildString { var offset = 0 val shape = this@toPrettyString.shape val linearStructure = this@toPrettyString.linearStructure @@ -72,32 +73,36 @@ internal inline fun DoubleTensor.toPrettyString(): String = buildString { append(initString) var charOffset = 3 for (vector in vectorSequence()) { - append(" ".repeat(charOffset)) + repeat(charOffset) { append(' ') } val index = linearStructure.index(offset) for (ind in index.reversed()) { if (ind != 0) { break } - append("[") + append('[') charOffset += 1 } val values = vector.as1D().toMutableList().map(::format) - append(values.joinToString(", ")) - append("]") + values.joinTo(this, separator = ", ") + + append(']') charOffset -= 1 - for ((ind, maxInd) in index.reversed().zip(shape.reversed()).drop(1)){ + + index.reversed().zip(shape.reversed()).drop(1).forEach { (ind, maxInd) -> if (ind != maxInd - 1) { - break + return@forEach } - append("]") - charOffset -=1 + append(']') + charOffset -= 1 } + offset += vectorSize if (this@toPrettyString.numElements == offset) { break } + append(",\n") } append("\n)") 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 1148c0aad..2282d7fcb 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 @@ -182,7 +182,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } -private inline fun DoubleLinearOpsTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10): Unit { +private fun DoubleLinearOpsTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10): Unit { val svd = tensor.svd() val tensorSVD = svd.first From 8a039326d40fe4e840bed09170607c457a89e5a3 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 19:47:05 +0100 Subject: [PATCH 156/211] Minor corrections --- kmath-core/api/kmath-core.api | 3 +-- .../kotlin/space/kscience/kmath/nd/StructureND.kt | 10 ++++------ .../tensors/core/algebras/TensorLinearStructure.kt | 5 ----- .../kscience/kmath/tensors/core/broadcastUtils.kt | 13 ++++++------- .../kmath/tensors/core/TestDoubleTensorAlgebra.kt | 1 - 5 files changed, 11 insertions(+), 21 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 687de9cc8..261aa1e24 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -792,7 +792,6 @@ public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath public fun getStrides ()[I public fun hashCode ()I public fun index (I)[I - public fun offset ([I)I } public final class space/kscience/kmath/nd/DefaultStrides$Companion { @@ -934,7 +933,7 @@ public abstract interface class space/kscience/kmath/nd/Strides { public abstract fun getStrides ()[I public abstract fun index (I)[I public fun indices ()Lkotlin/sequences/Sequence; - public abstract fun offset ([I)I + public fun offset ([I)I } public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/StructureND, space/kscience/kmath/structures/Buffer { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index 65c233012..a3331d71a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -189,7 +189,10 @@ public interface Strides { /** * Get linear index from multidimensional index */ - public fun offset(index: IntArray): Int + public fun offset(index: IntArray): Int = index.mapIndexed { i, value -> + if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${this.shape[i]})") + value * strides[i] + }.sum() /** * Get multidimensional from linear @@ -233,11 +236,6 @@ public class DefaultStrides private constructor(override val shape: IntArray) : }.toList().toIntArray() } - override fun offset(index: IntArray): Int = index.mapIndexed { i, value -> - if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${this.shape[i]})") - value * strides[i] - }.sum() - override fun index(offset: Int): IntArray { val res = IntArray(shape.size) var current = offset diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index 8e83dafd6..08aab5175 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -68,8 +68,6 @@ public class TensorLinearStructure(override val shape: IntArray) : Strides override val strides: IntArray get() = stridesFromShape(shape) - override fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides) - override fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) @@ -82,7 +80,4 @@ public class TensorLinearStructure(override val shape: IntArray) : Strides public val dim: Int get() = shape.size - override fun indices(): Sequence = (0 until linearSize).asSequence().map { - index(it) - } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt index 58d8654af..e883b7861 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt @@ -75,14 +75,13 @@ internal fun broadcastTensors(vararg tensors: DoubleTensor): List val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) val n = totalShape.reduce { acc, i -> acc * i } - val res = ArrayList(0) - for (tensor in tensors) { - val resTensor = DoubleTensor(totalShape, DoubleArray(n)) - multiIndexBroadCasting(tensor, resTensor, n) - res.add(resTensor) + return buildList { + for (tensor in tensors) { + val resTensor = DoubleTensor(totalShape, DoubleArray(n)) + multiIndexBroadCasting(tensor, resTensor, n) + add(resTensor) + } } - - return res } internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List { diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 34fe5d5f1..a0efa4573 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -170,7 +170,6 @@ internal class TestDoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) - val tensor4 = fromArray(intArrayOf(6, 1), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) assertTrue(tensor1 eq tensor1) assertTrue(tensor1 eq tensor2) From 74773686b432eac9e7d7804ffabf38eb1dbf1dca Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 19:49:43 +0100 Subject: [PATCH 157/211] toDoubleTensor and toIntTensor renaming --- .../space/kscience/kmath/tensors/core/BufferedTensor.kt | 4 ++-- .../space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 21030bbc7..4e286b489 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 @@ -77,5 +77,5 @@ internal val TensorStructure.tensor: IntTensor else -> this.toBufferedTensor().asTensor() } -public fun TensorStructure.toTypedTensor(): DoubleTensor = this.tensor -public fun TensorStructure.toTypedTensor(): IntTensor = this.tensor \ No newline at end of file +public fun TensorStructure.toDoubleTensor(): DoubleTensor = this.tensor +public fun TensorStructure.toIntTensor(): IntTensor = this.tensor \ No newline at end of file diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index eca54f68b..333a7bdec 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -67,8 +67,8 @@ internal class TestDoubleTensor { val bufferedTensorArray = ndArray.toBufferedTensor() // strides are flipped so data copied val tensorArray = bufferedTensorArray.asTensor() // data not contiguous so copied again - val tensorArrayPublic = ndArray.toTypedTensor() // public API, data copied twice - val sharedTensorArray = tensorArrayPublic.toTypedTensor() // no data copied by matching type + val tensorArrayPublic = ndArray.toDoubleTensor() // public API, data copied twice + val sharedTensorArray = tensorArrayPublic.toDoubleTensor() // no data copied by matching type assertTrue(tensorArray.mutableBuffer.array() contentEquals sharedTensorArray.mutableBuffer.array()) From 1b6bd67b903f761bf009a0677e422f637dd775d4 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 21:11:01 +0100 Subject: [PATCH 158/211] No virtual mutable buffers --- kmath-core/api/kmath-core.api | 9 --------- .../space/kscience/kmath/nd/Structure2D.kt | 6 +++--- .../space/kscience/kmath/structures/Buffer.kt | 18 ------------------ 3 files changed, 3 insertions(+), 30 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 261aa1e24..865ad2f6d 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -1881,15 +1881,6 @@ public final class space/kscience/kmath/structures/MutableBuffer$Companion { public final fun short-1yRgbGw (ILkotlin/jvm/functions/Function1;)[S } -public final class space/kscience/kmath/structures/MutableBufferFromGenerator : space/kscience/kmath/structures/MutableBuffer { - public fun (ILkotlin/jvm/functions/Function1;)V - public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; - public fun get (I)Ljava/lang/Object; - public fun getSize ()I - public fun iterator ()Ljava/util/Iterator; - public fun set (ILjava/lang/Object;)V -} - public final class space/kscience/kmath/structures/MutableListBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/MutableListBuffer; public static fun constructor-impl (ILkotlin/jvm/functions/Function1;)Ljava/util/List; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index d987d8cf4..28ae07a3c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.VirtualBuffer -import space.kscience.kmath.structures.MutableBufferFromGenerator +import space.kscience.kmath.structures.MutableListBuffer import kotlin.jvm.JvmInline import kotlin.reflect.KClass @@ -81,13 +81,13 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { * The buffer of rows of this structure. It gets elements from the structure dynamically. */ override val rows: List> - get() = List(rowNum) { i -> MutableBuffer1DWrapper(MutableBufferFromGenerator(colNum) { j -> get(i, j) })} + get() = List(rowNum) { i -> MutableBuffer1DWrapper(MutableListBuffer(colNum) { j -> get(i, j) })} /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ override val columns: List> - get() = List(colNum) { j -> MutableBuffer1DWrapper(MutableBufferFromGenerator(rowNum) { i -> get(i, j) }) } + get() = List(colNum) { j -> MutableBuffer1DWrapper(MutableListBuffer(rowNum) { i -> get(i, j) }) } } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 19018ffb5..be5dfb359 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -292,24 +292,6 @@ public class VirtualBuffer(override val size: Int, private val generator: (In override operator fun iterator(): Iterator = (0 until size).asSequence().map(generator).iterator() } -public class MutableBufferFromGenerator(override val size: Int, private val generator: (Int) -> T) : MutableBuffer { - - private val bufferHolder: MutableListBuffer = (0 until size).map(generator).toMutableList().asMutableBuffer() - - override operator fun get(index: Int): T { - if (index < 0 || index >= size) throw IndexOutOfBoundsException("Expected index from 0 to ${size - 1}, but found $index") - return bufferHolder[index] - } - - override operator fun iterator(): Iterator = bufferHolder.iterator() - - override fun set(index: Int, value: T) { - bufferHolder[index] = value - } - - override fun copy(): MutableBuffer = bufferHolder.copy() -} - /** * Convert this buffer to read-only buffer. */ From b7cac3a015d235d81d02d3bb4b8834dda2b48b95 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sat, 1 May 2021 13:32:50 +0300 Subject: [PATCH 159/211] fix sequences + array casting --- .../kmath/tensors/core/BufferedTensor.kt | 38 ++++++++++++++++++- .../kscience/kmath/tensors/core/linUtils.kt | 4 +- 2 files changed, 39 insertions(+), 3 deletions(-) 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 4e286b489..867b4fb7a 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 @@ -49,6 +49,7 @@ public class DoubleTensor internal constructor( 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) @@ -78,4 +79,39 @@ internal val TensorStructure.tensor: IntTensor } public fun TensorStructure.toDoubleTensor(): DoubleTensor = this.tensor -public fun TensorStructure.toIntTensor(): IntTensor = this.tensor \ No newline at end of file +public fun TensorStructure.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 tensor.mutableBuffer.array().drop(bufferStart).take(numElements).toDoubleArray() +} + +public fun IntTensor.toIntArray(): IntArray { + return tensor.mutableBuffer.array().drop(bufferStart).take(numElements).toIntArray() +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt index a152b3a17..e54cc4d26 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt @@ -18,7 +18,7 @@ internal fun BufferedTensor.vectorSequence(): Sequence> val vectorOffset = shape[n - 1] val vectorShape = intArrayOf(shape.last()) for (offset in 0 until numElements step vectorOffset) { - val vector = BufferedTensor(vectorShape, mutableBuffer, offset) + val vector = BufferedTensor(vectorShape, mutableBuffer, bufferStart + offset) yield(vector) } } @@ -29,7 +29,7 @@ internal fun BufferedTensor.matrixSequence(): Sequence> val matrixOffset = shape[n - 1] * shape[n - 2] val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) for (offset in 0 until numElements step matrixOffset) { - val matrix = BufferedTensor(matrixShape, mutableBuffer, offset) + val matrix = BufferedTensor(matrixShape, mutableBuffer, bufferStart + offset) yield(matrix) } } From fe81dea243860ad063d5490d13225182ddbfaedc Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sat, 1 May 2021 14:22:05 +0300 Subject: [PATCH 160/211] stack --- .../core/algebras/DoubleTensorAlgebra.kt | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index f428b9d2e..c6fb301b5 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -382,7 +382,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return false } 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 } } @@ -395,4 +399,20 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun TensorStructure.randNormalLike(seed: Long = 0): DoubleTensor = DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) + // stack tensors by axis 0 + public fun stack(tensors: List): 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.rowsByIndices(indices: IntArray): DoubleTensor { + return stack(indices.map { this[it] }) + } } From 83c7ec8c6b7cf52cd7a890a4e1551140327ec6dd Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 1 May 2021 00:13:32 +0700 Subject: [PATCH 161/211] Deprecate AlgebraElements.kt --- kmath-core/api/kmath-core.api | 7 ------- .../kscience/kmath/operations/AlgebraElements.kt | 14 +++++++++++++- .../kmath/operations/OptionalOperations.kt | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 6b300123c..a73e4ed54 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -991,14 +991,7 @@ public abstract interface class space/kscience/kmath/operations/Algebra { public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } -public abstract interface class space/kscience/kmath/operations/AlgebraElement { - public abstract fun getContext ()Lspace/kscience/kmath/operations/Algebra; -} - public final class space/kscience/kmath/operations/AlgebraElementsKt { - public static final fun div (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement; - public static final fun plus (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement; - public static final fun times (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement; } public final class space/kscience/kmath/operations/AlgebraExtensionsKt { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt index d7c87f213..cc058d3fc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt @@ -13,6 +13,8 @@ import space.kscience.kmath.misc.UnstableKMathAPI * @param C the type of mathematical context for this element. * @param T the type wrapped by this wrapper. */ +@UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public interface AlgebraElement> { /** * The context this element belongs to. @@ -45,6 +47,7 @@ public interface AlgebraElement> { * @return the difference. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public operator fun , S : NumbersAddOperations> T.minus(b: T): T = context.add(this, context.run { -b }) @@ -55,6 +58,8 @@ public operator fun , S : NumbersAddOperations> T.mi * @param b the addend. * @return the sum. */ +@UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public operator fun , S : Ring> T.plus(b: T): T = context.add(this, b) @@ -71,6 +76,8 @@ public operator fun , S : Ring> T.plus(b: T): T = * @param b the multiplier. * @return the product. */ +@UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public operator fun , R : Ring> T.times(b: T): T = context.multiply(this, b) @@ -81,6 +88,8 @@ public operator fun , R : Ring> T.times(b: T): T = * @param b the divisor. * @return the quotient. */ +@UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public operator fun , F : Field> T.div(b: T): T = context.divide(this, b) @@ -93,6 +102,7 @@ public operator fun , F : Field> T.div(b: T): T = * @param S the type of space. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public interface GroupElement, S : Group> : AlgebraElement /** @@ -103,6 +113,7 @@ public interface GroupElement, S : Group> : AlgebraEle * @param R the type of ring. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public interface RingElement, R : Ring> : GroupElement /** @@ -113,4 +124,5 @@ public interface RingElement, R : Ring> : GroupElement< * @param F the type of field. */ @UnstableKMathAPI -public interface FieldElement, F : Field> : RingElement \ No newline at end of file +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") +public interface FieldElement, F : Field> : RingElement diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt index 8e3e6c777..979e65396 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt @@ -80,36 +80,42 @@ public interface TrigonometricOperations : Algebra { * Computes the sine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> sin(arg: T): T = arg.context.sin(arg) /** * Computes the cosine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> cos(arg: T): T = arg.context.cos(arg) /** * Computes the tangent of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> tan(arg: T): T = arg.context.tan(arg) /** * Computes the inverse sine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> asin(arg: T): T = arg.context.asin(arg) /** * Computes the inverse cosine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> acos(arg: T): T = arg.context.acos(arg) /** * Computes the inverse tangent of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> atan(arg: T): T = arg.context.atan(arg) /** @@ -154,18 +160,21 @@ public interface PowerOperations : Algebra { * @return the base raised to the power. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public infix fun >> T.pow(power: Double): T = context.power(this, power) /** * Computes the square root of the value [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> sqrt(arg: T): T = arg pow 0.5 /** * Computes the square of the value [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> sqr(arg: T): T = arg pow 2.0 /** @@ -261,12 +270,14 @@ public interface ExponentialOperations : Algebra { * The identifier of exponential function. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> exp(arg: T): T = arg.context.exp(arg) /** * The identifier of natural logarithm. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> ln(arg: T): T = arg.context.ln(arg) @@ -280,30 +291,35 @@ public fun >> sinh(arg: T): T * Computes the hyperbolic cosine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> cosh(arg: T): T = arg.context.cosh(arg) /** * Computes the hyperbolic tangent of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> tanh(arg: T): T = arg.context.tanh(arg) /** * Computes the inverse hyperbolic sine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> asinh(arg: T): T = arg.context.asinh(arg) /** * Computes the inverse hyperbolic cosine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> acosh(arg: T): T = arg.context.acosh(arg) /** * Computes the inverse hyperbolic tangent of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> atanh(arg: T): T = arg.context.atanh(arg) /** From bfba653904793b74be89ea9f46461ad8c20a2b8e Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sat, 1 May 2021 17:47:12 +0300 Subject: [PATCH 162/211] refactor --- .../kscience/kmath/tensors/OLSWithSVD.kt | 6 ++--- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 8 ++++--- .../core/algebras/DoubleTensorAlgebra.kt | 18 +++++++------- .../kmath/tensors/core/broadcastUtils.kt | 24 +++++++++---------- .../kscience/kmath/tensors/core/utils.kt | 3 +-- .../core/TestDoubleLinearOpsAlgebra.kt | 6 ++--- 6 files changed, 32 insertions(+), 33 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 0408bba63..095905f05 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -21,7 +21,7 @@ fun main() { // work in context with linear operations DoubleLinearOpsTensorAlgebra.invoke { // take coefficient vector from normal distribution - val alpha = randNormal( + val alpha = randomNormal( intArrayOf(5), randSeed ) + fromArray( @@ -32,14 +32,14 @@ fun main() { println("Real alpha:\n$alpha") // also take sample of size 20 from normal distribution for x - val x = randNormal( + val x = randomNormal( intArrayOf(20, 5), randSeed ) // calculate y and add gaussian noise (N(0, 0.05)) val y = x dot alpha - y += y.randNormalLike(randSeed) * 0.05 + y += y.randomNormalLike(randSeed) * 0.05 // now restore the coefficient vector with OSL estimator with SVD val (u, singValues, v) = x.svd() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 700fafbeb..dd5ad5a61 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -31,7 +31,7 @@ public object DoubleLinearOpsTensorAlgebra : public fun TensorStructure.luFactor(epsilon: Double): Pair = computeLU(tensor, epsilon) - ?: throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon") + ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") public fun TensorStructure.luFactor(): Pair = luFactor(1e-9) @@ -47,8 +47,10 @@ public object DoubleLinearOpsTensorAlgebra : val n = luTensor.shape.last() val pTensor = luTensor.zeroesLike() - for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.tensor.vectorSequence())) - pivInit(p.as2D(), pivot.as1D(), n) + pTensor + .matrixSequence() + .zip(pivotsTensor.tensor.vectorSequence()) + .forEach { (p, pivot) -> pivInit(p.as2D(), pivot.as1D(), n) } val lTensor = luTensor.zeroesLike() val uTensor = luTensor.zeroesLike() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index c6fb301b5..d3e8bf175 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -284,7 +284,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { val m1 = newThis.shape[newThis.shape.size - 1] val m2 = newOther.shape[newOther.shape.size - 2] val n = newOther.shape[newOther.shape.size - 1] - if (m1 != m2) { + check (m1 == m2) { throw RuntimeException("Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)") } @@ -315,11 +315,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { val d1 = minusIndexFrom(n + 1, dim1) val d2 = minusIndexFrom(n + 1, dim2) - if (d1 == d2) { - throw RuntimeException("Diagonal dimensions cannot be identical $d1, $d2") + check(d1 != d2) { + "Diagonal dimensions cannot be identical $d1, $d2" } - if (d1 > n || d2 > n) { - throw RuntimeException("Dimension out of range") + check(d1 <= n && d2 <= n) { + "Dimension out of range" } var lessDim = d1 @@ -366,8 +366,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { ) } - public fun TensorStructure.eq(other: TensorStructure, delta: Double): Boolean { - return tensor.eq(other) { x, y -> abs(x - y) < delta } + public fun TensorStructure.eq(other: TensorStructure, epsilon: Double): Boolean { + return tensor.eq(other) { x, y -> abs(x - y) < epsilon } } public infix fun TensorStructure.eq(other: TensorStructure): Boolean = tensor.eq(other, 1e-5) @@ -393,10 +393,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return true } - public fun randNormal(shape: IntArray, seed: Long = 0): DoubleTensor = + public fun randomNormal(shape: IntArray, seed: Long = 0): DoubleTensor = DoubleTensor(shape, getRandomNormals(shape.reduce(Int::times), seed)) - public fun TensorStructure.randNormalLike(seed: Long = 0): DoubleTensor = + public fun TensorStructure.randomNormalLike(seed: Long = 0): DoubleTensor = DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) // stack tensors by axis 0 diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt index e883b7861..dfac054b5 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt @@ -42,8 +42,8 @@ internal fun broadcastShapes(vararg shapes: IntArray): IntArray { for (i in shape.indices) { val curDim = shape[i] val offset = totalDim - shape.size - if (curDim != 1 && totalShape[i + offset] != curDim) { - throw RuntimeException("Shapes are not compatible and cannot be broadcast") + check(curDim == 1 || totalShape[i + offset] == curDim) { + "Shapes are not compatible and cannot be broadcast" } } } @@ -52,8 +52,8 @@ internal fun broadcastShapes(vararg shapes: IntArray): IntArray { } internal fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor { - if (tensor.shape.size > newShape.size) { - throw RuntimeException("Tensor is not compatible with the new shape") + require(tensor.shape.size <= newShape.size) { + "Tensor is not compatible with the new shape" } val n = newShape.reduce { acc, i -> acc * i } @@ -62,8 +62,8 @@ internal fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor for (i in tensor.shape.indices) { val curDim = tensor.shape[i] val offset = newShape.size - tensor.shape.size - if (curDim != 1 && newShape[i + offset] != curDim) { - throw RuntimeException("Tensor is not compatible with the new shape and cannot be broadcast") + check(curDim == 1 || newShape[i + offset] == curDim) { + "Tensor is not compatible with the new shape and cannot be broadcast" } } @@ -75,19 +75,17 @@ internal fun broadcastTensors(vararg tensors: DoubleTensor): List val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) val n = totalShape.reduce { acc, i -> acc * i } - return buildList { - for (tensor in tensors) { - val resTensor = DoubleTensor(totalShape, DoubleArray(n)) - multiIndexBroadCasting(tensor, resTensor, n) - add(resTensor) - } + return tensors.map { tensor -> + val resTensor = DoubleTensor(totalShape, DoubleArray(n)) + multiIndexBroadCasting(tensor, resTensor, n) + resTensor } } internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List { val onlyTwoDims = tensors.asSequence().onEach { require(it.shape.size >= 2) { - throw RuntimeException("Tensors must have at least 2 dimensions") + "Tensors must have at least 2 dimensions" } }.any { it.shape.size != 2 } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 58d280307..88b9c6c5c 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -69,8 +69,7 @@ internal fun DoubleTensor.toPrettyString(): String = buildString { val shape = this@toPrettyString.shape val linearStructure = this@toPrettyString.linearStructure val vectorSize = shape.last() - val initString = "DoubleTensor(\n" - append(initString) + append("DoubleTensor(\n") var charOffset = 3 for (vector in vectorSequence()) { repeat(charOffset) { append(' ') } 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 2282d7fcb..6689e893a 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 @@ -135,7 +135,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testCholesky() = DoubleLinearOpsTensorAlgebra.invoke { - val tensor = randNormal(intArrayOf(2, 5, 5), 0) + val tensor = randomNormal(intArrayOf(2, 5, 5), 0) val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) ) @@ -163,7 +163,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra.invoke { - val tensor = randNormal(intArrayOf(2, 5, 3), 0) + val tensor = randomNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) assertTrue(tensor.eq(tensorSVD)) @@ -171,7 +171,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra.invoke { - val tensor = randNormal(shape = intArrayOf(2, 3, 3), 0) + val tensor = randomNormal(shape = intArrayOf(2, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) From ac6608b5b45ed7b59667216ec62b73380f60ef97 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sat, 1 May 2021 20:45:23 +0300 Subject: [PATCH 163/211] refactor --- .../tensors/LinearSystemSolvingWithLUP.kt | 2 +- .../kscience/kmath/tensors/OLSWithSVD.kt | 2 +- kmath-tensors/build.gradle.kts | 3 ++ .../kmath/tensors/core/BufferedTensor.kt | 8 +++- .../kscience/kmath/tensors/core/checks.kt | 23 ++++------ .../kscience/kmath/tensors/core/linUtils.kt | 12 ----- .../kscience/kmath/tensors/core/utils.kt | 45 +++++++++++-------- 7 files changed, 47 insertions(+), 48 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index a84224bcf..bd8233ccc 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -14,7 +14,7 @@ import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra fun main () { // work in context with linear operations - DoubleLinearOpsTensorAlgebra.invoke { + DoubleLinearOpsTensorAlgebra { // set true value of x val trueX = fromArray( diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 095905f05..435af35f6 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -19,7 +19,7 @@ fun main() { val randSeed = 100500L // work in context with linear operations - DoubleLinearOpsTensorAlgebra.invoke { + DoubleLinearOpsTensorAlgebra { // take coefficient vector from normal distribution val alpha = randomNormal( intArrayOf(5), diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts index af5116022..b7f24dc6a 100644 --- a/kmath-tensors/build.gradle.kts +++ b/kmath-tensors/build.gradle.kts @@ -3,6 +3,9 @@ plugins { } kotlin.sourceSets { + all { + languageSettings.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") + } commonMain { dependencies { api(project(":kmath-core")) 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 867b4fb7a..9541a97f9 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 @@ -109,9 +109,13 @@ public fun Array.toIntTensor(): IntTensor { } public fun DoubleTensor.toDoubleArray(): DoubleArray { - return tensor.mutableBuffer.array().drop(bufferStart).take(numElements).toDoubleArray() + return DoubleArray(numElements) { i -> + mutableBuffer[bufferStart + i] + } } public fun IntTensor.toIntArray(): IntArray { - return tensor.mutableBuffer.array().drop(bufferStart).take(numElements).toIntArray() + 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/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index fd98be8b2..b1c12ccde 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -5,38 +5,35 @@ import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra -internal fun checkEmptyShape(shape: IntArray): Unit = +internal fun checkEmptyShape(shape: IntArray) = check(shape.isNotEmpty()) { "Illegal empty shape provided" } -internal fun checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = +internal fun checkEmptyDoubleBuffer(buffer: DoubleArray) = check(buffer.isNotEmpty()) { "Illegal empty buffer provided" } -internal fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = +internal fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray) = check(buffer.size == shape.reduce(Int::times)) { "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" } - -internal fun checkShapesCompatible(a: TensorStructure, b: TensorStructure): Unit = +internal fun checkShapesCompatible(a: TensorStructure, b: TensorStructure) = check(a.shape contentEquals b.shape) { "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " } - -internal fun checkTranspose(dim: Int, i: Int, j: Int): Unit = +internal fun checkTranspose(dim: Int, i: Int, j: Int) = check((i < dim) and (j < dim)) { "Cannot transpose $i to $j for a tensor of dim $dim" } -internal fun checkView(a: TensorStructure, shape: IntArray): Unit = +internal fun checkView(a: TensorStructure, shape: IntArray) = check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) - -internal fun checkSquareMatrix(shape: IntArray): Unit { +internal fun checkSquareMatrix(shape: IntArray) { val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n instead" @@ -48,14 +45,12 @@ internal fun checkSquareMatrix(shape: IntArray): Unit { internal fun DoubleTensorAlgebra.checkSymmetric( tensor: TensorStructure, epsilon: Double = 1e-6 -): Unit = +) = check(tensor.eq(tensor.transpose(), epsilon)) { "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } -internal fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( - tensor: DoubleTensor, epsilon: Double = 1e-6 -): Unit { +internal fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { checkSymmetric(tensor, epsilon) for (mat in tensor.matrixSequence()) check(mat.asTensor().detLU().value() > 0.0) { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt index e54cc4d26..ba8b823c9 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt @@ -34,18 +34,6 @@ internal fun BufferedTensor.matrixSequence(): Sequence> } } -internal inline fun BufferedTensor.forEachVector(vectorAction: (BufferedTensor) -> Unit) { - for (vector in vectorSequence()) { - vectorAction(vector) - } -} - -internal inline fun BufferedTensor.forEachMatrix(matrixAction: (BufferedTensor) -> Unit) { - for (matrix in matrixSequence()) { - matrixAction(matrix) - } -} - internal fun dotHelper( a: MutableStructure2D, b: MutableStructure2D, diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 88b9c6c5c..0211342bb 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -14,7 +14,6 @@ internal fun Buffer.array(): IntArray = when (this) { else -> this.toIntArray() } - /** * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer] or copy the data. */ @@ -31,7 +30,7 @@ internal fun getRandomNormals(n: Int, seed: Long): DoubleArray { internal fun getRandomUnitVector(n: Int, seed: Long): DoubleArray { val unnorm = getRandomNormals(n, seed) - val norm = sqrt(unnorm.map { it * it }.sum()) + val norm = sqrt(unnorm.sumOf { it * it }) return unnorm.map { it / norm }.toDoubleArray() } @@ -45,23 +44,33 @@ internal fun minusIndexFrom(n: Int, i: Int): Int = if (i >= 0) i else { internal fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.dimension, i) -internal fun format(value: Double, digits: Int = 4): String { - val ten = 10.0 - val approxOrder = if (value == 0.0) 0 else ceil(log10(abs(value))).toInt() - val order = if ( - ((value % ten) == 0.0) or - (value == 1.0) or - ((1 / value) % ten == 0.0) - ) approxOrder else approxOrder - 1 - val lead = value / ten.pow(order) - val leadDisplay = round(lead * ten.pow(digits)) / ten.pow(digits) - val orderDisplay = if (order == 0) "" else if (order > 0) "E+$order" else "E$order" - val valueDisplay = "$leadDisplay$orderDisplay" - val res = if (value < 0.0) valueDisplay else " $valueDisplay" - +internal fun format(value: Double, digits: Int = 4): String = buildString { + val res = buildString { + val ten = 10.0 + val approxOrder = if (value == 0.0) 0 else ceil(log10(abs(value))).toInt() + val order = if ( + ((value % ten) == 0.0) || + (value == 1.0) || + ((1 / value) % ten == 0.0) + ) approxOrder else approxOrder - 1 + val lead = value / ten.pow(order) + if (value >= 0.0) append(' ') + append(round(lead * ten.pow(digits)) / ten.pow(digits)) + when { + order == 0 -> Unit + order > 0 -> { + append("e+") + append(order) + } + else -> { + append('e') + append(order) + } + } + } val fLength = digits + 6 - val endSpace = " ".repeat(fLength - res.length) - return "$res$endSpace" + append(res) + repeat(fLength - res.length) { append(' ') } } internal fun DoubleTensor.toPrettyString(): String = buildString { From 48d86fac5620b5e663a5dc62618f4f2869e86521 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sat, 1 May 2021 19:55:48 +0100 Subject: [PATCH 164/211] invoke refactor --- .../core/algebras/TensorLinearStructure.kt | 6 ----- .../kscience/kmath/tensors/core/linUtils.kt | 2 +- .../kmath/tensors/core/TestBroadcasting.kt | 10 ++++---- .../core/TestDoubleAnalyticTensorAlgebra.kt | 2 +- .../core/TestDoubleLinearOpsAlgebra.kt | 24 +++++++++---------- .../kmath/tensors/core/TestDoubleTensor.kt | 6 ++--- .../tensors/core/TestDoubleTensorAlgebra.kt | 18 +++++++------- 7 files changed, 31 insertions(+), 37 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index 08aab5175..5fbc7390f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -9,12 +9,6 @@ import space.kscience.kmath.nd.Strides import kotlin.math.max -internal fun offsetFromIndex(index: IntArray, shape: IntArray, strides: IntArray): Int = - index.mapIndexed { i, value -> - if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})") - value * strides[i] - }.sum() - internal fun stridesFromShape(shape: IntArray): IntArray { val nDim = shape.size val res = IntArray(nDim) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt index ba8b823c9..8adbfad39 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt @@ -241,7 +241,7 @@ internal fun DoubleLinearOpsTensorAlgebra.qrHelper( } } } - r[j, j] = DoubleAnalyticTensorAlgebra.invoke { (v dot v).sqrt().value() } + r[j, j] = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 1070a1115..1564b85c9 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -9,7 +9,7 @@ import kotlin.test.assertTrue internal class TestBroadcasting { @Test - fun broadcastShapes() = DoubleTensorAlgebra.invoke { + fun broadcastShapes() = DoubleTensorAlgebra { assertTrue( broadcastShapes( intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) @@ -24,7 +24,7 @@ internal class TestBroadcasting { } @Test - fun broadcastTo() = DoubleTensorAlgebra.invoke { + fun broadcastTo() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) @@ -34,7 +34,7 @@ internal class TestBroadcasting { } @Test - fun broadcastTensors() = DoubleTensorAlgebra.invoke { + fun broadcastTensors() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -51,7 +51,7 @@ internal class TestBroadcasting { } @Test - fun broadcastOuterTensors() = DoubleTensorAlgebra.invoke { + fun broadcastOuterTensors() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -68,7 +68,7 @@ internal class TestBroadcasting { } @Test - fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra.invoke { + fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) {0.0}) val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) {0.0}) val tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0)) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 66959a0de..835b8a08a 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -27,7 +27,7 @@ internal class TestDoubleAnalyticTensorAlgebra { } @Test - fun testExp() = DoubleAnalyticTensorAlgebra.invoke { + fun testExp() = DoubleAnalyticTensorAlgebra { tensor.exp().let { assertTrue { shape contentEquals it.shape } assertTrue { buffer.fmap(::exp).epsEqual(it.mutableBuffer.array())} 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 6689e893a..65070af7f 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 @@ -10,7 +10,7 @@ import kotlin.test.assertTrue internal class TestDoubleLinearOpsTensorAlgebra { @Test - fun testDetLU() = DoubleLinearOpsTensorAlgebra.invoke { + fun testDetLU() = DoubleLinearOpsTensorAlgebra { val tensor = fromArray( intArrayOf(2, 2, 2), doubleArrayOf( @@ -35,7 +35,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testDet() = DoubleLinearOpsTensorAlgebra.invoke { + fun testDet() = DoubleLinearOpsTensorAlgebra { val expectedValue = 0.019827417 val m = fromArray( intArrayOf(3, 3), doubleArrayOf( @@ -49,7 +49,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testDetSingle() = DoubleLinearOpsTensorAlgebra.invoke { + fun testDetSingle() = DoubleLinearOpsTensorAlgebra { val expectedValue = 48.151623 val m = fromArray( intArrayOf(1, 1), doubleArrayOf( @@ -61,7 +61,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testInvLU() = DoubleLinearOpsTensorAlgebra.invoke { + fun testInvLU() = DoubleLinearOpsTensorAlgebra { val tensor = fromArray( intArrayOf(2, 2, 2), doubleArrayOf( @@ -86,14 +86,14 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testScalarProduct() = DoubleLinearOpsTensorAlgebra.invoke { + fun testScalarProduct() = DoubleLinearOpsTensorAlgebra { val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) assertEquals(a.dot(b).value(), 59.92) } @Test - fun testQR() = DoubleLinearOpsTensorAlgebra.invoke { + fun testQR() = DoubleLinearOpsTensorAlgebra { val shape = intArrayOf(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, @@ -114,7 +114,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testLU() = DoubleLinearOpsTensorAlgebra.invoke { + fun testLU() = DoubleLinearOpsTensorAlgebra { val shape = intArrayOf(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, @@ -134,7 +134,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testCholesky() = DoubleLinearOpsTensorAlgebra.invoke { + fun testCholesky() = DoubleLinearOpsTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 5), 0) val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) @@ -145,7 +145,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testSVD1D() = DoubleLinearOpsTensorAlgebra.invoke { + fun testSVD1D() = DoubleLinearOpsTensorAlgebra { val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = svd1d(tensor2) @@ -156,13 +156,13 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testSVD() = DoubleLinearOpsTensorAlgebra.invoke{ + fun testSVD() = DoubleLinearOpsTensorAlgebra{ testSVDFor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } @Test - fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra.invoke { + fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) @@ -170,7 +170,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra.invoke { + fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { val tensor = randomNormal(shape = intArrayOf(2, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 333a7bdec..ed5f8e780 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -15,14 +15,14 @@ import kotlin.test.assertTrue internal class TestDoubleTensor { @Test - fun valueTest() = DoubleTensorAlgebra.invoke { + fun valueTest() = DoubleTensorAlgebra { val value = 12.5 val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @Test - fun stridesTest() = DoubleTensorAlgebra.invoke { + fun stridesTest() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) assertEquals(tensor[intArrayOf(0, 1)], 5.8) assertTrue( @@ -31,7 +31,7 @@ internal class TestDoubleTensor { } @Test - fun getTest() = DoubleTensorAlgebra.invoke { + fun getTest() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) val matrix = tensor[0].as2D() assertEquals(matrix[0, 1], 5.8) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index a0efa4573..df2d21b96 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -10,21 +10,21 @@ import kotlin.test.assertTrue internal class TestDoubleTensorAlgebra { @Test - fun doublePlus() = DoubleTensorAlgebra.invoke { + fun doublePlus() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(11.0, 12.0)) } @Test - fun doubleDiv() = DoubleTensorAlgebra.invoke { + fun doubleDiv() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0)) val res = 2.0/tensor assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 0.5)) } @Test - fun divDouble() = DoubleTensorAlgebra.invoke { + fun divDouble() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0)) val res = tensor / 2.5 assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(4.0, 2.0)) @@ -40,7 +40,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun transpose3x2() = DoubleTensorAlgebra.invoke { + fun transpose3x2() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) @@ -49,7 +49,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun transpose1x2x3() = DoubleTensorAlgebra.invoke { + fun transpose1x2x3() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transpose(0, 1) val res02 = tensor.transpose(-3, 2) @@ -65,7 +65,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun linearStructure() = DoubleTensorAlgebra.invoke { + fun linearStructure() = DoubleTensorAlgebra { val shape = intArrayOf(3) val tensorA = full(value = -4.5, shape = shape) val tensorB = full(value = 10.9, shape = shape) @@ -97,7 +97,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun dot() = DoubleTensorAlgebra.invoke { + fun dot() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor11 = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) @@ -133,7 +133,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun diagonalEmbedding() = DoubleTensorAlgebra.invoke { + fun diagonalEmbedding() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = zeros(intArrayOf(2, 3, 4, 5)) @@ -166,7 +166,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun testEq() = DoubleTensorAlgebra.invoke { + fun testEq() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) From 1fe1a74b48c6670aeaf0adfe217a5407795b71b8 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 1 May 2021 22:40:53 +0300 Subject: [PATCH 165/211] Create LICENSE.txt --- LICENSE.txt | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From c8fb770ffddb6428790a762e32513414503a2b32 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 1 May 2021 22:44:43 +0300 Subject: [PATCH 166/211] Rename LICENSE.txt to LICENSE --- LICENSE.txt => LICENSE | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename LICENSE.txt => LICENSE (100%) diff --git a/LICENSE.txt b/LICENSE similarity index 100% rename from LICENSE.txt rename to LICENSE From 5aaba0dae443605b3dedb4bc4ee7733922b8e41f Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sun, 2 May 2021 16:19:05 +0100 Subject: [PATCH 167/211] TensorStructure to Tensor --- .../tensors/api/AnalyticTensorAlgebra.kt | 36 ++++----- .../tensors/api/LinearOpsTensorAlgebra.kt | 16 ++-- .../api/{TensorStructure.kt => Tensor.kt} | 2 +- .../kmath/tensors/api/TensorAlgebra.kt | 52 ++++++------ .../api/TensorPartialDivisionAlgebra.kt | 12 +-- .../kmath/tensors/core/BufferedTensor.kt | 16 ++-- .../algebras/BroadcastDoubleTensorAlgebra.kt | 18 ++--- .../algebras/DoubleAnalyticTensorAlgebra.kt | 36 ++++----- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 36 ++++----- .../core/algebras/DoubleTensorAlgebra.kt | 80 +++++++++---------- .../kscience/kmath/tensors/core/checks.kt | 8 +- 11 files changed, 156 insertions(+), 156 deletions(-) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/{TensorStructure.kt => Tensor.kt} (60%) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 5c92c56c4..cd13e0752 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.api /** - * Element-wise analytic operations on [TensorStructure]. + * Element-wise analytic operations on [Tensor]. * * @param T the type of items closed under analytic functions in the tensors. */ @@ -14,54 +14,54 @@ public interface AnalyticTensorAlgebra : TensorPartialDivisionAlgebra { //For information: https://pytorch.org/docs/stable/generated/torch.exp.html - public fun TensorStructure.exp(): TensorStructure + public fun Tensor.exp(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.log.html - public fun TensorStructure.log(): TensorStructure + public fun Tensor.log(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.sqrt.html - public fun TensorStructure.sqrt(): TensorStructure + public fun Tensor.sqrt(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos - public fun TensorStructure.cos(): TensorStructure + public fun Tensor.cos(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.acos.html#torch.acos - public fun TensorStructure.acos(): TensorStructure + public fun Tensor.acos(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.cosh - public fun TensorStructure.cosh(): TensorStructure + public fun Tensor.cosh(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.acosh - public fun TensorStructure.acosh(): TensorStructure + public fun Tensor.acosh(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sin - public fun TensorStructure.sin(): TensorStructure + public fun Tensor.sin(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asin - public fun TensorStructure.asin(): TensorStructure + public fun Tensor.asin(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sinh - public fun TensorStructure.sinh(): TensorStructure + public fun Tensor.sinh(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asinh - public fun TensorStructure.asinh(): TensorStructure + public fun Tensor.asinh(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.atan.html#torch.tan - public fun TensorStructure.tan(): TensorStructure + public fun Tensor.tan(): Tensor //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.atan - public fun TensorStructure.atan(): TensorStructure + public fun Tensor.atan(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.tanh - public fun TensorStructure.tanh(): TensorStructure + public fun Tensor.tanh(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.atanh - public fun TensorStructure.atanh(): TensorStructure + public fun Tensor.atanh(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.ceil.html#torch.ceil - public fun TensorStructure.ceil(): TensorStructure + public fun Tensor.ceil(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor - public fun TensorStructure.floor(): TensorStructure + public fun Tensor.floor(): Tensor } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index bcbb52a1b..527e5d386 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.api /** - * Common linear algebra operations. Operates on [TensorStructure]. + * Common linear algebra operations. Operates on [Tensor]. * * @param T the type of items closed under division in the tensors. */ @@ -19,7 +19,7 @@ public interface LinearOpsTensorAlgebra : * * @return the determinant. */ - public fun TensorStructure.det(): TensorStructure + public fun Tensor.det(): Tensor /** * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input. @@ -29,7 +29,7 @@ public interface LinearOpsTensorAlgebra : * * @return the multiplicative inverse of a matrix. */ - public fun TensorStructure.inv(): TensorStructure + public fun Tensor.inv(): Tensor /** * Cholesky decomposition. @@ -44,7 +44,7 @@ public interface LinearOpsTensorAlgebra : * * @return the batch of L matrices. */ - public fun TensorStructure.cholesky(): TensorStructure + public fun Tensor.cholesky(): Tensor /** * QR decomposition. @@ -57,7 +57,7 @@ public interface LinearOpsTensorAlgebra : * * @return pair of Q and R tensors. */ - public fun TensorStructure.qr(): Pair, TensorStructure> + public fun Tensor.qr(): Pair, Tensor> /** * LUP decomposition @@ -70,7 +70,7 @@ public interface LinearOpsTensorAlgebra : * * * @return triple of P, L and U tensors */ - public fun TensorStructure.lu(): Triple, TensorStructure, TensorStructure> + public fun Tensor.lu(): Triple, Tensor, Tensor> /** * Singular Value Decomposition. @@ -83,7 +83,7 @@ public interface LinearOpsTensorAlgebra : * * @return the determinant. */ - public fun TensorStructure.svd(): Triple, TensorStructure, TensorStructure> + public fun Tensor.svd(): Triple, Tensor, Tensor> /** * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, @@ -92,6 +92,6 @@ public interface LinearOpsTensorAlgebra : * * @return a pair (eigenvalues, eigenvectors) */ - public fun TensorStructure.symEig(): Pair, TensorStructure> + public fun Tensor.symEig(): Pair, Tensor> } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt similarity index 60% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorStructure.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt index edecd6383..179787684 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt @@ -2,4 +2,4 @@ package space.kscience.kmath.tensors.api import space.kscience.kmath.nd.MutableStructureND -public typealias TensorStructure = MutableStructureND +public typealias Tensor = MutableStructureND diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 96d6985d8..b9c707c0b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -8,19 +8,19 @@ package space.kscience.kmath.tensors.api import space.kscience.kmath.operations.Algebra /** - * Algebra over a ring on [TensorStructure]. + * Algebra over a ring on [Tensor]. * For more information: https://proofwiki.org/wiki/Definition:Algebra_over_Ring * * @param T the type of items in the tensors. */ -public interface TensorAlgebra: Algebra> { +public interface TensorAlgebra: Algebra> { /** * Returns a single tensor value of unit dimension. The tensor shape must be equal to [1]. * * @return the value of a scalar tensor. */ - public fun TensorStructure.value(): T + public fun Tensor.value(): T /** * Each element of the tensor [other] is added to this value. @@ -29,7 +29,7 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be added. * @return the sum of this value and tensor [other]. */ - public operator fun T.plus(other: TensorStructure): TensorStructure + public operator fun T.plus(other: Tensor): Tensor /** * Adds the scalar [value] to each element of this tensor and returns a new resulting tensor. @@ -37,7 +37,7 @@ public interface TensorAlgebra: Algebra> { * @param value the number to be added to each element of this tensor. * @return the sum of this tensor and [value]. */ - public operator fun TensorStructure.plus(value: T): TensorStructure + public operator fun Tensor.plus(value: T): Tensor /** * Each element of the tensor [other] is added to each element of this tensor. @@ -46,21 +46,21 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be added. * @return the sum of this tensor and [other]. */ - public operator fun TensorStructure.plus(other: TensorStructure): TensorStructure + public operator fun Tensor.plus(other: Tensor): Tensor /** * Adds the scalar [value] to each element of this tensor. * * @param value the number to be added to each element of this tensor. */ - public operator fun TensorStructure.plusAssign(value: T): Unit + public operator fun Tensor.plusAssign(value: T): Unit /** * Each element of the tensor [other] is added to each element of this tensor. * * @param other tensor to be added. */ - public operator fun TensorStructure.plusAssign(other: TensorStructure): Unit + public operator fun Tensor.plusAssign(other: Tensor): Unit /** @@ -70,7 +70,7 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be subtracted. * @return the difference between this value and tensor [other]. */ - public operator fun T.minus(other: TensorStructure): TensorStructure + public operator fun T.minus(other: Tensor): Tensor /** * Subtracts the scalar [value] from each element of this tensor and returns a new resulting tensor. @@ -78,7 +78,7 @@ public interface TensorAlgebra: Algebra> { * @param value the number to be subtracted from each element of this tensor. * @return the difference between this tensor and [value]. */ - public operator fun TensorStructure.minus(value: T): TensorStructure + public operator fun Tensor.minus(value: T): Tensor /** * Each element of the tensor [other] is subtracted from each element of this tensor. @@ -87,21 +87,21 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be subtracted. * @return the difference between this tensor and [other]. */ - public operator fun TensorStructure.minus(other: TensorStructure): TensorStructure + public operator fun Tensor.minus(other: Tensor): Tensor /** * Subtracts the scalar [value] from each element of this tensor. * * @param value the number to be subtracted from each element of this tensor. */ - public operator fun TensorStructure.minusAssign(value: T): Unit + public operator fun Tensor.minusAssign(value: T): Unit /** * Each element of the tensor [other] is subtracted from each element of this tensor. * * @param other tensor to be subtracted. */ - public operator fun TensorStructure.minusAssign(other: TensorStructure): Unit + public operator fun Tensor.minusAssign(other: Tensor): Unit /** @@ -111,7 +111,7 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be multiplied. * @return the product of this value and tensor [other]. */ - public operator fun T.times(other: TensorStructure): TensorStructure + public operator fun T.times(other: Tensor): Tensor /** * Multiplies the scalar [value] by each element of this tensor and returns a new resulting tensor. @@ -119,7 +119,7 @@ public interface TensorAlgebra: Algebra> { * @param value the number to be multiplied by each element of this tensor. * @return the product of this tensor and [value]. */ - public operator fun TensorStructure.times(value: T): TensorStructure + public operator fun Tensor.times(value: T): Tensor /** * Each element of the tensor [other] is multiplied by each element of this tensor. @@ -128,28 +128,28 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be multiplied. * @return the product of this tensor and [other]. */ - public operator fun TensorStructure.times(other: TensorStructure): TensorStructure + public operator fun Tensor.times(other: Tensor): Tensor /** * Multiplies the scalar [value] by each element of this tensor. * * @param value the number to be multiplied by each element of this tensor. */ - public operator fun TensorStructure.timesAssign(value: T): Unit + public operator fun Tensor.timesAssign(value: T): Unit /** * Each element of the tensor [other] is multiplied by each element of this tensor. * * @param other tensor to be multiplied. */ - public operator fun TensorStructure.timesAssign(other: TensorStructure): Unit + public operator fun Tensor.timesAssign(other: Tensor): Unit /** * Numerical negative, element-wise. * * @return tensor negation of the original tensor. */ - public operator fun TensorStructure.unaryMinus(): TensorStructure + public operator fun Tensor.unaryMinus(): Tensor /** * Returns the tensor at index i @@ -158,7 +158,7 @@ public interface TensorAlgebra: Algebra> { * @param i index of the extractable tensor * @return subtensor of the original tensor with index [i] */ - public operator fun TensorStructure.get(i: Int): TensorStructure + public operator fun Tensor.get(i: Int): Tensor /** * Returns a tensor that is a transposed version of this tensor. The given dimensions [i] and [j] are swapped. @@ -168,7 +168,7 @@ public interface TensorAlgebra: Algebra> { * @param j the second dimension to be transposed * @return transposed tensor */ - public fun TensorStructure.transpose(i: Int = -2, j: Int = -1): TensorStructure + public fun Tensor.transpose(i: Int = -2, j: Int = -1): Tensor /** * Returns a new tensor with the same data as the self tensor but of a different shape. @@ -178,7 +178,7 @@ public interface TensorAlgebra: Algebra> { * @param shape the desired size * @return tensor with new shape */ - public fun TensorStructure.view(shape: IntArray): TensorStructure + public fun Tensor.view(shape: IntArray): Tensor /** * View this tensor as the same size as [other]. @@ -188,7 +188,7 @@ public interface TensorAlgebra: Algebra> { * @param other the result tensor has the same size as other. * @return the result tensor with the same size as other. */ - public fun TensorStructure.viewAs(other: TensorStructure): TensorStructure + public fun Tensor.viewAs(other: Tensor): Tensor /** * Matrix product of two tensors. @@ -219,7 +219,7 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be multiplied * @return mathematical product of two tensors */ - public infix fun TensorStructure.dot(other: TensorStructure): TensorStructure + public infix fun Tensor.dot(other: Tensor): Tensor /** * Creates a tensor whose diagonals of certain 2D planes (specified by [dim1] and [dim2]) @@ -245,10 +245,10 @@ public interface TensorAlgebra: Algebra> { * are filled by [diagonalEntries] */ public fun diagonalEmbedding( - diagonalEntries: TensorStructure, + diagonalEntries: Tensor, offset: Int = 0, dim1: Int = -2, dim2: Int = -1 - ): TensorStructure + ): Tensor } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt index eccc6fa0d..921157963 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.api /** - * Algebra over a field with partial division on [TensorStructure]. + * Algebra over a field with partial division on [Tensor]. * For more information: https://proofwiki.org/wiki/Definition:Division_Algebra * * @param T the type of items closed under division in the tensors. @@ -21,7 +21,7 @@ public interface TensorPartialDivisionAlgebra : * @param other tensor to divide by. * @return the division of this value by the tensor [other]. */ - public operator fun T.div(other: TensorStructure): TensorStructure + public operator fun T.div(other: Tensor): Tensor /** * Divide by the scalar [value] each element of this tensor returns a new resulting tensor. @@ -29,7 +29,7 @@ public interface TensorPartialDivisionAlgebra : * @param value the number to divide by each element of this tensor. * @return the division of this tensor by the [value]. */ - public operator fun TensorStructure.div(value: T): TensorStructure + public operator fun Tensor.div(value: T): Tensor /** * Each element of the tensor [other] is divided by each element of this tensor. @@ -38,19 +38,19 @@ public interface TensorPartialDivisionAlgebra : * @param other tensor to be divided by. * @return the division of this tensor by [other]. */ - public operator fun TensorStructure.div(other: TensorStructure): TensorStructure + public operator fun Tensor.div(other: Tensor): Tensor /** * Divides by the scalar [value] each element of this tensor. * * @param value the number to divide by each element of this tensor. */ - public operator fun TensorStructure.divAssign(value: T) + public operator fun Tensor.divAssign(value: T) /** * Each element of this tensor is divided by each element of the [other] tensor. * * @param other tensor to be divide by. */ - public operator fun TensorStructure.divAssign(other: TensorStructure) + public operator fun Tensor.divAssign(other: Tensor) } 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 9541a97f9..d0882efb8 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 @@ -2,7 +2,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.structures.* -import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure @@ -10,7 +10,7 @@ public open class BufferedTensor( override val shape: IntArray, internal val mutableBuffer: MutableBuffer, internal val bufferStart: Int -) : TensorStructure { +) : Tensor { public val linearStructure: TensorLinearStructure get() = TensorLinearStructure(shape) @@ -53,33 +53,33 @@ internal fun BufferedTensor.asTensor(): IntTensor = internal fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) -internal fun TensorStructure.copyToBufferedTensor(): BufferedTensor = +internal fun Tensor.copyToBufferedTensor(): BufferedTensor = BufferedTensor( this.shape, TensorLinearStructure(this.shape).indices().map(this::get).toMutableList().asMutableBuffer(), 0 ) -internal fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { +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 TensorStructure.tensor: DoubleTensor +internal val Tensor.tensor: DoubleTensor get() = when (this) { is DoubleTensor -> this else -> this.toBufferedTensor().asTensor() } -internal val TensorStructure.tensor: IntTensor +internal val Tensor.tensor: IntTensor get() = when (this) { is IntTensor -> this else -> this.toBufferedTensor().asTensor() } -public fun TensorStructure.toDoubleTensor(): DoubleTensor = this.tensor -public fun TensorStructure.toIntTensor(): IntTensor = this.tensor +public fun Tensor.toDoubleTensor(): DoubleTensor = this.tensor +public fun Tensor.toIntTensor(): IntTensor = this.tensor public fun Array.toDoubleTensor(): DoubleTensor { val n = size diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt index 9b97d5ef2..873ec9027 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core.algebras -import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.broadcastTensors import space.kscience.kmath.tensors.core.broadcastTo @@ -16,7 +16,7 @@ import space.kscience.kmath.tensors.core.broadcastTo */ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { - override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { + override fun Tensor.plus(other: Tensor): DoubleTensor { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] @@ -26,7 +26,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun TensorStructure.plusAssign(other: TensorStructure) { + override fun Tensor.plusAssign(other: Tensor) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] += @@ -34,7 +34,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { } } - override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { + override fun Tensor.minus(other: Tensor): DoubleTensor { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] @@ -44,7 +44,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun TensorStructure.minusAssign(other: TensorStructure) { + override fun Tensor.minusAssign(other: Tensor) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] -= @@ -52,7 +52,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { } } - override fun TensorStructure.times(other: TensorStructure): DoubleTensor { + override fun Tensor.times(other: Tensor): DoubleTensor { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] @@ -63,7 +63,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun TensorStructure.timesAssign(other: TensorStructure) { + override fun Tensor.timesAssign(other: Tensor) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] *= @@ -71,7 +71,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { } } - override fun TensorStructure.div(other: TensorStructure): DoubleTensor { + override fun Tensor.div(other: Tensor): DoubleTensor { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] @@ -82,7 +82,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun TensorStructure.divAssign(other: TensorStructure) { + override fun Tensor.divAssign(other: Tensor) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] /= diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 4a942df84..9aa6f093e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.core.algebras import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra -import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.tensor import kotlin.math.* @@ -14,38 +14,38 @@ import kotlin.math.* public object DoubleAnalyticTensorAlgebra : AnalyticTensorAlgebra, DoubleTensorAlgebra() { - override fun TensorStructure.exp(): DoubleTensor = tensor.map(::exp) + override fun Tensor.exp(): DoubleTensor = tensor.map(::exp) - override fun TensorStructure.log(): DoubleTensor = tensor.map(::ln) + override fun Tensor.log(): DoubleTensor = tensor.map(::ln) - override fun TensorStructure.sqrt(): DoubleTensor = tensor.map(::sqrt) + override fun Tensor.sqrt(): DoubleTensor = tensor.map(::sqrt) - override fun TensorStructure.cos(): DoubleTensor = tensor.map(::cos) + override fun Tensor.cos(): DoubleTensor = tensor.map(::cos) - override fun TensorStructure.acos(): DoubleTensor = tensor.map(::acos) + override fun Tensor.acos(): DoubleTensor = tensor.map(::acos) - override fun TensorStructure.cosh(): DoubleTensor = tensor.map(::cosh) + override fun Tensor.cosh(): DoubleTensor = tensor.map(::cosh) - override fun TensorStructure.acosh(): DoubleTensor = tensor.map(::acosh) + override fun Tensor.acosh(): DoubleTensor = tensor.map(::acosh) - override fun TensorStructure.sin(): DoubleTensor = tensor.map(::sin) + override fun Tensor.sin(): DoubleTensor = tensor.map(::sin) - override fun TensorStructure.asin(): DoubleTensor = tensor.map(::asin) + override fun Tensor.asin(): DoubleTensor = tensor.map(::asin) - override fun TensorStructure.sinh(): DoubleTensor = tensor.map(::sinh) + override fun Tensor.sinh(): DoubleTensor = tensor.map(::sinh) - override fun TensorStructure.asinh(): DoubleTensor = tensor.map(::asinh) + override fun Tensor.asinh(): DoubleTensor = tensor.map(::asinh) - override fun TensorStructure.tan(): DoubleTensor = tensor.map(::tan) + override fun Tensor.tan(): DoubleTensor = tensor.map(::tan) - override fun TensorStructure.atan(): DoubleTensor = tensor.map(::atan) + override fun Tensor.atan(): DoubleTensor = tensor.map(::atan) - override fun TensorStructure.tanh(): DoubleTensor = tensor.map(::tanh) + override fun Tensor.tanh(): DoubleTensor = tensor.map(::tanh) - override fun TensorStructure.atanh(): DoubleTensor = tensor.map(::atanh) + override fun Tensor.atanh(): DoubleTensor = tensor.map(::atanh) - override fun TensorStructure.ceil(): DoubleTensor = tensor.map(::ceil) + override fun Tensor.ceil(): DoubleTensor = tensor.map(::ceil) - override fun TensorStructure.floor(): DoubleTensor = tensor.map(::floor) + override fun Tensor.floor(): DoubleTensor = tensor.map(::floor) } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index dd5ad5a61..89345e315 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.tensors.core.algebras import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D -import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.checkSquareMatrix import space.kscience.kmath.tensors.core.choleskyHelper @@ -25,19 +25,19 @@ public object DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, DoubleTensorAlgebra() { - override fun TensorStructure.inv(): DoubleTensor = invLU(1e-9) + override fun Tensor.inv(): DoubleTensor = invLU(1e-9) - override fun TensorStructure.det(): DoubleTensor = detLU(1e-9) + override fun Tensor.det(): DoubleTensor = detLU(1e-9) - public fun TensorStructure.luFactor(epsilon: Double): Pair = + public fun Tensor.luFactor(epsilon: Double): Pair = computeLU(tensor, epsilon) ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") - public fun TensorStructure.luFactor(): Pair = luFactor(1e-9) + public fun Tensor.luFactor(): Pair = luFactor(1e-9) public fun luPivot( - luTensor: TensorStructure, - pivotsTensor: TensorStructure + luTensor: Tensor, + pivotsTensor: Tensor ): Triple { checkSquareMatrix(luTensor.shape) check( @@ -66,7 +66,7 @@ public object DoubleLinearOpsTensorAlgebra : return Triple(pTensor, lTensor, uTensor) } - public fun TensorStructure.cholesky(epsilon: Double): DoubleTensor { + public fun Tensor.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) checkPositiveDefinite(tensor, epsilon) @@ -79,9 +79,9 @@ public object DoubleLinearOpsTensorAlgebra : return lTensor } - override fun TensorStructure.cholesky(): DoubleTensor = cholesky(1e-6) + override fun Tensor.cholesky(): DoubleTensor = cholesky(1e-6) - override fun TensorStructure.qr(): Pair { + override fun Tensor.qr(): Pair { checkSquareMatrix(shape) val qTensor = zeroesLike() val rTensor = zeroesLike() @@ -95,10 +95,10 @@ public object DoubleLinearOpsTensorAlgebra : return qTensor to rTensor } - override fun TensorStructure.svd(): Triple = + override fun Tensor.svd(): Triple = svd(epsilon = 1e-10) - public fun TensorStructure.svd(epsilon: Double): Triple { + public fun Tensor.svd(epsilon: Double): Triple { val size = tensor.linearStructure.dim val commonShape = tensor.shape.sliceArray(0 until size - 2) val (n, m) = tensor.shape.sliceArray(size - 2 until size) @@ -122,11 +122,11 @@ public object DoubleLinearOpsTensorAlgebra : return Triple(uTensor.transpose(), sTensor, vTensor.transpose()) } - override fun TensorStructure.symEig(): Pair = + override fun Tensor.symEig(): Pair = symEig(epsilon = 1e-15) //For information: http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html - public fun TensorStructure.symEig(epsilon: Double): Pair { + public fun Tensor.symEig(epsilon: Double): Pair { checkSymmetric(tensor, epsilon) val (u, s, v) = tensor.svd(epsilon) val shp = s.shape + intArrayOf(1) @@ -139,7 +139,7 @@ public object DoubleLinearOpsTensorAlgebra : return eig to v } - public fun TensorStructure.detLU(epsilon: Double = 1e-9): DoubleTensor { + public fun Tensor.detLU(epsilon: Double = 1e-9): DoubleTensor { checkSquareMatrix(tensor.shape) val luTensor = tensor.copy() @@ -164,7 +164,7 @@ public object DoubleLinearOpsTensorAlgebra : return detTensor } - public fun TensorStructure.invLU(epsilon: Double = 1e-9): DoubleTensor { + public fun Tensor.invLU(epsilon: Double = 1e-9): DoubleTensor { val (luTensor, pivotsTensor) = luFactor(epsilon) val invTensor = luTensor.zeroesLike() @@ -177,11 +177,11 @@ public object DoubleLinearOpsTensorAlgebra : return invTensor } - public fun TensorStructure.lu(epsilon: Double = 1e-9): Triple { + public fun Tensor.lu(epsilon: Double = 1e-9): Triple { val (lu, pivots) = this.luFactor(epsilon) return luPivot(lu, pivots) } - override fun TensorStructure.lu(): Triple = lu(1e-9) + override fun Tensor.lu(): Triple = lu(1e-9) } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index d3e8bf175..4009f7b45 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.tensors.core.algebras import space.kscience.kmath.nd.as2D import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra -import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.broadcastOuterTensors import space.kscience.kmath.tensors.core.checkBufferShapeConsistency @@ -25,7 +25,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public companion object : DoubleTensorAlgebra() - override fun TensorStructure.value(): Double { + override fun Tensor.value(): Double { check(tensor.shape contentEquals intArrayOf(1)) { "Inconsistent value for tensor of shape ${shape.toList()}" } @@ -39,7 +39,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(shape, buffer, 0) } - override operator fun TensorStructure.get(i: Int): DoubleTensor { + override operator fun Tensor.get(i: Int): DoubleTensor { val lastShape = tensor.shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) val newStart = newShape.reduce(Int::times) * i + tensor.bufferStart @@ -52,7 +52,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(shape, buffer) } - public fun TensorStructure.fullLike(value: Double): DoubleTensor { + public fun Tensor.fullLike(value: Double): DoubleTensor { val shape = tensor.shape val buffer = DoubleArray(tensor.numElements) { value } return DoubleTensor(shape, buffer) @@ -60,11 +60,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun zeros(shape: IntArray): DoubleTensor = full(0.0, shape) - public fun TensorStructure.zeroesLike(): DoubleTensor = tensor.fullLike(0.0) + public fun Tensor.zeroesLike(): DoubleTensor = tensor.fullLike(0.0) public fun ones(shape: IntArray): DoubleTensor = full(1.0, shape) - public fun TensorStructure.onesLike(): DoubleTensor = tensor.fullLike(1.0) + public fun Tensor.onesLike(): DoubleTensor = tensor.fullLike(1.0) public fun eye(n: Int): DoubleTensor { val shape = intArrayOf(n, n) @@ -76,20 +76,20 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return res } - public fun TensorStructure.copy(): DoubleTensor { + public fun Tensor.copy(): DoubleTensor { return DoubleTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart) } - override fun Double.plus(other: TensorStructure): DoubleTensor { + override fun Double.plus(other: Tensor): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] + this } return DoubleTensor(other.shape, resBuffer) } - override fun TensorStructure.plus(value: Double): DoubleTensor = value + tensor + override fun Tensor.plus(value: Double): DoubleTensor = value + tensor - override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { + override fun Tensor.plus(other: Tensor): DoubleTensor { checkShapesCompatible(tensor, other.tensor) val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[i] + other.tensor.mutableBuffer.array()[i] @@ -97,13 +97,13 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(tensor.shape, resBuffer) } - override fun TensorStructure.plusAssign(value: Double) { + override fun Tensor.plusAssign(value: Double) { for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] += value } } - override fun TensorStructure.plusAssign(other: TensorStructure) { + override fun Tensor.plusAssign(other: Tensor) { checkShapesCompatible(tensor, other.tensor) for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] += @@ -111,21 +111,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } } - override fun Double.minus(other: TensorStructure): DoubleTensor { + override fun Double.minus(other: Tensor): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> this - other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } - override fun TensorStructure.minus(value: Double): DoubleTensor { + override fun Tensor.minus(value: Double): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[tensor.bufferStart + i] - value } return DoubleTensor(tensor.shape, resBuffer) } - override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { + override fun Tensor.minus(other: Tensor): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[i] - other.tensor.mutableBuffer.array()[i] @@ -133,13 +133,13 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(tensor.shape, resBuffer) } - override fun TensorStructure.minusAssign(value: Double) { + override fun Tensor.minusAssign(value: Double) { for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] -= value } } - override fun TensorStructure.minusAssign(other: TensorStructure) { + override fun Tensor.minusAssign(other: Tensor) { checkShapesCompatible(tensor, other) for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] -= @@ -147,16 +147,16 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } } - override fun Double.times(other: TensorStructure): DoubleTensor { + override fun Double.times(other: Tensor): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) } - override fun TensorStructure.times(value: Double): DoubleTensor = value * tensor + override fun Tensor.times(value: Double): DoubleTensor = value * tensor - override fun TensorStructure.times(other: TensorStructure): DoubleTensor { + override fun Tensor.times(other: Tensor): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[tensor.bufferStart + i] * @@ -165,13 +165,13 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(tensor.shape, resBuffer) } - override fun TensorStructure.timesAssign(value: Double) { + override fun Tensor.timesAssign(value: Double) { for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] *= value } } - override fun TensorStructure.timesAssign(other: TensorStructure) { + override fun Tensor.timesAssign(other: Tensor) { checkShapesCompatible(tensor, other) for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] *= @@ -179,21 +179,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } } - override fun Double.div(other: TensorStructure): DoubleTensor { + override fun Double.div(other: Tensor): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> this / other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } - override fun TensorStructure.div(value: Double): DoubleTensor { + override fun Tensor.div(value: Double): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[tensor.bufferStart + i] / value } return DoubleTensor(shape, resBuffer) } - override fun TensorStructure.div(other: TensorStructure): DoubleTensor { + override fun Tensor.div(other: Tensor): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[other.tensor.bufferStart + i] / @@ -202,13 +202,13 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(tensor.shape, resBuffer) } - override fun TensorStructure.divAssign(value: Double) { + override fun Tensor.divAssign(value: Double) { for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] /= value } } - override fun TensorStructure.divAssign(other: TensorStructure) { + override fun Tensor.divAssign(other: Tensor) { checkShapesCompatible(tensor, other) for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] /= @@ -216,14 +216,14 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } } - override fun TensorStructure.unaryMinus(): DoubleTensor { + override fun Tensor.unaryMinus(): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[tensor.bufferStart + i].unaryMinus() } return DoubleTensor(tensor.shape, resBuffer) } - override fun TensorStructure.transpose(i: Int, j: Int): DoubleTensor { + override fun Tensor.transpose(i: Int, j: Int): DoubleTensor { val ii = tensor.minusIndex(i) val jj = tensor.minusIndex(j) checkTranspose(tensor.dimension, ii, jj) @@ -248,16 +248,16 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } - override fun TensorStructure.view(shape: IntArray): DoubleTensor { + override fun Tensor.view(shape: IntArray): DoubleTensor { checkView(tensor, shape) return DoubleTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart) } - override fun TensorStructure.viewAs(other: TensorStructure): DoubleTensor { + override fun Tensor.viewAs(other: Tensor): DoubleTensor { return tensor.view(other.shape) } - override infix fun TensorStructure.dot(other: TensorStructure): DoubleTensor { + override infix fun Tensor.dot(other: Tensor): DoubleTensor { if (tensor.shape.size == 1 && other.shape.size == 1) { return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.mutableBuffer.array().sum())) } @@ -309,7 +309,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return resTensor } - override fun diagonalEmbedding(diagonalEntries: TensorStructure, offset: Int, dim1: Int, dim2: Int): + override fun diagonalEmbedding(diagonalEntries: Tensor, offset: Int, dim1: Int, dim2: Int): DoubleTensor { val n = diagonalEntries.shape.size val d1 = minusIndexFrom(n + 1, dim1) @@ -358,7 +358,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } - public fun TensorStructure.map(transform: (Double) -> Double): DoubleTensor { + public fun Tensor.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( tensor.shape, tensor.mutableBuffer.array().map { transform(it) }.toDoubleArray(), @@ -366,14 +366,14 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { ) } - public fun TensorStructure.eq(other: TensorStructure, epsilon: Double): Boolean { + public fun Tensor.eq(other: Tensor, epsilon: Double): Boolean { return tensor.eq(other) { x, y -> abs(x - y) < epsilon } } - public infix fun TensorStructure.eq(other: TensorStructure): Boolean = tensor.eq(other, 1e-5) + public infix fun Tensor.eq(other: Tensor): Boolean = tensor.eq(other, 1e-5) - private fun TensorStructure.eq( - other: TensorStructure, + private fun Tensor.eq( + other: Tensor, eqFunction: (Double, Double) -> Boolean ): Boolean { checkShapesCompatible(tensor, other) @@ -396,7 +396,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun randomNormal(shape: IntArray, seed: Long = 0): DoubleTensor = DoubleTensor(shape, getRandomNormals(shape.reduce(Int::times), seed)) - public fun TensorStructure.randomNormalLike(seed: Long = 0): DoubleTensor = + public fun Tensor.randomNormalLike(seed: Long = 0): DoubleTensor = DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) // stack tensors by axis 0 @@ -412,7 +412,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } // build tensor from this rows by given indices - public fun TensorStructure.rowsByIndices(indices: IntArray): DoubleTensor { + public fun Tensor.rowsByIndices(indices: IntArray): DoubleTensor { return stack(indices.map { this[it] }) } } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index b1c12ccde..f8bd5027a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra @@ -20,7 +20,7 @@ internal fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray) = "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" } -internal fun checkShapesCompatible(a: TensorStructure, b: TensorStructure) = +internal fun checkShapesCompatible(a: Tensor, b: Tensor) = check(a.shape contentEquals b.shape) { "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " } @@ -30,7 +30,7 @@ internal fun checkTranspose(dim: Int, i: Int, j: Int) = "Cannot transpose $i to $j for a tensor of dim $dim" } -internal fun checkView(a: TensorStructure, shape: IntArray) = +internal fun checkView(a: Tensor, shape: IntArray) = check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) internal fun checkSquareMatrix(shape: IntArray) { @@ -44,7 +44,7 @@ internal fun checkSquareMatrix(shape: IntArray) { } internal fun DoubleTensorAlgebra.checkSymmetric( - tensor: TensorStructure, epsilon: Double = 1e-6 + tensor: Tensor, epsilon: Double = 1e-6 ) = check(tensor.eq(tensor.transpose(), epsilon)) { "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" From f0627b2ced8cba0c641cb40a0bd10184b336b657 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 3 May 2021 00:24:32 +0700 Subject: [PATCH 168/211] Simplify and revise test cases for MST compilation engines #285 --- ...TestCompilerConsistencyWithInterpreter.kt} | 24 ++--- .../kmath/ast/TestCompilerOperations.kt | 65 +++++++++++++ .../kmath/ast/TestCompilerVariables.kt} | 14 +-- .../ast/{ParserTest.kt => TestParser.kt} | 2 +- ...cedenceTest.kt => TestParserPrecedence.kt} | 2 +- .../kotlin/space/kscience/kmath/ast/utils.kt | 25 +++++ .../kotlin/space/kscience/kmath/ast/utils.kt | 39 ++++++++ .../TestESTreeConsistencyWithInterpreter.kt | 97 ------------------- .../estree/TestESTreeOperationsSupport.kt | 42 -------- .../kmath/estree/TestESTreeSpecialization.kt | 76 --------------- .../kmath/estree/TestESTreeVariables.kt | 34 ------- .../kmath/wasm/TestWasmOperationsSupport.kt | 42 -------- .../kmath/wasm/TestWasmSpecialization.kt | 76 --------------- .../asm/TestAsmConsistencyWithInterpreter.kt | 97 ------------------- .../kmath/asm/TestAsmOperationsSupport.kt | 42 -------- .../kmath/asm/TestAsmSpecialization.kt | 76 --------------- .../kscience/kmath/asm/TestAsmVariables.kt | 34 ------- .../kotlin/space/kscience/kmath/ast/utils.kt | 25 +++++ 18 files changed, 171 insertions(+), 641 deletions(-) rename kmath-ast/src/{jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt => commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt} (76%) create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt rename kmath-ast/src/{jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt => commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt} (76%) rename kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/{ParserTest.kt => TestParser.kt} (98%) rename kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/{ParserPrecedenceTest.kt => TestParserPrecedence.kt} (96%) create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt delete mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt delete mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt delete mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt delete mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt delete mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt delete mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt create mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt similarity index 76% rename from kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt index f3e0726d6..0d018070c 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt @@ -3,12 +3,12 @@ * 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.wasm +package space.kscience.kmath.ast import space.kscience.kmath.expressions.MstField import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.interpret -import space.kscience.kmath.misc.symbol +import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing import space.kscience.kmath.operations.bindSymbol @@ -16,45 +16,41 @@ import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals -internal class TestWasmConsistencyWithInterpreter { +internal class TestCompilerConsistencyWithInterpreter { @Test - fun intRing() { + fun intRing() = runCompilerTest { val mst = MstRing { binaryOperationFunction("+")( unaryOperationFunction("+")( (bindSymbol(x) - (2.toByte() + (scale( add(number(1), number(1)), - 2.0 + 2.0, ) + 1.toByte()))) * 3.0 - 1.toByte() ), - number(1) + number(1), ) * number(2) } assertEquals( mst.interpret(IntRing, x to 3), - mst.compile(IntRing, x to 3) + mst.compile(IntRing, x to 3), ) } @Test - fun doubleField() { + fun doubleField() = runCompilerTest { val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), - number(1) / 2 + number(2.0) * one + number(1) / 2 + number(2.0) * one, ) + zero } assertEquals( mst.interpret(DoubleField, x to 2.0), - mst.compile(DoubleField, x to 2.0) + mst.compile(DoubleField, x to 2.0), ) } - - private companion object { - private val x by symbol - } } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt new file mode 100644 index 000000000..7d2af31c2 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt @@ -0,0 +1,65 @@ +/* + * 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.ast + +import space.kscience.kmath.expressions.MstExtendedField +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.Symbol.Companion.x +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class TestCompilerOperations { + @Test + fun testUnaryPlus() = runCompilerTest { + val expr = MstExtendedField { +bindSymbol(x) }.compileToExpression(DoubleField) + assertEquals(2.0, expr(x to 2.0)) + } + + @Test + fun testUnaryMinus() = runCompilerTest { + val expr = MstExtendedField { -bindSymbol(x) }.compileToExpression(DoubleField) + assertEquals(-2.0, expr(x to 2.0)) + } + + @Test + fun testAdd() = runCompilerTest { + val expr = MstExtendedField { bindSymbol(x) + bindSymbol(x) }.compileToExpression(DoubleField) + assertEquals(4.0, expr(x to 2.0)) + } + + @Test + fun testSine() = runCompilerTest { + val expr = MstExtendedField { sin(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(0.0, expr(x to 0.0)) + } + + @Test + fun testCosine() = runCompilerTest { + val expr = MstExtendedField { cos(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(1.0, expr(x to 0.0)) + } + + @Test + fun testSubtract() = runCompilerTest { + val expr = MstExtendedField { bindSymbol(x) - bindSymbol(x) }.compileToExpression(DoubleField) + assertEquals(0.0, expr(x to 2.0)) + } + + @Test + fun testDivide() = runCompilerTest { + val expr = MstExtendedField { bindSymbol(x) / bindSymbol(x) }.compileToExpression(DoubleField) + assertEquals(1.0, expr(x to 2.0)) + } + + @Test + fun testPower() = runCompilerTest { + val expr = MstExtendedField { bindSymbol(x) pow 2 }.compileToExpression(DoubleField) + assertEquals(4.0, expr(x to 2.0)) + } +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt similarity index 76% rename from kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt index 406ba8c8d..ecf8ed367 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt @@ -3,11 +3,11 @@ * 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.wasm +package space.kscience.kmath.ast import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol +import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.IntRing import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke @@ -15,20 +15,16 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith -internal class TestWasmVariables { +internal class TestCompilerVariables { @Test - fun testVariable() { + fun testVariable() = runCompilerTest { val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing) assertEquals(1, expr(x to 1)) } @Test - fun testUndefinedVariableFails() { + fun testUndefinedVariableFails() = runCompilerTest { val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing) assertFailsWith { expr() } } - - private companion object { - private val x by symbol - } } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt similarity index 98% rename from kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt index 185659a1f..b838245e1 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt @@ -13,7 +13,7 @@ import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals -internal class ParserTest { +internal class TestParser { @Test fun evaluateParsedMst() { val mst = "2+2*(2+2)".parseMath() diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt similarity index 96% rename from kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt index 67d77839a..bb6bb3ce1 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt @@ -10,7 +10,7 @@ import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals -internal class ParserPrecedenceTest { +internal class TestParserPrecedence { @Test fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath())) diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt new file mode 100644 index 000000000..abeaed0f8 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -0,0 +1,25 @@ +/* + * 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.ast + +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.IntRing + +internal interface CompilerTestContext { + fun MST.compileToExpression(algebra: IntRing): Expression + fun MST.compile(algebra: IntRing, arguments: Map): Int + fun MST.compile(algebra: IntRing, vararg arguments: Pair): Int = compile(algebra, mapOf(*arguments)) + fun MST.compileToExpression(algebra: DoubleField): Expression + fun MST.compile(algebra: DoubleField, arguments: Map): Double + + fun MST.compile(algebra: DoubleField, vararg arguments: Pair): Double = + compile(algebra, mapOf(*arguments)) +} + +internal expect inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt new file mode 100644 index 000000000..6b5b1b83d --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -0,0 +1,39 @@ +/* + * 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.ast + +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.estree.compile as estreeCompile +import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression +import space.kscience.kmath.wasm.compile as wasmCompile +import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression + +private object WasmCompilerTestContext : CompilerTestContext { + override fun MST.compileToExpression(algebra: IntRing): Expression = wasmCompileToExpression(algebra) + override fun MST.compile(algebra: IntRing, arguments: Map): Int = wasmCompile(algebra, arguments) + override fun MST.compileToExpression(algebra: DoubleField): Expression = wasmCompileToExpression(algebra) + + override fun MST.compile(algebra: DoubleField, arguments: Map): Double = + wasmCompile(algebra, arguments) +} + +private object ESTreeCompilerTestContext : CompilerTestContext { + override fun MST.compileToExpression(algebra: IntRing): Expression = estreeCompileToExpression(algebra) + override fun MST.compile(algebra: IntRing, arguments: Map): Int = estreeCompile(algebra, arguments) + override fun MST.compileToExpression(algebra: DoubleField): Expression = estreeCompileToExpression(algebra) + + override fun MST.compile(algebra: DoubleField, arguments: Map): Double = + estreeCompile(algebra, arguments) +} + +internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) { + action(WasmCompilerTestContext) + action(ESTreeCompilerTestContext) +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt deleted file mode 100644 index d80318db8..000000000 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.estree - -import space.kscience.kmath.complex.ComplexField -import space.kscience.kmath.complex.toComplex -import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.ByteRing -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestESTreeConsistencyWithInterpreter { - @Test - fun mstSpace() { - val mst = MstGroup { - binaryOperationFunction("+")( - unaryOperationFunction("+")( - number(3.toByte()) - (number(2.toByte()) + (scale( - add(number(1), number(1)), - 2.0 - ) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) - ), - - number(1) - ) + bindSymbol(x) + zero - } - - assertEquals( - mst.interpret(MstGroup, x to MST.Numeric(2)), - mst.compile(MstGroup, x to MST.Numeric(2)) - ) - } - - @Test - fun byteRing() { - val mst = MstRing { - binaryOperationFunction("+")( - unaryOperationFunction("+")( - (bindSymbol(x) - (2.toByte() + (scale( - add(number(1), number(1)), - 2.0 - ) + 1.toByte()))) * 3.0 - 1.toByte() - ), - - number(1) - ) * number(2) - } - - assertEquals( - mst.interpret(ByteRing, x to 3.toByte()), - mst.compile(ByteRing, x to 3.toByte()) - ) - } - - @Test - fun doubleField() { - val mst = MstField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 - + number(1), - number(1) / 2 + number(2.0) * one - ) + zero - } - - assertEquals( - mst.interpret(DoubleField, x to 2.0), - mst.compile(DoubleField, x to 2.0) - ) - } - - @Test - fun complexField() { - val mst = MstField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 - + number(1), - number(1) / 2 + number(2.0) * one - ) + zero - } - - assertEquals( - mst.interpret(ComplexField, x to 2.0.toComplex()), - mst.compile(ComplexField, x to 2.0.toComplex()), - ) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt deleted file mode 100644 index a0b68a811..000000000 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.estree - -import space.kscience.kmath.expressions.MstField -import space.kscience.kmath.expressions.MstGroup -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestESTreeOperationsSupport { - @Test - fun testUnaryOperationInvocation() { - val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField) - val res = expression(x to 2.0) - assertEquals(-2.0, res) - } - - @Test - fun testBinaryOperationInvocation() { - val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField) - val res = expression(x to 2.0) - assertEquals(-1.0, res) - } - - @Test - fun testConstProductInvocation() { - val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0) - assertEquals(4.0, res) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt deleted file mode 100644 index 6756fd8c7..000000000 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.estree - -import space.kscience.kmath.expressions.MstExtendedField -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestESTreeSpecialization { - @Test - fun testUnaryPlus() { - val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(2.0, expr(x to 2.0)) - } - - @Test - fun testUnaryMinus() { - val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(-2.0, expr(x to 2.0)) - } - - @Test - fun testAdd() { - val expr = MstExtendedField { - binaryOperationFunction("+")( - bindSymbol(x), - bindSymbol(x), - ) - }.compileToExpression(DoubleField) - assertEquals(4.0, expr(x to 2.0)) - } - - @Test - fun testSine() { - val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(0.0, expr(x to 0.0)) - } - - @Test - fun testSubtract() { - val expr = MstExtendedField { - binaryOperationFunction("-")(bindSymbol(x), - bindSymbol(x)) - }.compileToExpression(DoubleField) - assertEquals(0.0, expr(x to 2.0)) - } - - @Test - fun testDivide() { - val expr = MstExtendedField { - binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x)) - }.compileToExpression(DoubleField) - assertEquals(1.0, expr(x to 2.0)) - } - - @Test - fun testPower() { - val expr = MstExtendedField { - binaryOperationFunction("pow")(bindSymbol(x), number(2)) - }.compileToExpression(DoubleField) - - assertEquals(4.0, expr(x to 2.0)) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt deleted file mode 100644 index e1830d9df..000000000 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.estree - -import space.kscience.kmath.expressions.MstRing -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.ByteRing -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - -internal class TestESTreeVariables { - @Test - fun testVariable() { - val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) - assertEquals(1.toByte(), expr(x to 1.toByte())) - } - - @Test - fun testUndefinedVariableFails() { - val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) - assertFailsWith { expr() } - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt deleted file mode 100644 index 2946592f4..000000000 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.wasm - -import space.kscience.kmath.expressions.MstField -import space.kscience.kmath.expressions.MstGroup -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestWasmOperationsSupport { - @Test - fun testUnaryOperationInvocation() { - val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField) - val res = expression(x to 2.0) - assertEquals(-2.0, res) - } - - @Test - fun testBinaryOperationInvocation() { - val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField) - val res = expression(x to 2.0) - assertEquals(-1.0, res) - } - - @Test - fun testConstProductInvocation() { - val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0) - assertEquals(4.0, res) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt deleted file mode 100644 index e1f7b603a..000000000 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.wasm - -import space.kscience.kmath.expressions.MstExtendedField -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestWasmSpecialization { - @Test - fun testUnaryPlus() { - val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(2.0, expr(x to 2.0)) - } - - @Test - fun testUnaryMinus() { - val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(-2.0, expr(x to 2.0)) - } - - @Test - fun testAdd() { - val expr = MstExtendedField { - binaryOperationFunction("+")( - bindSymbol(x), - bindSymbol(x), - ) - }.compileToExpression(DoubleField) - assertEquals(4.0, expr(x to 2.0)) - } - - @Test - fun testSine() { - val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(0.0, expr(x to 0.0)) - } - - @Test - fun testSubtract() { - val expr = MstExtendedField { - binaryOperationFunction("-")(bindSymbol(x), - bindSymbol(x)) - }.compileToExpression(DoubleField) - assertEquals(0.0, expr(x to 2.0)) - } - - @Test - fun testDivide() { - val expr = MstExtendedField { - binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x)) - }.compileToExpression(DoubleField) - assertEquals(1.0, expr(x to 2.0)) - } - - @Test - fun testPower() { - val expr = MstExtendedField { - binaryOperationFunction("pow")(bindSymbol(x), number(2)) - }.compileToExpression(DoubleField) - - assertEquals(4.0, expr(x to 2.0)) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt deleted file mode 100644 index f94d36602..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.asm - -import space.kscience.kmath.complex.ComplexField -import space.kscience.kmath.complex.toComplex -import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.ByteRing -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestAsmConsistencyWithInterpreter { - @Test - fun mstSpace() { - val mst = MstGroup { - binaryOperationFunction("+")( - unaryOperationFunction("+")( - number(3.toByte()) - (number(2.toByte()) + (scale( - add(number(1), number(1)), - 2.0 - ) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) - ), - - number(1) - ) + bindSymbol(x) + zero - } - - assertEquals( - mst.interpret(MstGroup, x to MST.Numeric(2)), - mst.compile(MstGroup, x to MST.Numeric(2)) - ) - } - - @Test - fun byteRing() { - val mst = MstRing { - binaryOperationFunction("+")( - unaryOperationFunction("+")( - (bindSymbol(x) - (2.toByte() + (scale( - add(number(1), number(1)), - 2.0 - ) + 1.toByte()))) * 3.0 - 1.toByte() - ), - - number(1) - ) * number(2) - } - - assertEquals( - mst.interpret(ByteRing, x to 3.toByte()), - mst.compile(ByteRing, x to 3.toByte()) - ) - } - - @Test - fun doubleField() { - val mst = MstField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 - + number(1), - number(1) / 2 + number(2.0) * one - ) + zero - } - - assertEquals( - mst.interpret(DoubleField, x to 2.0), - mst.compile(DoubleField, x to 2.0) - ) - } - - @Test - fun complexField() { - val mst = MstField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 - + number(1), - number(1) / 2 + number(2.0) * one - ) + zero - } - - assertEquals( - mst.interpret(ComplexField, x to 2.0.toComplex()), - mst.compile(ComplexField, x to 2.0.toComplex()) - ) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt deleted file mode 100644 index 147639f7c..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.asm - -import space.kscience.kmath.expressions.MstField -import space.kscience.kmath.expressions.MstGroup -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestAsmOperationsSupport { - @Test - fun testUnaryOperationInvocation() { - val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField) - val res = expression(x to 2.0) - assertEquals(-2.0, res) - } - - @Test - fun testBinaryOperationInvocation() { - val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField) - val res = expression(x to 2.0) - assertEquals(-1.0, res) - } - - @Test - fun testConstProductInvocation() { - val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0) - assertEquals(4.0, res) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt deleted file mode 100644 index 3a681e482..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.asm - -import space.kscience.kmath.expressions.MstExtendedField -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestAsmSpecialization { - @Test - fun testUnaryPlus() { - val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(2.0, expr(x to 2.0)) - } - - @Test - fun testUnaryMinus() { - val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(-2.0, expr(x to 2.0)) - } - - @Test - fun testAdd() { - val expr = MstExtendedField { - binaryOperationFunction("+")( - bindSymbol(x), - bindSymbol(x), - ) - }.compileToExpression(DoubleField) - assertEquals(4.0, expr(x to 2.0)) - } - - @Test - fun testSine() { - val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(0.0, expr(x to 0.0)) - } - - @Test - fun testSubtract() { - val expr = MstExtendedField { - binaryOperationFunction("-")(bindSymbol(x), - bindSymbol(x)) - }.compileToExpression(DoubleField) - assertEquals(0.0, expr(x to 2.0)) - } - - @Test - fun testDivide() { - val expr = MstExtendedField { - binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x)) - }.compileToExpression(DoubleField) - assertEquals(1.0, expr(x to 2.0)) - } - - @Test - fun testPower() { - val expr = MstExtendedField { - binaryOperationFunction("pow")(bindSymbol(x), number(2)) - }.compileToExpression(DoubleField) - - assertEquals(4.0, expr(x to 2.0)) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt deleted file mode 100644 index 89b98d720..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.asm - -import space.kscience.kmath.expressions.MstRing -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.ByteRing -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - -internal class TestAsmVariables { - @Test - fun testVariable() { - val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) - assertEquals(1.toByte(), expr(x to 1.toByte())) - } - - @Test - fun testUndefinedVariableFails() { - val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) - assertFailsWith { expr() } - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt new file mode 100644 index 000000000..607c5fdd6 --- /dev/null +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -0,0 +1,25 @@ +/* + * 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.ast + +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.asm.compile as asmCompile +import space.kscience.kmath.asm.compileToExpression as asmCompileToExpression + +private object AsmCompilerTestContext : CompilerTestContext { + override fun MST.compileToExpression(algebra: IntRing): Expression = asmCompileToExpression(algebra) + override fun MST.compile(algebra: IntRing, arguments: Map): Int = asmCompile(algebra, arguments) + override fun MST.compileToExpression(algebra: DoubleField): Expression = asmCompileToExpression(algebra) + + override fun MST.compile(algebra: DoubleField, arguments: Map): Double = + asmCompile(algebra, arguments) +} + +internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) = action(AsmCompilerTestContext) From 8898f908ef6cd6a3ce9458af13cc9abe160e8649 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Mon, 3 May 2021 18:45:18 +0300 Subject: [PATCH 169/211] statistic algebra --- .../tensors/api/StatisticTensorAlgebra.kt | 137 ++++++++++++++++++ .../algebras/DoubleStatisticTensorAlgebra.kt | 105 ++++++++++++++ 2 files changed, 242 insertions(+) create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt new file mode 100644 index 000000000..e3a2a1124 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt @@ -0,0 +1,137 @@ +/* + * 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.api + +import space.kscience.kmath.tensors.core.DoubleTensor + +/** + * Common algebra with statistics methods. Operates on [Tensor]. + * + * @param T the type of items closed under division in the tensors. + */ + +public interface StatisticTensorAlgebra: TensorAlgebra { + + /** + * Returns the minimum value of all elements in the input tensor. + * + * @return the minimum value of all elements in the input tensor. + */ + public fun Tensor.min(): Double + + /** + * Returns the minimum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the minimum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor + + /** + * Returns the maximum value of all elements in the input tensor. + * + * @return the maximum value of all elements in the input tensor. + */ + public fun Tensor.max(): Double + + /** + * Returns the maximum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the maximum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor + + /** + * Returns the sum of all elements in the input tensor. + * + * @return the sum of all elements in the input tensor. + */ + public fun Tensor.sum(): Double + + /** + * Returns the sum of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the sum of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor + + /** + * Returns the mean of all elements in the input tensor. + * + * @return the mean of all elements in the input tensor. + */ + public fun Tensor.mean(): Double + + /** + * Returns the mean of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the mean of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor + + /** + * Returns the standard deviation of all elements in the input tensor. + * + * @return the standard deviation of all elements in the input tensor. + */ + public fun Tensor.std(): Double + + /** + * Returns the standard deviation of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the standard deviation of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor + + /** + * Returns the variance of all elements in the input tensor. + * + * @return the variance of all elements in the input tensor. + */ + public fun Tensor.variance(): Double + + /** + * Returns the variance of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the variance of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt new file mode 100644 index 000000000..3914a0dfb --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt @@ -0,0 +1,105 @@ +/* + * 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.algebras + +import kotlin.math.sqrt + +import space.kscience.kmath.tensors.api.* +import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.max +import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.mean +import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.min +import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.sum +import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.variance + +public object DoubleStatisticTensorAlgebra : StatisticTensorAlgebra, DoubleTensorAlgebra() { + + private fun Tensor.fold(foldFunction: (DoubleArray) -> Double): Double { + return foldFunction(this.tensor.toDoubleArray()) + } + + private fun Tensor.foldDim( + foldFunction: (DoubleArray) -> Double, + dim: Int, + keepDim: Boolean + ): DoubleTensor { + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val resShape = if (keepDim) { + shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() + } else { + shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() + } + val resNumElements = resShape.reduce(Int::times) + val resTensor = DoubleTensor(resShape, DoubleArray(resNumElements) { 0.0 }, 0) + for (index in resTensor.linearStructure.indices()) { + val prefix = index.take(dim).toIntArray() + val suffix = index.takeLast(dimension - dim - 1).toIntArray() + resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i -> + this[prefix + intArrayOf(i) + suffix] + }) + } + + return resTensor + } + + override fun Tensor.min(): Double = this.fold { it.minOrNull()!! } + + override fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.minOrNull()!! }, dim, keepDim) + + override fun Tensor.max(): Double = this.fold { it.maxOrNull()!! } + + override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) + + override fun Tensor.sum(): Double = this.fold { it.sum() } + + override fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.sum() }, dim, keepDim) + + override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } + + override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + arr.sum() / shape[dim] + }, + dim, + keepDim + ) + + override fun Tensor.std(): Double = this.fold { arr -> + val mean = arr.sum() / tensor.numElements + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1)) + } + + override fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val mean = arr.sum() / shape[dim] + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) + }, + dim, + keepDim + ) + + override fun Tensor.variance(): Double = this.fold { arr -> + val mean = arr.sum() / tensor.numElements + arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1) + } + + override fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val mean = arr.sum() / shape[dim] + arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) + }, + dim, + keepDim + ) + +} \ No newline at end of file From 7f8914d8eacb6fb09469fa18b7328fa16bfc2208 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Mon, 3 May 2021 20:42:18 +0300 Subject: [PATCH 170/211] fixes --- .../kmath/tensors/api/StatisticTensorAlgebra.kt | 17 ++--------------- .../algebras/DoubleStatisticTensorAlgebra.kt | 7 +++---- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt index e3a2a1124..d0b17af97 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt @@ -9,16 +9,12 @@ import space.kscience.kmath.tensors.core.DoubleTensor /** * Common algebra with statistics methods. Operates on [Tensor]. - * - * @param T the type of items closed under division in the tensors. */ public interface StatisticTensorAlgebra: TensorAlgebra { /** * Returns the minimum value of all elements in the input tensor. - * - * @return the minimum value of all elements in the input tensor. */ public fun Tensor.min(): Double @@ -37,8 +33,6 @@ public interface StatisticTensorAlgebra: TensorAlgebra { /** * Returns the maximum value of all elements in the input tensor. - * - * @return the maximum value of all elements in the input tensor. */ public fun Tensor.max(): Double @@ -57,8 +51,6 @@ public interface StatisticTensorAlgebra: TensorAlgebra { /** * Returns the sum of all elements in the input tensor. - * - * @return the sum of all elements in the input tensor. */ public fun Tensor.sum(): Double @@ -77,8 +69,6 @@ public interface StatisticTensorAlgebra: TensorAlgebra { /** * Returns the mean of all elements in the input tensor. - * - * @return the mean of all elements in the input tensor. */ public fun Tensor.mean(): Double @@ -97,8 +87,6 @@ public interface StatisticTensorAlgebra: TensorAlgebra { /** * Returns the standard deviation of all elements in the input tensor. - * - * @return the standard deviation of all elements in the input tensor. */ public fun Tensor.std(): Double @@ -117,8 +105,6 @@ public interface StatisticTensorAlgebra: TensorAlgebra { /** * Returns the variance of all elements in the input tensor. - * - * @return the variance of all elements in the input tensor. */ public fun Tensor.variance(): Double @@ -134,4 +120,5 @@ public interface StatisticTensorAlgebra: TensorAlgebra { * @return the variance of each row of the input tensor in the given dimension [dim]. */ public fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor -} \ No newline at end of file + +} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt index 3914a0dfb..b455aff48 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt @@ -17,9 +17,8 @@ import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.v public object DoubleStatisticTensorAlgebra : StatisticTensorAlgebra, DoubleTensorAlgebra() { - private fun Tensor.fold(foldFunction: (DoubleArray) -> Double): Double { - return foldFunction(this.tensor.toDoubleArray()) - } + private fun Tensor.fold(foldFunction: (DoubleArray) -> Double): Double = + foldFunction(this.tensor.toDoubleArray()) private fun Tensor.foldDim( foldFunction: (DoubleArray) -> Double, @@ -102,4 +101,4 @@ public object DoubleStatisticTensorAlgebra : StatisticTensorAlgebra, Dou keepDim ) -} \ No newline at end of file +} From b59e48410f07ad203820b9c581b5e9997bff9784 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 3 May 2021 19:49:23 +0100 Subject: [PATCH 171/211] More basic functionality, tests to come --- .../tensors/api/AnalyticTensorAlgebra.kt | 95 +++++++++++++- .../tensors/api/StatisticTensorAlgebra.kt | 124 ------------------ .../kmath/tensors/api/TensorAlgebra.kt | 20 +++ .../algebras/DoubleAnalyticTensorAlgebra.kt | 54 ++++++++ .../algebras/DoubleStatisticTensorAlgebra.kt | 104 --------------- .../core/algebras/DoubleTensorAlgebra.kt | 36 ++++- 6 files changed, 202 insertions(+), 231 deletions(-) delete mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt delete mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index cd13e0752..f9b2df45c 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -5,14 +5,107 @@ package space.kscience.kmath.tensors.api + /** - * Element-wise analytic operations on [Tensor]. + * Analytic operations on [Tensor]. * * @param T the type of items closed under analytic functions in the tensors. */ public interface AnalyticTensorAlgebra : TensorPartialDivisionAlgebra { + + /** + * @return the minimum value of all elements in the input tensor. + */ + public fun Tensor.min(): T + + /** + * Returns the minimum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the minimum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.min(dim: Int, keepDim: Boolean): Tensor + + /** + * @return the maximum value of all elements in the input tensor. + */ + public fun Tensor.max(): T + + /** + * Returns the maximum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the maximum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.max(dim: Int, keepDim: Boolean): Tensor + + + /** + * @return the mean of all elements in the input tensor. + */ + public fun Tensor.mean(): T + + /** + * Returns the mean of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the mean of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.mean(dim: Int, keepDim: Boolean): Tensor + + /** + * @return the standard deviation of all elements in the input tensor. + */ + public fun Tensor.std(): T + + /** + * Returns the standard deviation of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the standard deviation of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.std(dim: Int, keepDim: Boolean): Tensor + + /** + * @return the variance of all elements in the input tensor. + */ + public fun Tensor.variance(): T + + /** + * Returns the variance of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the variance of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.variance(dim: Int, keepDim: Boolean): Tensor + //For information: https://pytorch.org/docs/stable/generated/torch.exp.html public fun Tensor.exp(): Tensor diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt deleted file mode 100644 index d0b17af97..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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.api - -import space.kscience.kmath.tensors.core.DoubleTensor - -/** - * Common algebra with statistics methods. Operates on [Tensor]. - */ - -public interface StatisticTensorAlgebra: TensorAlgebra { - - /** - * Returns the minimum value of all elements in the input tensor. - */ - public fun Tensor.min(): Double - - /** - * Returns the minimum value of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the minimum value of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor - - /** - * Returns the maximum value of all elements in the input tensor. - */ - public fun Tensor.max(): Double - - /** - * Returns the maximum value of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the maximum value of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor - - /** - * Returns the sum of all elements in the input tensor. - */ - public fun Tensor.sum(): Double - - /** - * Returns the sum of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the sum of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor - - /** - * Returns the mean of all elements in the input tensor. - */ - public fun Tensor.mean(): Double - - /** - * Returns the mean of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the mean of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor - - /** - * Returns the standard deviation of all elements in the input tensor. - */ - public fun Tensor.std(): Double - - /** - * Returns the standard deviation of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the standard deviation of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor - - /** - * Returns the variance of all elements in the input tensor. - */ - public fun Tensor.variance(): Double - - /** - * Returns the variance of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the variance of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor - -} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index b9c707c0b..b99f79e9a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -251,4 +251,24 @@ public interface TensorAlgebra: Algebra> { dim2: Int = -1 ): Tensor + /** + * @return the sum of all elements in the input tensor. + */ + public fun Tensor.sum(): T + + /** + * Returns the sum of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the sum of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.sum(dim: Int, keepDim: Boolean): Tensor + + + } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 9aa6f093e..547018498 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -14,6 +14,60 @@ import kotlin.math.* public object DoubleAnalyticTensorAlgebra : AnalyticTensorAlgebra, DoubleTensorAlgebra() { + + override fun Tensor.min(): Double = this.fold { it.minOrNull()!! } + + override fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.minOrNull()!! }, dim, keepDim) + + override fun Tensor.max(): Double = this.fold { it.maxOrNull()!! } + + override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) + + + override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } + + override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + arr.sum() / shape[dim] + }, + dim, + keepDim + ) + + override fun Tensor.std(): Double = this.fold { arr -> + val mean = arr.sum() / tensor.numElements + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1)) + } + + override fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val mean = arr.sum() / shape[dim] + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) + }, + dim, + keepDim + ) + + override fun Tensor.variance(): Double = this.fold { arr -> + val mean = arr.sum() / tensor.numElements + arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1) + } + + override fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val mean = arr.sum() / shape[dim] + arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) + }, + dim, + keepDim + ) + override fun Tensor.exp(): DoubleTensor = tensor.map(::exp) override fun Tensor.log(): DoubleTensor = tensor.map(::ln) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt deleted file mode 100644 index b455aff48..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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.algebras - -import kotlin.math.sqrt - -import space.kscience.kmath.tensors.api.* -import space.kscience.kmath.tensors.core.* -import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.max -import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.mean -import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.min -import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.sum -import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.variance - -public object DoubleStatisticTensorAlgebra : StatisticTensorAlgebra, DoubleTensorAlgebra() { - - private fun Tensor.fold(foldFunction: (DoubleArray) -> Double): Double = - foldFunction(this.tensor.toDoubleArray()) - - private fun Tensor.foldDim( - foldFunction: (DoubleArray) -> Double, - dim: Int, - keepDim: Boolean - ): DoubleTensor { - check(dim < dimension) { "Dimension $dim out of range $dimension" } - val resShape = if (keepDim) { - shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() - } else { - shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() - } - val resNumElements = resShape.reduce(Int::times) - val resTensor = DoubleTensor(resShape, DoubleArray(resNumElements) { 0.0 }, 0) - for (index in resTensor.linearStructure.indices()) { - val prefix = index.take(dim).toIntArray() - val suffix = index.takeLast(dimension - dim - 1).toIntArray() - resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i -> - this[prefix + intArrayOf(i) + suffix] - }) - } - - return resTensor - } - - override fun Tensor.min(): Double = this.fold { it.minOrNull()!! } - - override fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim({ x -> x.minOrNull()!! }, dim, keepDim) - - override fun Tensor.max(): Double = this.fold { it.maxOrNull()!! } - - override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) - - override fun Tensor.sum(): Double = this.fold { it.sum() } - - override fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim({ x -> x.sum() }, dim, keepDim) - - override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } - - override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim( - { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - arr.sum() / shape[dim] - }, - dim, - keepDim - ) - - override fun Tensor.std(): Double = this.fold { arr -> - val mean = arr.sum() / tensor.numElements - sqrt(arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1)) - } - - override fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( - { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - val mean = arr.sum() / shape[dim] - sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) - }, - dim, - keepDim - ) - - override fun Tensor.variance(): Double = this.fold { arr -> - val mean = arr.sum() / tensor.numElements - arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1) - } - - override fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( - { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - val mean = arr.sum() / shape[dim] - arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) - }, - dim, - keepDim - ) - -} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 4009f7b45..c0a6312a9 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -284,7 +284,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { val m1 = newThis.shape[newThis.shape.size - 1] val m2 = newOther.shape[newOther.shape.size - 2] val n = newOther.shape[newOther.shape.size - 1] - check (m1 == m2) { + check(m1 == m2) { throw RuntimeException("Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)") } @@ -403,7 +403,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun stack(tensors: List): 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"} + 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) @@ -415,4 +415,36 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun Tensor.rowsByIndices(indices: IntArray): DoubleTensor { return stack(indices.map { this[it] }) } + + internal fun Tensor.fold(foldFunction: (DoubleArray) -> Double): Double = + foldFunction(tensor.toDoubleArray()) + + internal fun Tensor.foldDim( + foldFunction: (DoubleArray) -> Double, + dim: Int, + keepDim: Boolean + ): DoubleTensor { + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val resShape = if (keepDim) { + shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() + } else { + shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() + } + val resNumElements = resShape.reduce(Int::times) + val resTensor = DoubleTensor(resShape, DoubleArray(resNumElements) { 0.0 }, 0) + for (index in resTensor.linearStructure.indices()) { + val prefix = index.take(dim).toIntArray() + val suffix = index.takeLast(dimension - dim - 1).toIntArray() + resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i -> + tensor[prefix + intArrayOf(i) + suffix] + }) + } + + return resTensor + } + + override fun Tensor.sum(): Double = tensor.fold { it.sum() } + + override fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.sum() }, dim, keepDim) } From 591b40872954e1c91d50f3d9998b7cd8e0ea550b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 3 May 2021 04:14:19 +0700 Subject: [PATCH 172/211] MST rendering: support infix division, use arcsin instead sin^-1 form for inverse trigonometric functions --- README.md | 14 ++- kmath-ast/README.md | 89 +++++++++++++-- kmath-ast/docs/README-TEMPLATE.md | 103 ++++++++++++++++-- .../ast/rendering/LatexSyntaxRenderer.kt | 6 +- .../ast/rendering/MathMLSyntaxRenderer.kt | 15 ++- .../kmath/ast/rendering/MathRenderer.kt | 2 + .../kmath/ast/rendering/MathSyntax.kt | 32 +++--- .../kscience/kmath/ast/rendering/features.kt | 72 +++++++++--- .../kscience/kmath/ast/rendering/stages.kt | 76 ++++++++++++- .../kmath/ast/rendering/TestFeatures.kt | 18 +-- .../kmath/ast/rendering/TestStages.kt | 6 + kmath-for-real/README.md | 4 +- kmath-functions/README.md | 4 +- 13 files changed, 363 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 773eb6398..97ce164e1 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ KMath is a modular library. Different modules provide different features with di * ### [kmath-ast](kmath-ast) > > -> **Maturity**: PROTOTYPE +> **Maturity**: EXPERIMENTAL > > **Features:** > - [expression-language](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser @@ -154,9 +154,9 @@ performance calculations to code generation. > **Maturity**: PROTOTYPE > > **Features:** -> - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix. -> - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix. -> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix. +> - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : Point implementations. +> - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : Matrix implementation. +> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : LinearSpace implementations.
@@ -200,6 +200,12 @@ One can still use generic algebras though. > **Maturity**: PROTOTYPE
+* ### [kmath-jupyter](kmath-jupyter) +> +> +> **Maturity**: PROTOTYPE +
+ * ### [kmath-kotlingrad](kmath-kotlingrad) > > diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 4de165e72..26ee98ba5 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -1,6 +1,6 @@ # Module kmath-ast -Abstract syntax tree expression representation and related optimizations. +Performance and visualization extensions to MST API. - [expression-language](src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser - [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler @@ -39,12 +39,16 @@ dependencies { ### On JVM -`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds -a special implementation of `Expression` with implemented `invoke` function. +`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds a +special implementation of `Expression` with implemented `invoke` function. For example, the following builder: ```kotlin +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.* +import space.kscience.kmath.asm.* + MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` @@ -54,6 +58,7 @@ MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) package space.kscience.kmath.asm.generated; import java.util.Map; + import kotlin.jvm.functions.Function2; import space.kscience.kmath.asm.internal.MapIntrinsics; import space.kscience.kmath.expressions.Expression; @@ -63,7 +68,7 @@ public final class AsmCompiledExpression_45045_0 implements Expression { private final Object[] constants; public final Double invoke(Map arguments) { - return (Double)((Function2)this.constants[0]).invoke((Double)MapIntrinsics.getOrFail(arguments, "x"), 2); + return (Double) ((Function2) this.constants[0]).invoke((Double) MapIntrinsics.getOrFail(arguments, "x"), 2); } public AsmCompiledExpression_45045_0(Object[] constants) { @@ -75,8 +80,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression { #### Known issues -- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid - class loading overhead. +- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class + loading overhead. - This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders. ### On JS @@ -84,6 +89,10 @@ public final class AsmCompiledExpression_45045_0 implements Expression { A similar feature is also available on JS. ```kotlin +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.* +import space.kscience.kmath.estree.* + MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` @@ -91,13 +100,16 @@ The code above returns expression implemented with such a JS function: ```js var executable = function (constants, arguments) { - return constants[1](constants[0](arguments, "x"), 2); + return constants[1](constants[0](arguments, "x"), 2); }; ``` -JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported. +JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. +Currently, only expressions inside `DoubleField` and `IntRing` are supported. ```kotlin +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.* import space.kscience.kmath.wasm.* MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) @@ -128,7 +140,9 @@ Example usage: ```kotlin import space.kscience.kmath.ast.* import space.kscience.kmath.ast.rendering.* +import space.kscience.kmath.misc.* +@OptIn(UnstableKMathAPI::class) public fun main() { val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath() val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst) @@ -144,13 +158,68 @@ public fun main() { Result LaTeX: -![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D) +![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{-12}) Result MathML (embedding MathML is not allowed by GitHub Markdown): +
+ ```html -ex-sin-12x2×1010+x3-12 + + + exp + + + + x + + + - + + + + + arcsin + + + 2 + + x + + + + 2 + × + + + 10 + + + 10 + + + + + + + x + + + 3 + + + + + + + - + 12 + + + + ``` +
+ It is also possible to create custom algorithms of render, and even add support of other markup languages (see API reference). diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index 1ecf477ef..80ea31642 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -1,6 +1,6 @@ # Module kmath-ast -Abstract syntax tree expression representation and related optimizations. +Performance and visualization extensions to MST API. ${features} @@ -10,12 +10,16 @@ ${artifact} ### On JVM -`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds -a special implementation of `Expression` with implemented `invoke` function. +`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds a +special implementation of `Expression` with implemented `invoke` function. For example, the following builder: ```kotlin +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.* +import space.kscience.kmath.asm.* + MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` @@ -25,6 +29,7 @@ MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) package space.kscience.kmath.asm.generated; import java.util.Map; + import kotlin.jvm.functions.Function2; import space.kscience.kmath.asm.internal.MapIntrinsics; import space.kscience.kmath.expressions.Expression; @@ -34,7 +39,7 @@ public final class AsmCompiledExpression_45045_0 implements Expression { private final Object[] constants; public final Double invoke(Map arguments) { - return (Double)((Function2)this.constants[0]).invoke((Double)MapIntrinsics.getOrFail(arguments, "x"), 2); + return (Double) ((Function2) this.constants[0]).invoke((Double) MapIntrinsics.getOrFail(arguments, "x"), 2); } public AsmCompiledExpression_45045_0(Object[] constants) { @@ -46,8 +51,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression { #### Known issues -- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid - class loading overhead. +- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class + loading overhead. - This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders. ### On JS @@ -55,6 +60,10 @@ public final class AsmCompiledExpression_45045_0 implements Expression { A similar feature is also available on JS. ```kotlin +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.* +import space.kscience.kmath.estree.* + MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` @@ -62,13 +71,16 @@ The code above returns expression implemented with such a JS function: ```js var executable = function (constants, arguments) { - return constants[1](constants[0](arguments, "x"), 2); + return constants[1](constants[0](arguments, "x"), 2); }; ``` -JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported. +JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. +Currently, only expressions inside `DoubleField` and `IntRing` are supported. ```kotlin +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.* import space.kscience.kmath.wasm.* MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) @@ -99,9 +111,11 @@ Example usage: ```kotlin import space.kscience.kmath.ast.* import space.kscience.kmath.ast.rendering.* +import space.kscience.kmath.misc.* +@OptIn(UnstableKMathAPI::class) public fun main() { - val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath() + val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(12)+x^(2/3)".parseMath() val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst) val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax) println("LaTeX:") @@ -115,13 +129,78 @@ public fun main() { Result LaTeX: -![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D) +![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3}) -Result MathML (embedding MathML is not allowed by GitHub Markdown): +Result MathML (can be used with MathJax or other renderers): + +
```html -ex-sin-12x2×1010+x3-12 + + + exp + + + + x + + + - + + + + + arcsin + + + 2 + + x + + + + 2 + × + + + 10 + + + 10 + + + + + + + x + + + 3 + + + + + + + 12 + + + + + + + x + + + 2 + / + 3 + + + + ``` +
+ It is also possible to create custom algorithms of render, and even add support of other markup languages (see API reference). diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt index 5909f1f9d..01717b0f9 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -118,7 +118,11 @@ public object LatexSyntaxRenderer : SyntaxRenderer { render(node.right) } - is FractionSyntax -> { + is FractionSyntax -> if (node.infix) { + render(node.left) + append('/') + render(node.right) + } else { append("\\frac{") render(node.left) append("}{") diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index 5b44e660d..cda8e2322 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -133,14 +133,13 @@ public object MathMLSyntaxRenderer : SyntaxRenderer { render(node.right) } - is FractionSyntax -> tag("mfrac") { - tag("mrow") { - render(node.left) - } - - tag("mrow") { - render(node.right) - } + is FractionSyntax -> if (node.infix) { + render(node.left) + tag("mo") { append('/') } + render(node.right) + } else tag("mfrac") { + tag("mrow") { render(node.left) } + tag("mrow") { render(node.right) } } is RadicalWithIndexSyntax -> tag("mroot") { diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index 6b22ac519..c33f95483 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -89,6 +89,7 @@ public open class FeaturedMathRendererWithPostProcess( SquareRoot.Default, Exponent.Default, InverseTrigonometricOperations.Default, + InverseHyperbolicOperations.Default, // Fallback option for unknown operations - printing them as operator BinaryOperator.Default, @@ -105,6 +106,7 @@ public open class FeaturedMathRendererWithPostProcess( ), listOf( BetterExponent, + BetterFraction, SimplifyParentheses.Default, BetterMultiplication, ), diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt index 3c023e342..a71985fbc 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -102,7 +102,7 @@ public data class SymbolSyntax(public var string: String) : TerminalSyntax() public data class OperatorNameSyntax(public var name: String) : TerminalSyntax() /** - * Represents a usage of special symbols. + * Represents a usage of special symbols (e.g., *∞*). * * @property kind The kind of symbol. * @author Iaroslav Postovalov @@ -143,7 +143,7 @@ public data class OperandSyntax( } /** - * Represents unary, prefix operator syntax (like f x). + * Represents unary, prefix operator syntax (like *f(x)*). * * @property prefix The prefix. * @author Iaroslav Postovalov @@ -160,7 +160,7 @@ public data class UnaryOperatorSyntax( } /** - * Represents prefix, unary plus operator. + * Represents prefix, unary plus operator (*+x*). * * @author Iaroslav Postovalov */ @@ -175,7 +175,7 @@ public data class UnaryPlusSyntax( } /** - * Represents prefix, unary minus operator. + * Represents prefix, unary minus operator (*-x*). * * @author Iaroslav Postovalov */ @@ -190,7 +190,7 @@ public data class UnaryMinusSyntax( } /** - * Represents radical with a node inside it. + * Represents radical with a node inside it (*√x*). * * @property operand The radicand. * @author Iaroslav Postovalov @@ -225,7 +225,7 @@ public data class ExponentSyntax( } /** - * Represents a syntax node with superscript (usually, for exponentiation). + * Represents a syntax node with superscript (*x2*). * * @property left The node. * @property right The superscript. @@ -244,7 +244,7 @@ public data class SuperscriptSyntax( } /** - * Represents a syntax node with subscript. + * Represents a syntax node with subscript (*xi*). * * @property left The node. * @property right The subscript. @@ -263,7 +263,7 @@ public data class SubscriptSyntax( } /** - * Represents binary, prefix operator syntax (like f(a, b)). + * Represents binary, prefix operator syntax (like *f(a, b)*). * * @property prefix The prefix. * @author Iaroslav Postovalov @@ -282,7 +282,7 @@ public data class BinaryOperatorSyntax( } /** - * Represents binary, infix addition. + * Represents binary, infix addition (*42 + 42*). * * @param left The augend. * @param right The addend. @@ -301,7 +301,7 @@ public data class BinaryPlusSyntax( } /** - * Represents binary, infix subtraction. + * Represents binary, infix subtraction (*42 - 42*). * * @param left The minuend. * @param right The subtrahend. @@ -324,13 +324,15 @@ public data class BinaryMinusSyntax( * * @property left The numerator. * @property right The denominator. + * @property infix Whether infix (*1 / 2*) or normal (*½*) fraction should be made. * @author Iaroslav Postovalov */ @UnstableKMathAPI public data class FractionSyntax( public override val operation: String, - public override val left: MathSyntax, - public override val right: MathSyntax, + public override val left: OperandSyntax, + public override val right: OperandSyntax, + public var infix: Boolean, ) : BinarySyntax() { init { left.parent = this @@ -339,7 +341,7 @@ public data class FractionSyntax( } /** - * Represents radical syntax with index. + * Represents radical syntax with index (*3√x*). * * @property left The index. * @property right The radicand. @@ -358,11 +360,11 @@ public data class RadicalWithIndexSyntax( } /** - * Represents binary, infix multiplication in the form of coefficient (2 x) or with operator (x×2). + * Represents binary, infix multiplication in the form of coefficient (*2 x*) or with operator (*x × 2*). * * @property left The multiplicand. * @property right The multiplier. - * @property times whether the times (×) symbol should be used. + * @property times Whether the times (×) symbol should be used. * @author Iaroslav Postovalov */ @UnstableKMathAPI diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index c1b513345..ac716f9ff 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -54,6 +54,7 @@ else * *('-'? (DIGIT+ ('.' DIGIT+)? ('E' '-'? DIGIT+)? | 'Infinity')) | 'NaN'*. * * @property types The suitable types. + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class PrettyPrintFloats(public val types: Set>) : RenderFeature { @@ -113,6 +114,7 @@ public class PrettyPrintFloats(public val types: Set>) : Rend * Special printing for numeric types which are printed in form of *'-'? DIGIT+*. * * @property types The suitable types. + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class PrettyPrintIntegers(public val types: Set>) : RenderFeature { @@ -135,6 +137,7 @@ public class PrettyPrintIntegers(public val types: Set>) : Re * Special printing for symbols meaning Pi. * * @property symbols The allowed symbols. + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class PrettyPrintPi(public val symbols: Set) : RenderFeature { @@ -157,6 +160,7 @@ public class PrettyPrintPi(public val symbols: Set) : RenderFeature { * not [MST.Unary]. * * @param operations the allowed operations. If `null`, any operation is accepted. + * @author Iaroslav Postovalov */ @UnstableKMathAPI public abstract class Unary(public val operations: Collection?) : RenderFeature { @@ -177,6 +181,7 @@ public abstract class Unary(public val operations: Collection?) : Render * not [MST.Binary]. * * @property operations the allowed operations. If `null`, any operation is accepted. + * @author Iaroslav Postovalov */ @UnstableKMathAPI public abstract class Binary(public val operations: Collection?) : RenderFeature { @@ -193,6 +198,8 @@ public abstract class Binary(public val operations: Collection?) : Rende /** * Handles binary nodes by producing [BinaryPlusSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class BinaryPlus(operations: Collection?) : Binary(operations) { @@ -213,6 +220,8 @@ public class BinaryPlus(operations: Collection?) : Binary(operations) { /** * Handles binary nodes by producing [BinaryMinusSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class BinaryMinus(operations: Collection?) : Binary(operations) { @@ -233,6 +242,8 @@ public class BinaryMinus(operations: Collection?) : Binary(operations) { /** * Handles unary nodes by producing [UnaryPlusSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class UnaryPlus(operations: Collection?) : Unary(operations) { @@ -251,6 +262,8 @@ public class UnaryPlus(operations: Collection?) : Unary(operations) { /** * Handles binary nodes by producing [UnaryMinusSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class UnaryMinus(operations: Collection?) : Unary(operations) { @@ -269,13 +282,16 @@ public class UnaryMinus(operations: Collection?) : Unary(operations) { /** * Handles binary nodes by producing [FractionSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class Fraction(operations: Collection?) : Binary(operations) { public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = FractionSyntax( operation = node.operation, - left = parent.render(node.left), - right = parent.render(node.right), + left = OperandSyntax(operand = parent.render(node.left), parentheses = true), + right = OperandSyntax(operand = parent.render(node.right), parentheses = true), + infix = true, ) public companion object { @@ -288,6 +304,8 @@ public class Fraction(operations: Collection?) : Binary(operations) { /** * Handles binary nodes by producing [BinaryOperatorSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class BinaryOperator(operations: Collection?) : Binary(operations) { @@ -309,6 +327,8 @@ public class BinaryOperator(operations: Collection?) : Binary(operations /** * Handles unary nodes by producing [UnaryOperatorSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class UnaryOperator(operations: Collection?) : Unary(operations) { @@ -329,6 +349,8 @@ public class UnaryOperator(operations: Collection?) : Unary(operations) /** * Handles binary nodes by producing [SuperscriptSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class Power(operations: Collection?) : Binary(operations) { @@ -365,6 +387,8 @@ public class SquareRoot(operations: Collection?) : Unary(operations) { /** * Handles unary nodes by producing [ExponentSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class Exponent(operations: Collection?) : Unary(operations) { @@ -384,6 +408,8 @@ public class Exponent(operations: Collection?) : Unary(operations) { /** * Handles binary nodes by producing [MultiplicationSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class Multiplication(operations: Collection?) : Binary(operations) { @@ -404,36 +430,52 @@ public class Multiplication(operations: Collection?) : Binary(operations } /** - * Handles binary nodes by producing inverse [UnaryOperatorSyntax] (like *sin-1*) with removing the `a` - * prefix of operation ID. + * Handles binary nodes by producing inverse [UnaryOperatorSyntax] with *arc* prefix instead of *a*. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class InverseTrigonometricOperations(operations: Collection?) : Unary(operations) { public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = UnaryOperatorSyntax( operation = node.operation, - prefix = SuperscriptSyntax( - operation = PowerOperations.POW_OPERATION, - left = OperatorNameSyntax(name = node.operation.removePrefix("a")), - right = UnaryMinusSyntax( - operation = GroupOperations.MINUS_OPERATION, - operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true), - ), - ), + prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "arc")), operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), ) public companion object { /** * The default instance configured with [TrigonometricOperations.ACOS_OPERATION], - * [TrigonometricOperations.ASIN_OPERATION], [TrigonometricOperations.ATAN_OPERATION], - * [ExponentialOperations.ACOSH_OPERATION], [ExponentialOperations.ASINH_OPERATION], and - * [ExponentialOperations.ATANH_OPERATION]. + * [TrigonometricOperations.ASIN_OPERATION], [TrigonometricOperations.ATAN_OPERATION]. */ public val Default: InverseTrigonometricOperations = InverseTrigonometricOperations(setOf( TrigonometricOperations.ACOS_OPERATION, TrigonometricOperations.ASIN_OPERATION, TrigonometricOperations.ATAN_OPERATION, + )) + } +} + +/** + * Handles binary nodes by producing inverse [UnaryOperatorSyntax] with *ar* prefix instead of *a*. + * + * @author Iaroslav Postovalov + */ +@UnstableKMathAPI +public class InverseHyperbolicOperations(operations: Collection?) : Unary(operations) { + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = + UnaryOperatorSyntax( + operation = node.operation, + prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "ar")), + operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), + ) + + public companion object { + /** + * The default instance configured with [ExponentialOperations.ACOSH_OPERATION], + * [ExponentialOperations.ASINH_OPERATION], and [ExponentialOperations.ATANH_OPERATION]. + */ + public val Default: InverseHyperbolicOperations = InverseHyperbolicOperations(setOf( ExponentialOperations.ACOSH_OPERATION, ExponentialOperations.ASINH_OPERATION, ExponentialOperations.ATANH_OPERATION, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt index 7eb75b9ff..1f31af853 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt @@ -83,6 +83,75 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro } } +/** + * Chooses [FractionSyntax.infix] depending on the context. + * + * @author Iaroslav Postovalov + */ +@UnstableKMathAPI +public object BetterFraction : FeaturedMathRendererWithPostProcess.PostProcessStage { + private fun perform0(node: MathSyntax, infix: Boolean = false): Unit = when (node) { + is NumberSyntax -> Unit + is SymbolSyntax -> Unit + is OperatorNameSyntax -> Unit + is SpecialSymbolSyntax -> Unit + is OperandSyntax -> perform0(node.operand, infix) + + is UnaryOperatorSyntax -> { + perform0(node.prefix, infix) + perform0(node.operand, infix) + } + + is UnaryPlusSyntax -> perform0(node.operand, infix) + is UnaryMinusSyntax -> perform0(node.operand, infix) + is RadicalSyntax -> perform0(node.operand, infix) + is ExponentSyntax -> perform0(node.operand, infix) + + is SuperscriptSyntax -> { + perform0(node.left, true) + perform0(node.right, true) + } + + is SubscriptSyntax -> { + perform0(node.left, true) + perform0(node.right, true) + } + + is BinaryOperatorSyntax -> { + perform0(node.prefix, infix) + perform0(node.left, infix) + perform0(node.right, infix) + } + + is BinaryPlusSyntax -> { + perform0(node.left, infix) + perform0(node.right, infix) + } + + is BinaryMinusSyntax -> { + perform0(node.left, infix) + perform0(node.right, infix) + } + + is FractionSyntax -> { + node.infix = infix + perform0(node.left, infix) + perform0(node.right, infix) + } + + is RadicalWithIndexSyntax -> { + perform0(node.left, true) + perform0(node.right, true) + } + + is MultiplicationSyntax -> { + perform0(node.left, infix) + perform0(node.right, infix) + } + } + + public override fun perform(node: MathSyntax): Unit = perform0(node) +} /** * Applies [ExponentSyntax.useOperatorForm] to [ExponentSyntax] when the operand contains a fraction, a @@ -102,7 +171,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt is UnaryOperatorSyntax -> perform0(node.prefix) || perform0(node.operand) is UnaryPlusSyntax -> perform0(node.operand) is UnaryMinusSyntax -> perform0(node.operand) - is RadicalSyntax -> perform0(node.operand) + is RadicalSyntax -> true is ExponentSyntax -> { val r = perform0(node.operand) @@ -116,7 +185,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt is BinaryPlusSyntax -> perform0(node.left) || perform0(node.right) is BinaryMinusSyntax -> perform0(node.left) || perform0(node.right) is FractionSyntax -> true - is RadicalWithIndexSyntax -> perform0(node.left) || perform0(node.right) + is RadicalWithIndexSyntax -> true is MultiplicationSyntax -> perform0(node.left) || perform0(node.right) } } @@ -163,8 +232,11 @@ public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> val isInsideExpOperator = node.parent is ExponentSyntax && (node.parent as ExponentSyntax).useOperatorForm + val isOnOrUnderNormalFraction = node.parent is FractionSyntax && !((node.parent as FractionSyntax).infix) + node.parentheses = !isRightOfSuperscript && (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax || isInsideExpOperator) + && !isOnOrUnderNormalFraction perform(node.operand) } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt index 1ab20ed85..a40c785b9 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt @@ -99,13 +99,17 @@ internal class TestFeatures { fun multiplication() = testLatex("x*1", "x\\times1") @Test - fun inverseTrigonometry() { - testLatex("asin(x)", "\\operatorname{sin}^{-1}\\,\\left(x\\right)") - testLatex("asinh(x)", "\\operatorname{sinh}^{-1}\\,\\left(x\\right)") - testLatex("acos(x)", "\\operatorname{cos}^{-1}\\,\\left(x\\right)") - testLatex("acosh(x)", "\\operatorname{cosh}^{-1}\\,\\left(x\\right)") - testLatex("atan(x)", "\\operatorname{tan}^{-1}\\,\\left(x\\right)") - testLatex("atanh(x)", "\\operatorname{tanh}^{-1}\\,\\left(x\\right)") + fun inverseTrigonometric() { + testLatex("asin(x)", "\\operatorname{arcsin}\\,\\left(x\\right)") + testLatex("acos(x)", "\\operatorname{arccos}\\,\\left(x\\right)") + testLatex("atan(x)", "\\operatorname{arctan}\\,\\left(x\\right)") + } + + @Test + fun inverseHyperbolic() { + testLatex("asinh(x)", "\\operatorname{arsinh}\\,\\left(x\\right)") + testLatex("acosh(x)", "\\operatorname{arcosh}\\,\\left(x\\right)") + testLatex("atanh(x)", "\\operatorname{artanh}\\,\\left(x\\right)") } // @Test diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt index 599e43eb2..09ec127c7 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt @@ -37,4 +37,10 @@ internal class TestStages { testLatex("exp(x/2)", "\\operatorname{exp}\\,\\left(\\frac{x}{2}\\right)") testLatex("exp(x^2)", "\\operatorname{exp}\\,\\left(x^{2}\\right)") } + + @Test + fun fraction() { + testLatex("x/y", "\\frac{x}{y}") + testLatex("x^(x/y)", "x^{x/y}") + } } diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 46bf657c3..a77f9d98b 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -15,7 +15,7 @@ The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-d ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -26,7 +26,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + mavenCentral() } dependencies { diff --git a/kmath-functions/README.md b/kmath-functions/README.md index c7c30f1a1..2090ede3e 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -17,7 +17,7 @@ The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0- ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -28,7 +28,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + mavenCentral() } dependencies { From d0281871fac1f59f4218ea1e4440f1991e742bb1 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 5 May 2021 14:27:01 +0300 Subject: [PATCH 173/211] analytic tests and examples --- .../kmath/tensors/DataSetNormalization.kt | 46 ++++++ .../tensors/api/AnalyticTensorAlgebra.kt | 3 +- .../algebras/DoubleAnalyticTensorAlgebra.kt | 3 +- .../core/TestDoubleAnalyticTensorAlgebra.kt | 152 ++++++++++++++++-- 4 files changed, 186 insertions(+), 18 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt new file mode 100644 index 000000000..4d53d940b --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt @@ -0,0 +1,46 @@ +/* + * 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 + +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra + +// Dataset normalization + +fun main() { + + // work in context with analytic methods + DoubleAnalyticTensorAlgebra { + // take dataset of 5-element vectors from normal distribution + val dataset = randomNormal(intArrayOf(100, 5)) * 1.5 // all elements from N(0, 1.5) + BroadcastDoubleTensorAlgebra { + dataset += fromArray( + intArrayOf(5), + doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means + ) + } + + // find out mean and standard deviation of each column + val mean = dataset.mean(0, false) + val std = dataset.std(0, false) + + println("Mean:\n$mean") + println("Standard deviation:\n$std") + + // also we can calculate other statistic as minimum and maximum of rows + println("Minimum:\n${dataset.min(0, false)}") + println("Maximum:\n${dataset.max(0, false)}") + + // now we can scale dataset with mean normalization + val datasetScaled = BroadcastDoubleTensorAlgebra { (dataset - mean) / std } + + // find out mean and std of scaled dataset + + println("Mean of scaled:\n${datasetScaled.mean(0, false)}") + println("Mean of scaled:\n${datasetScaled.std(0, false)}") + } +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index f9b2df45c..7784bfa45 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -51,7 +51,6 @@ public interface AnalyticTensorAlgebra : */ public fun Tensor.max(dim: Int, keepDim: Boolean): Tensor - /** * @return the mean of all elements in the input tensor. */ @@ -110,7 +109,7 @@ public interface AnalyticTensorAlgebra : public fun Tensor.exp(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.log.html - public fun Tensor.log(): Tensor + public fun Tensor.ln(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.sqrt.html public fun Tensor.sqrt(): Tensor diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 547018498..5580f845f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -25,7 +25,6 @@ public object DoubleAnalyticTensorAlgebra : override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) - override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = @@ -70,7 +69,7 @@ public object DoubleAnalyticTensorAlgebra : override fun Tensor.exp(): DoubleTensor = tensor.map(::exp) - override fun Tensor.log(): DoubleTensor = tensor.map(::ln) + override fun Tensor.ln(): DoubleTensor = tensor.map(::ln) override fun Tensor.sqrt(): DoubleTensor = tensor.map(::sqrt) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 835b8a08a..bebd65dc5 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -2,35 +2,159 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra -import kotlin.math.abs -import kotlin.math.exp +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.tan +import kotlin.math.* import kotlin.test.Test import kotlin.test.assertTrue internal class TestDoubleAnalyticTensorAlgebra { val shape = intArrayOf(2, 1, 3, 2) - val buffer = doubleArrayOf(27.1, 20.0, 19.84, 23.123, 0.0, 1.0, 3.23, 133.7, 25.3, 100.3, 11.0, 12.012) + val buffer = doubleArrayOf( + 27.1, 20.0, 19.84, + 23.123, 3.0, 2.0, + + 3.23, 133.7, 25.3, + 100.3, 11.0, 12.012 + ) val tensor = DoubleTensor(shape, buffer) fun DoubleArray.fmap(transform: (Double) -> Double): DoubleArray { return this.map(transform).toDoubleArray() } - fun DoubleArray.epsEqual(other: DoubleArray, eps: Double = 1e-5): Boolean { - for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) { - if (abs(elem1 - elem2) > eps) { - return false - } - } - return true + fun expectedTensor(transform: (Double) -> Double): DoubleTensor { + return DoubleTensor(shape, buffer.fmap(transform)) } @Test fun testExp() = DoubleAnalyticTensorAlgebra { - tensor.exp().let { - assertTrue { shape contentEquals it.shape } - assertTrue { buffer.fmap(::exp).epsEqual(it.mutableBuffer.array())} - } + assertTrue { tensor.exp() eq expectedTensor(::exp) } } + + @Test + fun testLog() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.ln() eq expectedTensor(::ln) } + } + + @Test + fun testSqrt() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.sqrt() eq expectedTensor(::sqrt) } + } + + @Test + fun testCos() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.cos() eq expectedTensor(::cos) } + } + + + @Test + fun testCosh() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.cosh() eq expectedTensor(::cosh) } + } + + @Test + fun testAcosh() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.acosh() eq expectedTensor(::acosh) } + } + + @Test + fun testSin() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.sin() eq expectedTensor(::sin) } + } + + @Test + fun testSinh() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.sinh() eq expectedTensor(::sinh) } + } + + @Test + fun testAsinh() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.asinh() eq expectedTensor(::asinh) } + } + + @Test + fun testTan() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.tan() eq expectedTensor(::tan) } + } + + @Test + fun testAtan() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.atan() eq expectedTensor(::atan) } + } + + @Test + fun testTanh() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.tanh() eq expectedTensor(::tanh) } + } + + @Test + fun testCeil() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.ceil() eq expectedTensor(::ceil) } + } + + @Test + fun testFloor() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.floor() eq expectedTensor(::floor) } + } + + val shape2 = intArrayOf(2, 2) + val buffer2 = doubleArrayOf( + 1.0, 2.0, + -3.0, 4.0 + ) + val tensor2 = DoubleTensor(shape2, buffer2) + + @Test + fun testMin() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor2.min() == -3.0 } + assertTrue { tensor2.min(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(-3.0, 2.0) + )} + assertTrue { tensor2.min(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(1.0, -3.0) + )} + } + + @Test + fun testMax() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor2.max() == 4.0 } + assertTrue { tensor2.max(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(1.0, 4.0) + )} + assertTrue { tensor2.max(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(2.0, 4.0) + )} + } + + @Test + fun testSum() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor2.sum() == 4.0 } + assertTrue { tensor2.sum(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(-2.0, 6.0) + )} + assertTrue { tensor2.sum(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(3.0, 1.0) + )} + } + + @Test + fun testMean() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor2.mean() == 1.0 } + assertTrue { tensor2.mean(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(-1.0, 3.0) + )} + assertTrue { tensor2.mean(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(1.5, 0.5) + )} + } + } \ No newline at end of file From 218b81a242b79baba4cb8db82887e4fa90556b05 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 5 May 2021 16:11:46 +0100 Subject: [PATCH 174/211] Min max refactor --- .../tensors/api/AnalyticTensorAlgebra.kt | 37 ------------------- .../kmath/tensors/api/TensorAlgebra.kt | 35 ++++++++++++++++++ .../algebras/DoubleAnalyticTensorAlgebra.kt | 10 ----- .../core/algebras/DoubleTensorAlgebra.kt | 14 +++++++ .../core/TestDoubleAnalyticTensorAlgebra.kt | 8 ++-- 5 files changed, 53 insertions(+), 51 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 7784bfa45..aa5678b31 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -14,43 +14,6 @@ package space.kscience.kmath.tensors.api public interface AnalyticTensorAlgebra : TensorPartialDivisionAlgebra { - - /** - * @return the minimum value of all elements in the input tensor. - */ - public fun Tensor.min(): T - - /** - * Returns the minimum value of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the minimum value of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.min(dim: Int, keepDim: Boolean): Tensor - - /** - * @return the maximum value of all elements in the input tensor. - */ - public fun Tensor.max(): T - - /** - * Returns the maximum value of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the maximum value of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.max(dim: Int, keepDim: Boolean): Tensor - /** * @return the mean of all elements in the input tensor. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index b99f79e9a..b0a0f9618 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -269,6 +269,41 @@ public interface TensorAlgebra: Algebra> { */ public fun Tensor.sum(dim: Int, keepDim: Boolean): Tensor + /** + * @return the minimum value of all elements in the input tensor. + */ + public fun Tensor.min(): T + + /** + * Returns the minimum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the minimum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.min(dim: Int, keepDim: Boolean): Tensor + + /** + * @return the maximum value of all elements in the input tensor. + */ + public fun Tensor.max(): T + + /** + * Returns the maximum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the maximum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.max(dim: Int, keepDim: Boolean): Tensor } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 5580f845f..4a1f360e3 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -15,16 +15,6 @@ public object DoubleAnalyticTensorAlgebra : AnalyticTensorAlgebra, DoubleTensorAlgebra() { - override fun Tensor.min(): Double = this.fold { it.minOrNull()!! } - - override fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim({ x -> x.minOrNull()!! }, dim, keepDim) - - override fun Tensor.max(): Double = this.fold { it.maxOrNull()!! } - - override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) - override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index c0a6312a9..d220bdd9a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -9,6 +9,8 @@ import space.kscience.kmath.nd.as2D import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.fold +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.foldDim import space.kscience.kmath.tensors.core.broadcastOuterTensors import space.kscience.kmath.tensors.core.checkBufferShapeConsistency import space.kscience.kmath.tensors.core.checkEmptyDoubleBuffer @@ -447,4 +449,16 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor = foldDim({ x -> x.sum() }, dim, keepDim) + + + override fun Tensor.min(): Double = this.fold { it.minOrNull()!! } + + override fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.minOrNull()!! }, dim, keepDim) + + override fun Tensor.max(): Double = this.fold { it.maxOrNull()!! } + + override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) + } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index bebd65dc5..3ea19da26 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.tan +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.math.* import kotlin.test.Test import kotlin.test.assertTrue @@ -106,7 +106,7 @@ internal class TestDoubleAnalyticTensorAlgebra { val tensor2 = DoubleTensor(shape2, buffer2) @Test - fun testMin() = DoubleAnalyticTensorAlgebra { + fun testMin() = DoubleTensorAlgebra { assertTrue { tensor2.min() == -3.0 } assertTrue { tensor2.min(0, true) eq fromArray( intArrayOf(1, 2), @@ -119,7 +119,7 @@ internal class TestDoubleAnalyticTensorAlgebra { } @Test - fun testMax() = DoubleAnalyticTensorAlgebra { + fun testMax() = DoubleTensorAlgebra { assertTrue { tensor2.max() == 4.0 } assertTrue { tensor2.max(0, true) eq fromArray( intArrayOf(1, 2), @@ -132,7 +132,7 @@ internal class TestDoubleAnalyticTensorAlgebra { } @Test - fun testSum() = DoubleAnalyticTensorAlgebra { + fun testSum() = DoubleTensorAlgebra { assertTrue { tensor2.sum() == 4.0 } assertTrue { tensor2.sum(0, true) eq fromArray( intArrayOf(1, 2), From 431db00f1ac9da54b65d00a09fa6f7b33c150942 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 5 May 2021 16:35:26 +0100 Subject: [PATCH 175/211] refactor tests --- .../kmath/tensors/core/TestBroadcasting.kt | 12 ++++---- .../kmath/tensors/core/TestDoubleTensor.kt | 8 ++--- .../tensors/core/TestDoubleTensorAlgebra.kt | 30 ++++++------------- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 1564b85c9..6e3b4df60 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -9,7 +9,7 @@ import kotlin.test.assertTrue internal class TestBroadcasting { @Test - fun broadcastShapes() = DoubleTensorAlgebra { + fun testBroadcastShapes() = DoubleTensorAlgebra { assertTrue( broadcastShapes( intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) @@ -24,7 +24,7 @@ internal class TestBroadcasting { } @Test - fun broadcastTo() = DoubleTensorAlgebra { + fun testBroadcastTo() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) @@ -34,7 +34,7 @@ internal class TestBroadcasting { } @Test - fun broadcastTensors() = DoubleTensorAlgebra { + fun testBroadcastTensors() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -51,7 +51,7 @@ internal class TestBroadcasting { } @Test - fun broadcastOuterTensors() = DoubleTensorAlgebra { + fun testBroadcastOuterTensors() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -68,7 +68,7 @@ internal class TestBroadcasting { } @Test - fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra { + fun testBroadcastOuterTensorsShapes() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) {0.0}) val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) {0.0}) val tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0)) @@ -81,7 +81,7 @@ internal class TestBroadcasting { } @Test - fun minusTensor() = BroadcastDoubleTensorAlgebra.invoke { + fun testMinusTensor() = BroadcastDoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index ed5f8e780..132735cc7 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -15,14 +15,14 @@ import kotlin.test.assertTrue internal class TestDoubleTensor { @Test - fun valueTest() = DoubleTensorAlgebra { + fun testValue() = DoubleTensorAlgebra { val value = 12.5 val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @Test - fun stridesTest() = DoubleTensorAlgebra { + fun testStrides() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) assertEquals(tensor[intArrayOf(0, 1)], 5.8) assertTrue( @@ -31,7 +31,7 @@ internal class TestDoubleTensor { } @Test - fun getTest() = DoubleTensorAlgebra { + fun testGet() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) val matrix = tensor[0].as2D() assertEquals(matrix[0, 1], 5.8) @@ -55,7 +55,7 @@ internal class TestDoubleTensor { } @Test - fun noBufferProtocol() { + fun testNoBufferProtocol() { // create buffer val doubleArray = DoubleBuffer(doubleArrayOf(1.0, 2.0, 3.0)) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index df2d21b96..d782d78d9 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -10,28 +10,28 @@ import kotlin.test.assertTrue internal class TestDoubleTensorAlgebra { @Test - fun doublePlus() = DoubleTensorAlgebra { + fun testDoublePlus() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(11.0, 12.0)) } @Test - fun doubleDiv() = DoubleTensorAlgebra { + fun TestDoubleDiv() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0)) val res = 2.0/tensor assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 0.5)) } @Test - fun divDouble() = DoubleTensorAlgebra { + fun testDivDouble() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0)) val res = tensor / 2.5 assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(4.0, 2.0)) } @Test - fun transpose1x1() = DoubleTensorAlgebra { + fun testTranspose1x1() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1), doubleArrayOf(0.0)) val res = tensor.transpose(0, 0) @@ -40,7 +40,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun transpose3x2() = DoubleTensorAlgebra { + fun testTranspose3x2() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) @@ -49,7 +49,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun transpose1x2x3() = DoubleTensorAlgebra { + fun testTranspose1x2x3() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transpose(0, 1) val res02 = tensor.transpose(-3, 2) @@ -65,7 +65,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun linearStructure() = DoubleTensorAlgebra { + fun testLinearStructure() = DoubleTensorAlgebra { val shape = intArrayOf(3) val tensorA = full(value = -4.5, shape = shape) val tensorB = full(value = 10.9, shape = shape) @@ -97,7 +97,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun dot() = DoubleTensorAlgebra { + fun testDot() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor11 = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) @@ -118,22 +118,10 @@ internal class TestDoubleTensorAlgebra { val res11 = tensor1.dot(tensor11) assertTrue(res11.mutableBuffer.array() contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0)) assertTrue(res11.shape contentEquals intArrayOf(2, 2)) - - var tensor4 = fromArray(intArrayOf(10, 3, 4), DoubleArray(10 * 3 * 4) {0.0}) - var tensor5 = fromArray(intArrayOf(10, 4, 5), DoubleArray(10 * 4 * 5) {0.0}) - assertTrue(tensor4.dot(tensor5).shape contentEquals intArrayOf(10, 3, 5)) - - tensor4 = fromArray(intArrayOf(10, 3, 4), DoubleArray(10 * 3 * 4) {0.0}) - tensor5 = fromArray(intArrayOf(4, 5), DoubleArray(4 * 5) {0.0}) - assertTrue(tensor4.dot(tensor5).shape contentEquals intArrayOf(10, 3, 5)) - - tensor4 = fromArray(intArrayOf(4, 2, 1, 3, 8, 1), DoubleArray(4 * 2 * 1 * 3 * 8 * 1) {0.0}) - tensor5 = fromArray(intArrayOf(5, 1, 2, 8, 3, 1, 5), DoubleArray(5 * 1 * 2 * 8 * 3 * 1 * 5) {0.0}) - assertTrue(tensor4.dot(tensor5).shape contentEquals intArrayOf(5, 4, 2, 8, 3, 8, 5)) } @Test - fun diagonalEmbedding() = DoubleTensorAlgebra { + fun testDiagonalEmbedding() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = zeros(intArrayOf(2, 3, 4, 5)) From 229c1b57daa3727a6e59d16c6ed04786a83ae220 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 6 May 2021 10:27:47 +0300 Subject: [PATCH 176/211] add documentation to DoubleLinearOpsTensorAlgebra --- .../tensors/api/LinearOpsTensorAlgebra.kt | 2 +- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 95 ++++++++++++++++++- 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 527e5d386..ec070b6bd 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -81,7 +81,7 @@ public interface LinearOpsTensorAlgebra : * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd * - * @return the determinant. + * @return triple `(U, S, V)`. */ public fun Tensor.svd(): Triple, Tensor, Tensor> diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 89345e315..d17dc70fe 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -20,7 +20,10 @@ import space.kscience.kmath.tensors.core.luPivotHelper import space.kscience.kmath.tensors.core.pivInit import kotlin.math.min - +/** + * Implementation of common linear algebra operations on double numbers. + * Implements the LinearOpsTensorAlgebra interface. + */ public object DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, DoubleTensorAlgebra() { @@ -29,12 +32,41 @@ public object DoubleLinearOpsTensorAlgebra : override fun Tensor.det(): DoubleTensor = detLU(1e-9) + /** + * Computes the LU factorization of a matrix or batches of matrices `input`. + * Returns a tuple containing the LU factorization and pivots of `input`. + * + * @param epsilon permissible error when comparing the determinant of a matrix with zero + * @return pair of `factorization` and `pivots`. + * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. + * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. + */ public fun Tensor.luFactor(epsilon: Double): Pair = computeLU(tensor, epsilon) ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") + /** + * Computes the LU factorization of a matrix or batches of matrices `input`. + * Returns a tuple containing the LU factorization and pivots of `input`. + * Uses an error of ``1e-9`` when calculating whether a matrix is degenerate. + * + * @return pair of `factorization` and `pivots`. + * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. + * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. + */ public fun Tensor.luFactor(): Pair = luFactor(1e-9) + /** + * Unpacks the data and pivots from a LU factorization of a tensor. + * Given a tensor [luTensor], return tensors (P, L, U) satisfying ``P * luTensor = L * U``, + * with `P` being a permutation matrix or batch of matrices, + * `L` being a lower triangular matrix or batch of matrices, + * `U` being an upper triangular matrix or batch of matrices. + * + * @param luTensor the packed LU factorization data + * @param pivotsTensor the packed LU factorization pivots + * @return triple of P, L and U tensors + */ public fun luPivot( luTensor: Tensor, pivotsTensor: Tensor @@ -66,6 +98,18 @@ public object DoubleLinearOpsTensorAlgebra : return Triple(pTensor, lTensor, uTensor) } + /** + * QR decomposition. + * + * Computes the QR decomposition of a matrix or a batch of matrices, and returns a pair `(Q, R)` of tensors. + * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q * R``, + * with `Q` being an orthogonal matrix or batch of orthogonal matrices + * and `R` being an upper triangular matrix or batch of upper triangular matrices. + * + * @param epsilon permissible error when comparing tensors for equality. + * Used when checking the positive definiteness of the input matrix or matrices. + * @return pair of Q and R tensors. + */ public fun Tensor.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) checkPositiveDefinite(tensor, epsilon) @@ -98,6 +142,18 @@ public object DoubleLinearOpsTensorAlgebra : override fun Tensor.svd(): Triple = svd(epsilon = 1e-10) + /** + * Singular Value Decomposition. + * + * Computes the singular value decomposition of either a matrix or batch of matrices `input`. + * The singular value decomposition is represented as a triple `(U, S, V)`, + * such that ``input = U.dot(diagonalEmbedding(S).dot(V.T))``. + * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. + * + * @param epsilon permissible error when calculating the dot product of vectors, + * i.e. the precision with which the cosine approaches 1 in an iterative algorithm. + * @return triple `(U, S, V)`. + */ public fun Tensor.svd(epsilon: Double): Triple { val size = tensor.linearStructure.dim val commonShape = tensor.shape.sliceArray(0 until size - 2) @@ -125,7 +181,14 @@ public object DoubleLinearOpsTensorAlgebra : override fun Tensor.symEig(): Pair = symEig(epsilon = 1e-15) - //For information: http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html + /** + * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, + * represented by a pair (eigenvalues, eigenvectors). + * + * @param epsilon permissible error when comparing tensors for equality + * and when the cosine approaches 1 in the SVD algorithm. + * @return a pair (eigenvalues, eigenvectors) + */ public fun Tensor.symEig(epsilon: Double): Pair { checkSymmetric(tensor, epsilon) val (u, s, v) = tensor.svd(epsilon) @@ -139,6 +202,13 @@ public object DoubleLinearOpsTensorAlgebra : return eig to v } + /** + * Computes the determinant of a square matrix input, or of each square matrix in a batched input + * using LU factorization algorithm. + * + * @param epsilon error in the LU algorithm - permissible error when comparing the determinant of a matrix with zero + * @return the determinant. + */ public fun Tensor.detLU(epsilon: Double = 1e-9): DoubleTensor { checkSquareMatrix(tensor.shape) @@ -164,6 +234,15 @@ public object DoubleLinearOpsTensorAlgebra : return detTensor } + /** + * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input + * using LU factorization algorithm. + * Given a square matrix `a`, return the matrix `aInv` satisfying + * ``a.dot(aInv) = aInv.dot(a) = eye(a.shape[0])``. + * + * @param epsilon error in the LU algorithm - permissible error when comparing the determinant of a matrix with zero + * @return the multiplicative inverse of a matrix. + */ public fun Tensor.invLU(epsilon: Double = 1e-9): DoubleTensor { val (luTensor, pivotsTensor) = luFactor(epsilon) val invTensor = luTensor.zeroesLike() @@ -177,6 +256,18 @@ public object DoubleLinearOpsTensorAlgebra : return invTensor } + /** + * LUP decomposition + * + * Computes the LUP decomposition of a matrix or a batch of matrices. + * Given a tensor `input`, return tensors (P, L, U) satisfying ``P * input = L * U``, + * with `P` being a permutation matrix or batch of matrices, + * `L` being a lower triangular matrix or batch of matrices, + * `U` being an upper triangular matrix or batch of matrices. + * + * @param epsilon permissible error when comparing the determinant of a matrix with zero + * @return triple of P, L and U tensors + */ public fun Tensor.lu(epsilon: Double = 1e-9): Triple { val (lu, pivots) = this.luFactor(epsilon) return luPivot(lu, pivots) From a1cbd7a457a93619ad3033c66248b522137e4c46 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 6 May 2021 09:48:43 +0100 Subject: [PATCH 177/211] TensorLinearStructure doc --- .../kmath/tensors/core/algebras/TensorLinearStructure.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index 5fbc7390f..d69d342ad 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -56,7 +56,12 @@ internal fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { return res } - +/** + * This [Strides] implemetation follow the last dimension first convention + * For more information: https://numpy.org/doc/stable/reference/generated/numpy.ndarray.strides.html + * + * @param shape the shape of the tensor. + */ public class TensorLinearStructure(override val shape: IntArray) : Strides { override val strides: IntArray @@ -65,6 +70,7 @@ public class TensorLinearStructure(override val shape: IntArray) : Strides override fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) + // TODO: documentation (Alya) public fun stepIndex(index: IntArray): IntArray = stepIndex(index, shape, shape.size) From 477e64e4d396ebff3a66f487b2b0cab7f507e6bd Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 6 May 2021 09:51:59 +0100 Subject: [PATCH 178/211] Typos corrected --- .../kmath/tensors/core/algebras/TensorLinearStructure.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index d69d342ad..a5c01af55 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -57,7 +57,7 @@ internal fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { } /** - * This [Strides] implemetation follow the last dimension first convention + * This [Strides] implementation follows the last dimension first convention * For more information: https://numpy.org/doc/stable/reference/generated/numpy.ndarray.strides.html * * @param shape the shape of the tensor. From 16bed539977c516645d0a980f4f22578a6fbec11 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 6 May 2021 09:59:58 +0100 Subject: [PATCH 179/211] Drop unused functionality in TensorLinearStructure --- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 2 +- .../core/algebras/TensorLinearStructure.kt | 27 +------------------ 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index d17dc70fe..430482613 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -155,7 +155,7 @@ public object DoubleLinearOpsTensorAlgebra : * @return triple `(U, S, V)`. */ public fun Tensor.svd(epsilon: Double): Triple { - val size = tensor.linearStructure.dim + val size = tensor.dimension val commonShape = tensor.shape.sliceArray(0 until size - 2) val (n, m) = tensor.shape.sliceArray(size - 2 until size) val uTensor = zeros(commonShape + intArrayOf(min(n, m), n)) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index a5c01af55..68aa03311 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -39,45 +39,20 @@ internal fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArra return res } -internal fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { - val res = index.copyOf() - var current = nDim - 1 - var carry = 0 - - do { - res[current]++ - if (res[current] >= shape[current]) { - carry = 1 - res[current] = 0 - } - current-- - } while (carry != 0 && current >= 0) - - return res -} - /** * This [Strides] implementation follows the last dimension first convention * For more information: https://numpy.org/doc/stable/reference/generated/numpy.ndarray.strides.html * * @param shape the shape of the tensor. */ -public class TensorLinearStructure(override val shape: IntArray) : Strides -{ +public class TensorLinearStructure(override val shape: IntArray) : Strides { override val strides: IntArray get() = stridesFromShape(shape) override fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) - // TODO: documentation (Alya) - public fun stepIndex(index: IntArray): IntArray = - stepIndex(index, shape, shape.size) - override val linearSize: Int get() = shape.reduce(Int::times) - public val dim: Int - get() = shape.size - } \ No newline at end of file From 499cf85ff08ac65e7343e33af2f4f65cd9967b3f Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Thu, 6 May 2021 12:30:13 +0300 Subject: [PATCH 180/211] 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 From 35928e7960bd5676820b751490be057fa62409ff Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 6 May 2021 10:52:37 +0100 Subject: [PATCH 181/211] minor corrections --- .../kscience/kmath/tensors/core/BufferedTensor.kt | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) 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 e4ffccd96..e8c0556c2 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 @@ -5,7 +5,7 @@ import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure /** - * [Tensor] implementation provided with [MutableBuffer] + * Represents [Tensor] over a [MutableBuffer] intended to be used through [DoubleTensor] and [IntTensor] */ public open class BufferedTensor internal constructor( override val shape: IntArray, @@ -14,7 +14,7 @@ public open class BufferedTensor internal constructor( ) : Tensor { /** - * [TensorLinearStructure] with the same shape + * Buffer strides based on [TensorLinearStructure] implementation */ public val linearStructure: TensorLinearStructure get() = TensorLinearStructure(shape) @@ -25,23 +25,12 @@ public open class BufferedTensor internal constructor( 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] } From 8ac253b9fe112bfe64d467c07db9dc9b9ed74e52 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Thu, 6 May 2021 14:09:47 +0300 Subject: [PATCH 182/211] cov + docs --- .../tensors/api/AnalyticTensorAlgebra.kt | 10 +++++++ .../algebras/DoubleAnalyticTensorAlgebra.kt | 24 ++++++++++++++++- .../core/algebras/DoubleTensorAlgebra.kt | 27 +++++++++++++------ 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index aa5678b31..69e88c28f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -68,6 +68,16 @@ public interface AnalyticTensorAlgebra : */ public fun Tensor.variance(dim: Int, keepDim: Boolean): Tensor + /** + * Returns the covariance matrix M of given vectors. + * + * M[i, j] contains covariance of i-th and j-th given vectors + * + * @param tensors the [List] of 1-dimensional tensors with same shape + * @return the covariance matrix + */ + public fun cov(tensors: List>): Tensor + //For information: https://pytorch.org/docs/stable/generated/torch.exp.html public fun Tensor.exp(): Tensor diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 4a1f360e3..23a2fa282 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -57,6 +57,28 @@ public object DoubleAnalyticTensorAlgebra : keepDim ) + private fun cov(x: DoubleTensor, y:DoubleTensor): Double{ + val n = x.shape[0] + return ((x - x.mean()) * (y - y.mean())).mean() * n / (n - 1) + } + + override fun cov(tensors: List>): DoubleTensor { + check(tensors.isNotEmpty()) { "List must have at least 1 element" } + val n = tensors.size + val m = tensors[0].shape[0] + check(tensors.all { it.shape contentEquals intArrayOf(m) }) { "Tensors must have same shapes" } + val resTensor = DoubleTensor( + intArrayOf(n, n), + DoubleArray(n * n) {0.0} + ) + for (i in 0 until n){ + for (j in 0 until n){ + resTensor[intArrayOf(i, j)] = cov(tensors[i].tensor, tensors[j].tensor) + } + } + return resTensor + } + override fun Tensor.exp(): DoubleTensor = tensor.map(::exp) override fun Tensor.ln(): DoubleTensor = tensor.map(::ln) @@ -91,4 +113,4 @@ public object DoubleAnalyticTensorAlgebra : override fun Tensor.floor(): DoubleTensor = tensor.map(::floor) -} \ No newline at end of file +} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index d220bdd9a..74ef63ab7 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -401,19 +401,31 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun Tensor.randomNormalLike(seed: Long = 0): DoubleTensor = DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) - // stack tensors by axis 0 - public fun stack(tensors: List): 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" } + /** + * Concatenates a sequence of tensors along a new dimension. + * + * @param tensors the [List] of tensors with same shapes to concatenate + * @param dim the dimension to insert + * @return tensor with concatenation result + */ + public fun stack(tensors: List>, dim: Int = 0): DoubleTensor { + check(dim == 0) { "Stack by non-zero dimension not implemented yet" } + check(tensors.isNotEmpty()) { "List must have at least 1 element" } + val shape = tensors[0].shape + check(tensors.all { it.shape contentEquals shape }) { "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) + it.tensor.mutableBuffer.array().drop(it.tensor.bufferStart).take(it.tensor.numElements) }.toDoubleArray() return DoubleTensor(resShape, resBuffer, 0) } - // build tensor from this rows by given indices + /** + * Build tensor from rows of input tensor + * + * @param indices the [IntArray] of 1-dimensional indices + * @return tensor with rows corresponding to rows by [indices] + */ public fun Tensor.rowsByIndices(indices: IntArray): DoubleTensor { return stack(indices.map { this[it] }) } @@ -450,7 +462,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor = foldDim({ x -> x.sum() }, dim, keepDim) - override fun Tensor.min(): Double = this.fold { it.minOrNull()!! } override fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor = From dc22bd84986d14f6d82209a106d6413e3bd609e2 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 6 May 2021 14:23:57 +0300 Subject: [PATCH 183/211] add documentation to DoubleTensorAlgebra --- .../core/algebras/DoubleTensorAlgebra.kt | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index d220bdd9a..2cad85a09 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -23,6 +23,9 @@ import space.kscience.kmath.tensors.core.getRandomNormals import space.kscience.kmath.tensors.core.minusIndexFrom import kotlin.math.abs +/** + * Implementation of basic operations over double tensors and basic algebra operations on them. + */ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public companion object : DoubleTensorAlgebra() @@ -34,6 +37,13 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return tensor.mutableBuffer.array()[tensor.bufferStart] } + /** + * Constructs a tensor with the specified shape and data. + * + * @param shape the desired shape for the tensor. + * @param buffer one-dimensional data array. + * @return tensor with the [shape] shape and [buffer] data. + */ public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor { checkEmptyShape(shape) checkEmptyDoubleBuffer(buffer) @@ -48,26 +58,67 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(newShape, tensor.mutableBuffer.array(), newStart) } + /** + * Creates a tensor of a given shape and fills all elements with a given value. + * + * @param value the value to fill the output tensor with. + * @param shape array of integers defining the shape of the output tensor. + * @return tensor with the [shape] shape and filled with [value]. + */ public fun full(value: Double, shape: IntArray): DoubleTensor { checkEmptyShape(shape) val buffer = DoubleArray(shape.reduce(Int::times)) { value } return DoubleTensor(shape, buffer) } + /** + * Returns a tensor with the same shape as `input` filled with [value]. + * + * @param value the value to fill the output tensor with. + * @return tensor with the `input` tensor shape and filled with [value]. + */ public fun Tensor.fullLike(value: Double): DoubleTensor { val shape = tensor.shape val buffer = DoubleArray(tensor.numElements) { value } return DoubleTensor(shape, buffer) } + /** + * Returns a tensor filled with the scalar value 0.0, with the shape defined by the variable argument [shape]. + * + * @param shape array of integers defining the shape of the output tensor. + * @return tensor filled with the scalar value 0.0, with the [shape] shape. + */ public fun zeros(shape: IntArray): DoubleTensor = full(0.0, shape) + /** + * Returns a tensor filled with the scalar value 0.0, with the same shape as a given array. + * + * @return tensor filled with the scalar value 0.0, with the same shape as `input` tensor. + */ public fun Tensor.zeroesLike(): DoubleTensor = tensor.fullLike(0.0) + /** + * Returns a tensor filled with the scalar value 1.0, with the shape defined by the variable argument [shape]. + * + * @param shape array of integers defining the shape of the output tensor. + * @return tensor filled with the scalar value 1.0, with the [shape] shape. + */ public fun ones(shape: IntArray): DoubleTensor = full(1.0, shape) + /** + * Returns a tensor filled with the scalar value 1.0, with the same shape as a given array. + * + * @return tensor filled with the scalar value 1.0, with the same shape as `input` tensor. + */ public fun Tensor.onesLike(): DoubleTensor = tensor.fullLike(1.0) + /** + * Returns a 2-D tensor with shape ([n], [n]), with ones on the diagonal and zeros elsewhere. + * + * @param n the number of rows and columns + * @return a 2-D tensor with ones on the diagonal and zeros elsewhere. + */ public fun eye(n: Int): DoubleTensor { val shape = intArrayOf(n, n) val buffer = DoubleArray(n * n) { 0.0 } @@ -78,6 +129,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return res } + /** + * Return a copy of the tensor. + * + * @return a copy of the `input` tensor with a copied buffer. + */ public fun Tensor.copy(): DoubleTensor { return DoubleTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart) } @@ -359,7 +415,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return resTensor.tensor } - public fun Tensor.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( tensor.shape, From 90149e396561004e781b390f87c51361e6a9e82f Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 6 May 2021 14:42:15 +0300 Subject: [PATCH 184/211] add documentation to map and randomNormal function --- .../core/algebras/DoubleTensorAlgebra.kt | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index d8b59daa7..8c76de0de 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -415,6 +415,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return resTensor.tensor } + /** + * Applies the [transform] function to each element of the tensor and returns the resulting modified tensor. + * + * @param transform the function to be applied to each element of the tensor. + * @return the resulting tensor after applying the function. + */ public fun Tensor.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( tensor.shape, @@ -423,10 +429,24 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { ) } + /** + * Compares element-wise two tensors with a specified precision. + * + * @param other the tensor to compare with `input` tensor. + * @param epsilon permissible error when comparing two Double values. + * @return true if two tensors have the same shape and elements, false otherwise. + */ public fun Tensor.eq(other: Tensor, epsilon: Double): Boolean { return tensor.eq(other) { x, y -> abs(x - y) < epsilon } } + /** + * Compares element-wise two tensors. + * Comparison of two Double values occurs with 1e-5 precision. + * + * @param other the tensor to compare with `input` tensor. + * @return true if two tensors have the same shape and elements, false otherwise. + */ public infix fun Tensor.eq(other: Tensor): Boolean = tensor.eq(other, 1e-5) private fun Tensor.eq( @@ -450,9 +470,25 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return true } + /** + * Returns a tensor of random numbers drawn from normal distributions with 0.0 mean and 1.0 standard deviation. + * + * @param shape the desired shape for the output tensor. + * @param seed the random seed of the pseudo-random number generator. + * @return tensor of a given shape filled with numbers from the normal distribution + * with 0.0 mean and 1.0 standard deviation. + */ public fun randomNormal(shape: IntArray, seed: Long = 0): DoubleTensor = DoubleTensor(shape, getRandomNormals(shape.reduce(Int::times), seed)) + /** + * Returns a tensor with the same shape as `input` of random numbers drawn from normal distributions + * with 0.0 mean and 1.0 standard deviation. + * + * @param seed the random seed of the pseudo-random number generator. + * @return tensor with the same shape as `input` filled with numbers from the normal distribution + * with 0.0 mean and 1.0 standard deviation. + */ public fun Tensor.randomNormalLike(seed: Long = 0): DoubleTensor = DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) From 5fe1320855941167afba93fb0f3d0beb855c834e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 6 May 2021 12:59:21 +0100 Subject: [PATCH 185/211] minor corrections --- .../kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 8c76de0de..1c8eacf66 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -493,7 +493,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) /** - * Concatenates a sequence of tensors along a new dimension. + * Concatenates a sequence of tensors along the first dimension. * * @param tensors the [List] of tensors with same shapes to concatenate * @param dim the dimension to insert From db5378c9f4ab3ff4e84d815d9db4686015330bf9 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Thu, 6 May 2021 16:29:21 +0300 Subject: [PATCH 186/211] PCA example --- .../space/kscience/kmath/tensors/PCA.kt | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt new file mode 100644 index 000000000..1d72b2326 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -0,0 +1,78 @@ +/* + * 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 + +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra + +const val seed = 100500L + +// simple PCA + +fun main(){ + DoubleAnalyticTensorAlgebra { + + // assume x is range from 0 until 10 + val x = fromArray( + intArrayOf(10), + (0 until 10).toList().map { it.toDouble() }.toDoubleArray() + ) + + // take y dependent on x with noise + val y = 2.0 * x + (3.0 + x.randomNormalLike(seed) * 1.5) + + println("x:\n$x") + println("y:\n$y") + + // stack them into single dataset + val dataset = stack(listOf(x, y)).transpose() + + // normalize both x and y + val xMean = x.mean() + val yMean = y.mean() + + val xStd = x.std() + val yStd = y.std() + + val xScaled = (x - xMean) / xStd + val yScaled = (y - yMean) / yStd + + // save means ans standard deviations for further recovery + val mean = fromArray( + intArrayOf(2), + doubleArrayOf(xMean, yMean) + ) + println("Means:\n$mean") + + val std = fromArray( + intArrayOf(2), + doubleArrayOf(xStd, yStd) + ) + println("Standard deviations:\n$std") + + // calculate the covariance matrix of scaled x and y + val covMatrix = cov(listOf(xScaled, yScaled)) + println("Covariance matrix:\n$covMatrix") + + // and find out eigenvector of it + val (_, evecs) = DoubleLinearOpsTensorAlgebra {covMatrix.symEig()} + val v = evecs[0] + println("Eigenvector:\n$v") + + // reduce dimension of dataset + val datasetReduced = v dot stack(listOf(xScaled, yScaled)) + println("Reduced data:\n$datasetReduced") + + // we can restore original data from reduced data. + // for example, find 7th element of dataset + val n = 7 + val restored = BroadcastDoubleTensorAlgebra{(datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean} + println("Original value:\n${dataset[n]}") + println("Restored value:\n$restored") + } +} From febe526325150c2b716f233956a12e69fcb44804 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 6 May 2021 14:50:05 +0100 Subject: [PATCH 187/211] Update stack docs --- .../kmath/tensors/core/algebras/DoubleTensorAlgebra.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 1c8eacf66..9500fbdec 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -493,14 +493,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) /** - * Concatenates a sequence of tensors along the first dimension. + * Concatenates a sequence of tensors with equal shapes along the first dimension. * * @param tensors the [List] of tensors with same shapes to concatenate - * @param dim the dimension to insert * @return tensor with concatenation result */ - public fun stack(tensors: List>, dim: Int = 0): DoubleTensor { - check(dim == 0) { "Stack by non-zero dimension not implemented yet" } + public fun stack(tensors: List>): DoubleTensor { check(tensors.isNotEmpty()) { "List must have at least 1 element" } val shape = tensors[0].shape check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } From 1b1a078deaee681c99603737d11eecefe0411db4 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 7 May 2021 03:22:34 +0300 Subject: [PATCH 188/211] neural network! --- .../kscience/kmath/tensors/NeuralNetwork.kt | 245 ++++++++++++++++++ .../space/kscience/kmath/tensors/PCA.kt | 5 +- .../kmath/tensors/api/TensorAlgebra.kt | 13 +- .../core/algebras/DoubleTensorAlgebra.kt | 5 + 4 files changed, 266 insertions(+), 2 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt new file mode 100644 index 000000000..ea863988c --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt @@ -0,0 +1,245 @@ +/* + * 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 + +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.toDoubleArray +import kotlin.math.sqrt + +const val seed = 100500L + +// Simple feedforward neural network with backpropagation training + +// interface of network layer +interface Layer { + fun forward(input: DoubleTensor): DoubleTensor + fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor +} + +// activation layer +open class Activation( + val activation: (DoubleTensor) -> DoubleTensor, + val activationDer: (DoubleTensor) -> DoubleTensor +) : Layer { + override fun forward(input: DoubleTensor): DoubleTensor { + return activation(input) + } + + override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor { + return DoubleTensorAlgebra { outputError * activationDer(input) } + } +} + +fun relu(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { + x.map { if (it > 0) it else 0.0 } +} + +fun reluDer(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { + x.map { if (it > 0) 1.0 else 0.0 } +} + +// activation layer with relu activator +class ReLU : Activation(::relu, ::reluDer) + +fun sigmoid(x: DoubleTensor): DoubleTensor = DoubleAnalyticTensorAlgebra { + 1.0 / (1.0 + (-x).exp()) +} + +fun sigmoidDer(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { + sigmoid(x) * (1.0 - sigmoid(x)) +} + +// activation layer with sigmoid activator +class Sigmoid : Activation(::sigmoid, ::sigmoidDer) + +// dense layer +class Dense( + private val inputUnits: Int, + private val outputUnits: Int, + private val learningRate: Double = 0.1 +) : Layer { + + private val weights: DoubleTensor = DoubleTensorAlgebra { + randomNormal( + intArrayOf(inputUnits, outputUnits), + seed + ) * sqrt(2.0 / (inputUnits + outputUnits)) + } + + private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(intArrayOf(outputUnits)) } + + override fun forward(input: DoubleTensor): DoubleTensor { + return BroadcastDoubleTensorAlgebra { (input dot weights) + bias } + } + + override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { + val gradInput = outputError dot weights.transpose() + + val gradW = input.transpose() dot outputError + val gradBias = DoubleAnalyticTensorAlgebra { + outputError.mean(dim = 0, keepDim = false) * input.shape[0].toDouble() + } + + weights -= learningRate * gradW + bias -= learningRate * gradBias + + gradInput + } + +} + +// simple accuracy equal to the proportion of correct answers +fun accuracy(yPred: DoubleTensor, yTrue: DoubleTensor): Double { + check(yPred.shape contentEquals yTrue.shape) + val n = yPred.shape[0] + var correctCnt = 0 + for (i in 0 until n) { + if (yPred[intArrayOf(i, 0)] == yTrue[intArrayOf(i, 0)]) { + correctCnt += 1 + } + } + return correctCnt.toDouble() / n.toDouble() +} + +// neural network class +class NeuralNetwork(private val layers: List) { + private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = DoubleAnalyticTensorAlgebra { + + val onesForAnswers = yPred.zeroesLike() + yTrue.toDoubleArray().forEachIndexed { index, labelDouble -> + val label = labelDouble.toInt() + onesForAnswers[intArrayOf(index, label)] = 1.0 + } + + val softmaxValue = BroadcastDoubleTensorAlgebra { yPred.exp() / yPred.exp().sum(dim = 1, keepDim = true) } + + (-onesForAnswers + softmaxValue) / (yPred.shape[0].toDouble()) + } + + @OptIn(ExperimentalStdlibApi::class) + private fun forward(x: DoubleTensor): List { + var input = x + + return buildList { + layers.forEach { layer -> + val output = layer.forward(input) + add(output) + input = output + } + } + } + + @OptIn(ExperimentalStdlibApi::class) + private fun train(xTrain: DoubleTensor, yTrain: DoubleTensor) { + val layerInputs = buildList { + add(xTrain) + addAll(forward(xTrain)) + } + + var lossGrad = softMaxLoss(layerInputs.last(), yTrain) + + layers.zip(layerInputs).reversed().forEach { (layer, input) -> + lossGrad = layer.backward(input, lossGrad) + } + } + + fun fit(xTrain: DoubleTensor, yTrain: DoubleTensor, batchSize: Int, epochs: Int) = DoubleTensorAlgebra { + fun iterBatch(x: DoubleTensor, y: DoubleTensor): Sequence> = sequence { + val n = x.shape[0] + val shuffledIndices = (0 until n).shuffled() + for (i in 0 until n step batchSize) { + val excerptIndices = shuffledIndices.drop(i).take(batchSize).toIntArray() + val batch = x.rowsByIndices(excerptIndices) to y.rowsByIndices(excerptIndices) + yield(batch) + } + } + + for (epoch in 0 until epochs) { + println("Epoch ${epoch + 1}/$epochs") + for ((xBatch, yBatch) in iterBatch(xTrain, yTrain)) { + train(xBatch, yBatch) + } + println("Accuracy:${accuracy(yTrain, predict(xTrain).argMax(1, true))}") + } + } + + fun predict(x: DoubleTensor): DoubleTensor { + return forward(x).last() + } + +} + + + +@OptIn(ExperimentalStdlibApi::class) +fun main() { + DoubleTensorAlgebra { + val features = 5 + val sampleSize = 250 + val trainSize = 180 + val testSize = sampleSize - trainSize + + // take sample of features from normal distribution + val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5 + BroadcastDoubleTensorAlgebra { + x += fromArray( + intArrayOf(5), + doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means + ) + } + + // define class like '1' if the sum of features > 0 and '0' otherwise + val y = fromArray( + intArrayOf(sampleSize, 1), + DoubleArray(sampleSize) { i -> + if (x[i].sum() > 0.0) { + 1.0 + } else { + 0.0 + } + } + ) + + // split train ans test + val trainIndices = (0 until trainSize).toList().toIntArray() + val testIndices = (trainSize until sampleSize).toList().toIntArray() + + val xTrain = x.rowsByIndices(trainIndices) + val yTrain = y.rowsByIndices(trainIndices) + + val xTest = x.rowsByIndices(testIndices) + val yTest = y.rowsByIndices(testIndices) + + // build model + val layers = buildList { + add(Dense(features, 64)) + add(ReLU()) + add(Dense(64, 16)) + add(ReLU()) + add(Dense(16, 2)) + add(Sigmoid()) + } + val model = NeuralNetwork(layers) + + // fit it with train data + model.fit(xTrain, yTrain, batchSize = 20, epochs = 10) + + // make prediction + val prediction = model.predict(xTest) + + // process raw prediction via argMax + val predictionLabels = prediction.argMax(1, true) + + // find out accuracy + val acc = accuracy(yTest, predictionLabels) + println("Test accuracy:$acc") + + } +} diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt index 1d72b2326..ee25b63a3 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -10,11 +10,14 @@ import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra -const val seed = 100500L + // simple PCA fun main(){ + val seed = 100500L + + // work in context with analytic methods DoubleAnalyticTensorAlgebra { // assume x is range from 0 until 10 diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index b0a0f9618..417cff87f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -305,5 +305,16 @@ public interface TensorAlgebra: Algebra> { */ public fun Tensor.max(dim: Int, keepDim: Boolean): Tensor - + /** + * Returns the index of maximum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the the index of maximum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.argMax(dim: Int, keepDim: Boolean): Tensor } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 9500fbdec..6fac0a0ec 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -561,4 +561,9 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) + override fun Tensor.argMax(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> + x.withIndex().maxByOrNull { it.value }?.index!!.toDouble() + }, dim, keepDim) + } From 14ca7cdd31e14855c95a51b8143bf80aae02feb9 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 7 May 2021 13:00:20 +0300 Subject: [PATCH 189/211] fixes --- .../kmath/tensors/api/LinearOpsTensorAlgebra.kt | 15 ++++++++------- .../kscience/kmath/tensors/api/TensorAlgebra.kt | 2 +- .../tensors/core/algebras/DoubleTensorAlgebra.kt | 9 ++++----- .../core/algebras/TensorLinearStructure.kt | 3 +-- .../kscience/kmath/tensors/core/tensorCasts.kt | 2 +- .../kmath/tensors/core/tensorCastsUtils.kt | 2 +- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index ec070b6bd..4a325ab4e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -23,8 +23,8 @@ public interface LinearOpsTensorAlgebra : /** * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input. - * Given a square matrix `a`, return the matrix `aInv` satisfying - * ``a.dot(aInv) = aInv.dot(a) = eye(a.shape[0])``. + * Given a square matrix `A`, return the matrix `AInv` satisfying + * `A dot AInv = AInv dot A = eye(a.shape[0])`. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv * * @return the multiplicative inverse of a matrix. @@ -37,7 +37,7 @@ public interface LinearOpsTensorAlgebra : * Computes the Cholesky decomposition of a Hermitian (or symmetric for real-valued matrices) * positive-definite matrix or the Cholesky decompositions for a batch of such matrices. * Each decomposition has the form: - * Given a tensor `input`, return the tensor `L` satisfying ``input = L * L.H``, + * Given a tensor `input`, return the tensor `L` satisfying `input = L dot L.H`, * where L is a lower-triangular matrix and L.H is the conjugate transpose of L, * which is just a transpose for the case of real-valued input matrices. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.cholesky @@ -50,7 +50,7 @@ public interface LinearOpsTensorAlgebra : * QR decomposition. * * Computes the QR decomposition of a matrix or a batch of matrices, and returns a pair `(Q, R)` of tensors. - * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q * R``, + * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q dot R``, * with `Q` being an orthogonal matrix or batch of orthogonal matrices * and `R` being an upper triangular matrix or batch of upper triangular matrices. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr @@ -63,7 +63,7 @@ public interface LinearOpsTensorAlgebra : * LUP decomposition * * Computes the LUP decomposition of a matrix or a batch of matrices. - * Given a tensor `input`, return tensors (P, L, U) satisfying ``P * input = L * U``, + * Given a tensor `input`, return tensors (P, L, U) satisfying `P dot input = L dot U`, * with `P` being a permutation matrix or batch of matrices, * `L` being a lower triangular matrix or batch of matrices, * `U` being an upper triangular matrix or batch of matrices. @@ -77,7 +77,8 @@ public interface LinearOpsTensorAlgebra : * * Computes the singular value decomposition of either a matrix or batch of matrices `input`. * The singular value decomposition is represented as a triple `(U, S, V)`, - * such that ``input = U.dot(diagonalEmbedding(S).dot(V.T))``. + * such that `input = U dot diagonalEmbedding(S) dot V.H`, + * where V.H is the conjugate transpose of V. * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd * @@ -94,4 +95,4 @@ public interface LinearOpsTensorAlgebra : */ public fun Tensor.symEig(): Pair, Tensor> -} \ No newline at end of file +} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 417cff87f..e7f8dc7ae 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -288,7 +288,7 @@ public interface TensorAlgebra: Algebra> { public fun Tensor.min(dim: Int, keepDim: Boolean): Tensor /** - * @return the maximum value of all elements in the input tensor. + * Returns the maximum value of all elements in the input tensor. */ public fun Tensor.max(): T diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 6fac0a0ec..e5d41f856 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -343,7 +343,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { val m2 = newOther.shape[newOther.shape.size - 2] val n = newOther.shape[newOther.shape.size - 1] check(m1 == m2) { - throw RuntimeException("Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)") + "Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)" } val resShape = newThis.shape.sliceArray(0..(newThis.shape.size - 2)) + intArrayOf(newOther.shape.last()) @@ -436,9 +436,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { * @param epsilon permissible error when comparing two Double values. * @return true if two tensors have the same shape and elements, false otherwise. */ - public fun Tensor.eq(other: Tensor, epsilon: Double): Boolean { - return tensor.eq(other) { x, y -> abs(x - y) < epsilon } - } + public fun Tensor.eq(other: Tensor, epsilon: Double): Boolean = + tensor.eq(other) { x, y -> abs(x - y) < epsilon } /** * Compares element-wise two tensors. @@ -510,7 +509,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } /** - * Build tensor from rows of input tensor + * Builds tensor from rows of input tensor * * @param indices the [IntArray] of 1-dimensional indices * @return tensor with rows corresponding to rows by [indices] diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index 68aa03311..f65e2b955 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -23,7 +23,6 @@ internal fun stridesFromShape(shape: IntArray): IntArray { current-- } return res - } internal fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { @@ -55,4 +54,4 @@ public class TensorLinearStructure(override val shape: IntArray) : Strides { override val linearSize: Int get() = shape.reduce(Int::times) -} \ No newline at end of file +} 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 index 6254ce751..2743a5218 100644 --- 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 @@ -33,4 +33,4 @@ 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 index 31de6919f..70e3b9c61 100644 --- 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 @@ -39,4 +39,4 @@ internal val Tensor.tensor: IntTensor get() = when (this) { is IntTensor -> this else -> this.toBufferedTensor().asTensor() - } \ No newline at end of file + } From 0920e21d622e85e95e25b6d28d906309dab8d875 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 12:52:17 +0100 Subject: [PATCH 190/211] Merging implementations together --- .../kmath/tensors/DataSetNormalization.kt | 20 +- .../tensors/LinearSystemSolvingWithLUP.kt | 4 +- .../kscience/kmath/tensors/NeuralNetwork.kt | 26 +- .../kscience/kmath/tensors/OLSWithSVD.kt | 9 +- .../space/kscience/kmath/tensors/PCA.kt | 11 +- .../tensors/api/AnalyticTensorAlgebra.kt | 3 +- .../tensors/api/LinearOpsTensorAlgebra.kt | 3 +- .../api/TensorPartialDivisionAlgebra.kt | 3 +- .../kmath/tensors/core/DoubleTensor.kt | 1 + .../algebras/BroadcastDoubleTensorAlgebra.kt | 6 +- .../algebras/DoubleAnalyticTensorAlgebra.kt | 116 ------ .../algebras/DoubleLinearOpsTensorAlgebra.kt | 278 ------------- .../core/algebras/DoubleTensorAlgebra.kt | 385 +++++++++++++++++- .../core/{ => internal}/broadcastUtils.kt | 8 +- .../tensors/core/{ => internal}/checks.kt | 11 +- .../tensors/core/{ => internal}/linUtils.kt | 27 +- .../core/{ => internal}/tensorCastsUtils.kt | 5 +- .../tensors/core/{ => internal}/utils.kt | 9 +- .../kmath/tensors/core/tensorCasts.kt | 1 + .../kmath/tensors/core/TestBroadcasting.kt | 1 + .../core/TestDoubleAnalyticTensorAlgebra.kt | 31 +- .../core/TestDoubleLinearOpsAlgebra.kt | 30 +- .../kmath/tensors/core/TestDoubleTensor.kt | 4 + .../tensors/core/TestDoubleTensorAlgebra.kt | 1 + 24 files changed, 488 insertions(+), 505 deletions(-) delete mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt delete mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => internal}/broadcastUtils.kt (94%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => internal}/checks.kt (83%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => internal}/linUtils.kt (91%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => internal}/tensorCastsUtils.kt (88%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => internal}/utils.kt (91%) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt index 4d53d940b..d029348f2 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt @@ -7,22 +7,22 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra + // Dataset normalization fun main() { - // work in context with analytic methods - DoubleAnalyticTensorAlgebra { + // work in context with broadcast methods + BroadcastDoubleTensorAlgebra { // take dataset of 5-element vectors from normal distribution val dataset = randomNormal(intArrayOf(100, 5)) * 1.5 // all elements from N(0, 1.5) - BroadcastDoubleTensorAlgebra { - dataset += fromArray( - intArrayOf(5), - doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means - ) - } + + dataset += fromArray( + intArrayOf(5), + doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means + ) + // find out mean and standard deviation of each column val mean = dataset.mean(0, false) @@ -36,7 +36,7 @@ fun main() { println("Maximum:\n${dataset.max(0, false)}") // now we can scale dataset with mean normalization - val datasetScaled = BroadcastDoubleTensorAlgebra { (dataset - mean) / std } + val datasetScaled = (dataset - mean) / std // find out mean and std of scaled dataset diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index bd8233ccc..c0ece04ca 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -7,14 +7,14 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra // solving linear system with LUP decomposition fun main () { // work in context with linear operations - DoubleLinearOpsTensorAlgebra { + BroadcastDoubleTensorAlgebra { // set true value of x val trueX = fromArray( diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt index ea863988c..1998b8d16 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt @@ -8,7 +8,6 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.toDoubleArray import kotlin.math.sqrt @@ -48,7 +47,7 @@ fun reluDer(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { // activation layer with relu activator class ReLU : Activation(::relu, ::reluDer) -fun sigmoid(x: DoubleTensor): DoubleTensor = DoubleAnalyticTensorAlgebra { +fun sigmoid(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { 1.0 / (1.0 + (-x).exp()) } @@ -83,9 +82,7 @@ class Dense( val gradInput = outputError dot weights.transpose() val gradW = input.transpose() dot outputError - val gradBias = DoubleAnalyticTensorAlgebra { - outputError.mean(dim = 0, keepDim = false) * input.shape[0].toDouble() - } + val gradBias = outputError.mean(dim = 0, keepDim = false) * input.shape[0].toDouble() weights -= learningRate * gradW bias -= learningRate * gradBias @@ -110,7 +107,7 @@ fun accuracy(yPred: DoubleTensor, yTrue: DoubleTensor): Double { // neural network class class NeuralNetwork(private val layers: List) { - private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = DoubleAnalyticTensorAlgebra { + private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra { val onesForAnswers = yPred.zeroesLike() yTrue.toDoubleArray().forEachIndexed { index, labelDouble -> @@ -118,7 +115,7 @@ class NeuralNetwork(private val layers: List) { onesForAnswers[intArrayOf(index, label)] = 1.0 } - val softmaxValue = BroadcastDoubleTensorAlgebra { yPred.exp() / yPred.exp().sum(dim = 1, keepDim = true) } + val softmaxValue = yPred.exp() / yPred.exp().sum(dim = 1, keepDim = true) (-onesForAnswers + softmaxValue) / (yPred.shape[0].toDouble()) } @@ -177,10 +174,9 @@ class NeuralNetwork(private val layers: List) { } - @OptIn(ExperimentalStdlibApi::class) fun main() { - DoubleTensorAlgebra { + BroadcastDoubleTensorAlgebra { val features = 5 val sampleSize = 250 val trainSize = 180 @@ -188,12 +184,12 @@ fun main() { // take sample of features from normal distribution val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5 - BroadcastDoubleTensorAlgebra { - x += fromArray( - intArrayOf(5), - doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means - ) - } + + x += fromArray( + intArrayOf(5), + doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means + ) + // define class like '1' if the sum of features > 0 and '0' otherwise val y = fromArray( diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 435af35f6..497f63b41 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -7,8 +7,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.math.abs @@ -19,7 +18,7 @@ fun main() { val randSeed = 100500L // work in context with linear operations - DoubleLinearOpsTensorAlgebra { + DoubleTensorAlgebra { // take coefficient vector from normal distribution val alpha = randomNormal( intArrayOf(5), @@ -56,12 +55,12 @@ fun main() { "$alphaOLS") // figure out MSE of approximation - fun mse(yTrue: DoubleTensor, yPred: DoubleTensor): Double = DoubleAnalyticTensorAlgebra{ + fun mse(yTrue: DoubleTensor, yPred: DoubleTensor): Double { require(yTrue.shape.size == 1) require(yTrue.shape contentEquals yPred.shape) val diff = yTrue - yPred - diff.dot(diff).sqrt().value() + return diff.dot(diff).sqrt().value() } println("MSE: ${mse(alpha, alphaOLS)}") diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt index ee25b63a3..d29dbb094 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -7,9 +7,6 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra - // simple PCA @@ -17,8 +14,8 @@ import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra fun main(){ val seed = 100500L - // work in context with analytic methods - DoubleAnalyticTensorAlgebra { + // work in context with broadcast methods + BroadcastDoubleTensorAlgebra { // assume x is range from 0 until 10 val x = fromArray( @@ -63,7 +60,7 @@ fun main(){ println("Covariance matrix:\n$covMatrix") // and find out eigenvector of it - val (_, evecs) = DoubleLinearOpsTensorAlgebra {covMatrix.symEig()} + val (_, evecs) = covMatrix.symEig() val v = evecs[0] println("Eigenvector:\n$v") @@ -74,7 +71,7 @@ fun main(){ // we can restore original data from reduced data. // for example, find 7th element of dataset val n = 7 - val restored = BroadcastDoubleTensorAlgebra{(datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean} + val restored = (datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean println("Original value:\n${dataset[n]}") println("Restored value:\n$restored") } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 69e88c28f..1db986e77 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -11,8 +11,7 @@ package space.kscience.kmath.tensors.api * * @param T the type of items closed under analytic functions in the tensors. */ -public interface AnalyticTensorAlgebra : - TensorPartialDivisionAlgebra { +public interface AnalyticTensorAlgebra : TensorPartialDivisionAlgebra { /** * @return the mean of all elements in the input tensor. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 4a325ab4e..6bdecfa85 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -10,8 +10,7 @@ package space.kscience.kmath.tensors.api * * @param T the type of items closed under division in the tensors. */ -public interface LinearOpsTensorAlgebra : - TensorPartialDivisionAlgebra { +public interface LinearOpsTensorAlgebra : TensorPartialDivisionAlgebra { /** * Computes the determinant of a square matrix input, or of each square matrix in a batched input. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt index 921157963..02bf5415d 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt @@ -11,8 +11,7 @@ package space.kscience.kmath.tensors.api * * @param T the type of items closed under division in the tensors. */ -public interface TensorPartialDivisionAlgebra : - TensorAlgebra { +public interface TensorPartialDivisionAlgebra : TensorAlgebra { /** * Each element of the tensor [other] is divided by this value. 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 index e3143f5a7..41df50cba 100644 --- 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 @@ -6,6 +6,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.tensors.core.internal.toPrettyString /** * Default [BufferedTensor] implementation for [Double] values diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt index 873ec9027..bc7d90c28 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -7,8 +7,10 @@ package space.kscience.kmath.tensors.core.algebras import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.* -import space.kscience.kmath.tensors.core.broadcastTensors -import space.kscience.kmath.tensors.core.broadcastTo +import space.kscience.kmath.tensors.core.internal.array +import space.kscience.kmath.tensors.core.internal.broadcastTensors +import space.kscience.kmath.tensors.core.internal.broadcastTo +import space.kscience.kmath.tensors.core.internal.tensor /** * Basic linear algebra operations implemented with broadcasting. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt deleted file mode 100644 index 23a2fa282..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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.algebras - -import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra -import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.tensor -import kotlin.math.* - -public object DoubleAnalyticTensorAlgebra : - AnalyticTensorAlgebra, - DoubleTensorAlgebra() { - - override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } - - override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim( - { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - arr.sum() / shape[dim] - }, - dim, - keepDim - ) - - override fun Tensor.std(): Double = this.fold { arr -> - val mean = arr.sum() / tensor.numElements - sqrt(arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1)) - } - - override fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( - { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - val mean = arr.sum() / shape[dim] - sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) - }, - dim, - keepDim - ) - - override fun Tensor.variance(): Double = this.fold { arr -> - val mean = arr.sum() / tensor.numElements - arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1) - } - - override fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( - { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - val mean = arr.sum() / shape[dim] - arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) - }, - dim, - keepDim - ) - - private fun cov(x: DoubleTensor, y:DoubleTensor): Double{ - val n = x.shape[0] - return ((x - x.mean()) * (y - y.mean())).mean() * n / (n - 1) - } - - override fun cov(tensors: List>): DoubleTensor { - check(tensors.isNotEmpty()) { "List must have at least 1 element" } - val n = tensors.size - val m = tensors[0].shape[0] - check(tensors.all { it.shape contentEquals intArrayOf(m) }) { "Tensors must have same shapes" } - val resTensor = DoubleTensor( - intArrayOf(n, n), - DoubleArray(n * n) {0.0} - ) - for (i in 0 until n){ - for (j in 0 until n){ - resTensor[intArrayOf(i, j)] = cov(tensors[i].tensor, tensors[j].tensor) - } - } - return resTensor - } - - override fun Tensor.exp(): DoubleTensor = tensor.map(::exp) - - override fun Tensor.ln(): DoubleTensor = tensor.map(::ln) - - override fun Tensor.sqrt(): DoubleTensor = tensor.map(::sqrt) - - override fun Tensor.cos(): DoubleTensor = tensor.map(::cos) - - override fun Tensor.acos(): DoubleTensor = tensor.map(::acos) - - override fun Tensor.cosh(): DoubleTensor = tensor.map(::cosh) - - override fun Tensor.acosh(): DoubleTensor = tensor.map(::acosh) - - override fun Tensor.sin(): DoubleTensor = tensor.map(::sin) - - override fun Tensor.asin(): DoubleTensor = tensor.map(::asin) - - override fun Tensor.sinh(): DoubleTensor = tensor.map(::sinh) - - override fun Tensor.asinh(): DoubleTensor = tensor.map(::asinh) - - override fun Tensor.tan(): DoubleTensor = tensor.map(::tan) - - override fun Tensor.atan(): DoubleTensor = tensor.map(::atan) - - override fun Tensor.tanh(): DoubleTensor = tensor.map(::tanh) - - override fun Tensor.atanh(): DoubleTensor = tensor.map(::atanh) - - override fun Tensor.ceil(): DoubleTensor = tensor.map(::ceil) - - override fun Tensor.floor(): DoubleTensor = tensor.map(::floor) - -} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt deleted file mode 100644 index 430482613..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ /dev/null @@ -1,278 +0,0 @@ -/* - * 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.algebras - -import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra -import space.kscience.kmath.nd.as1D -import space.kscience.kmath.nd.as2D -import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.* -import space.kscience.kmath.tensors.core.checkSquareMatrix -import space.kscience.kmath.tensors.core.choleskyHelper -import space.kscience.kmath.tensors.core.cleanSymHelper -import space.kscience.kmath.tensors.core.luHelper -import space.kscience.kmath.tensors.core.luMatrixDet -import space.kscience.kmath.tensors.core.luMatrixInv -import space.kscience.kmath.tensors.core.luPivotHelper -import space.kscience.kmath.tensors.core.pivInit -import kotlin.math.min - -/** - * Implementation of common linear algebra operations on double numbers. - * Implements the LinearOpsTensorAlgebra interface. - */ -public object DoubleLinearOpsTensorAlgebra : - LinearOpsTensorAlgebra, - DoubleTensorAlgebra() { - - override fun Tensor.inv(): DoubleTensor = invLU(1e-9) - - override fun Tensor.det(): DoubleTensor = detLU(1e-9) - - /** - * Computes the LU factorization of a matrix or batches of matrices `input`. - * Returns a tuple containing the LU factorization and pivots of `input`. - * - * @param epsilon permissible error when comparing the determinant of a matrix with zero - * @return pair of `factorization` and `pivots`. - * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. - * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. - */ - public fun Tensor.luFactor(epsilon: Double): Pair = - computeLU(tensor, epsilon) - ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") - - /** - * Computes the LU factorization of a matrix or batches of matrices `input`. - * Returns a tuple containing the LU factorization and pivots of `input`. - * Uses an error of ``1e-9`` when calculating whether a matrix is degenerate. - * - * @return pair of `factorization` and `pivots`. - * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. - * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. - */ - public fun Tensor.luFactor(): Pair = luFactor(1e-9) - - /** - * Unpacks the data and pivots from a LU factorization of a tensor. - * Given a tensor [luTensor], return tensors (P, L, U) satisfying ``P * luTensor = L * U``, - * with `P` being a permutation matrix or batch of matrices, - * `L` being a lower triangular matrix or batch of matrices, - * `U` being an upper triangular matrix or batch of matrices. - * - * @param luTensor the packed LU factorization data - * @param pivotsTensor the packed LU factorization pivots - * @return triple of P, L and U tensors - */ - public fun luPivot( - luTensor: Tensor, - pivotsTensor: Tensor - ): Triple { - checkSquareMatrix(luTensor.shape) - check( - luTensor.shape.dropLast(2).toIntArray() contentEquals pivotsTensor.shape.dropLast(1).toIntArray() || - luTensor.shape.last() == pivotsTensor.shape.last() - 1 - ) { "Inappropriate shapes of input tensors" } - - val n = luTensor.shape.last() - val pTensor = luTensor.zeroesLike() - pTensor - .matrixSequence() - .zip(pivotsTensor.tensor.vectorSequence()) - .forEach { (p, pivot) -> pivInit(p.as2D(), pivot.as1D(), n) } - - val lTensor = luTensor.zeroesLike() - val uTensor = luTensor.zeroesLike() - - lTensor.matrixSequence() - .zip(uTensor.matrixSequence()) - .zip(luTensor.tensor.matrixSequence()) - .forEach { (pairLU, lu) -> - val (l, u) = pairLU - luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) - } - - return Triple(pTensor, lTensor, uTensor) - } - - /** - * QR decomposition. - * - * Computes the QR decomposition of a matrix or a batch of matrices, and returns a pair `(Q, R)` of tensors. - * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q * R``, - * with `Q` being an orthogonal matrix or batch of orthogonal matrices - * and `R` being an upper triangular matrix or batch of upper triangular matrices. - * - * @param epsilon permissible error when comparing tensors for equality. - * Used when checking the positive definiteness of the input matrix or matrices. - * @return pair of Q and R tensors. - */ - public fun Tensor.cholesky(epsilon: Double): DoubleTensor { - checkSquareMatrix(shape) - checkPositiveDefinite(tensor, epsilon) - - val n = shape.last() - val lTensor = zeroesLike() - - for ((a, l) in tensor.matrixSequence().zip(lTensor.matrixSequence())) - for (i in 0 until n) choleskyHelper(a.as2D(), l.as2D(), n) - - return lTensor - } - - override fun Tensor.cholesky(): DoubleTensor = cholesky(1e-6) - - override fun Tensor.qr(): Pair { - checkSquareMatrix(shape) - val qTensor = zeroesLike() - val rTensor = zeroesLike() - tensor.matrixSequence() - .zip((qTensor.matrixSequence() - .zip(rTensor.matrixSequence()))).forEach { (matrix, qr) -> - val (q, r) = qr - qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) - } - - return qTensor to rTensor - } - - override fun Tensor.svd(): Triple = - svd(epsilon = 1e-10) - - /** - * Singular Value Decomposition. - * - * Computes the singular value decomposition of either a matrix or batch of matrices `input`. - * The singular value decomposition is represented as a triple `(U, S, V)`, - * such that ``input = U.dot(diagonalEmbedding(S).dot(V.T))``. - * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. - * - * @param epsilon permissible error when calculating the dot product of vectors, - * i.e. the precision with which the cosine approaches 1 in an iterative algorithm. - * @return triple `(U, S, V)`. - */ - public fun Tensor.svd(epsilon: Double): Triple { - val size = tensor.dimension - val commonShape = tensor.shape.sliceArray(0 until size - 2) - val (n, m) = tensor.shape.sliceArray(size - 2 until size) - val uTensor = zeros(commonShape + intArrayOf(min(n, m), n)) - val sTensor = zeros(commonShape + intArrayOf(min(n, m))) - val vTensor = zeros(commonShape + intArrayOf(min(n, m), m)) - - tensor.matrixSequence() - .zip(uTensor.matrixSequence() - .zip(sTensor.vectorSequence() - .zip(vTensor.matrixSequence()))).forEach { (matrix, USV) -> - val matrixSize = matrix.shape.reduce { acc, i -> acc * i } - val curMatrix = DoubleTensor( - matrix.shape, - matrix.mutableBuffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize) - .toDoubleArray() - ) - svdHelper(curMatrix, USV, m, n, epsilon) - } - - return Triple(uTensor.transpose(), sTensor, vTensor.transpose()) - } - - override fun Tensor.symEig(): Pair = - symEig(epsilon = 1e-15) - - /** - * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, - * represented by a pair (eigenvalues, eigenvectors). - * - * @param epsilon permissible error when comparing tensors for equality - * and when the cosine approaches 1 in the SVD algorithm. - * @return a pair (eigenvalues, eigenvectors) - */ - public fun Tensor.symEig(epsilon: Double): Pair { - checkSymmetric(tensor, epsilon) - val (u, s, v) = tensor.svd(epsilon) - val shp = s.shape + intArrayOf(1) - val utv = u.transpose() dot v - val n = s.shape.last() - for (matrix in utv.matrixSequence()) - cleanSymHelper(matrix.as2D(), n) - - val eig = (utv dot s.view(shp)).view(s.shape) - return eig to v - } - - /** - * Computes the determinant of a square matrix input, or of each square matrix in a batched input - * using LU factorization algorithm. - * - * @param epsilon error in the LU algorithm - permissible error when comparing the determinant of a matrix with zero - * @return the determinant. - */ - public fun Tensor.detLU(epsilon: Double = 1e-9): DoubleTensor { - - checkSquareMatrix(tensor.shape) - val luTensor = tensor.copy() - val pivotsTensor = tensor.setUpPivots() - - val n = shape.size - - val detTensorShape = IntArray(n - 1) { i -> shape[i] } - detTensorShape[n - 2] = 1 - val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } - - val detTensor = DoubleTensor( - detTensorShape, - resBuffer - ) - - luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (lu, pivots) -> - resBuffer[index] = if (luHelper(lu.as2D(), pivots.as1D(), epsilon)) - 0.0 else luMatrixDet(lu.as2D(), pivots.as1D()) - } - - return detTensor - } - - /** - * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input - * using LU factorization algorithm. - * Given a square matrix `a`, return the matrix `aInv` satisfying - * ``a.dot(aInv) = aInv.dot(a) = eye(a.shape[0])``. - * - * @param epsilon error in the LU algorithm - permissible error when comparing the determinant of a matrix with zero - * @return the multiplicative inverse of a matrix. - */ - public fun Tensor.invLU(epsilon: Double = 1e-9): DoubleTensor { - val (luTensor, pivotsTensor) = luFactor(epsilon) - val invTensor = luTensor.zeroesLike() - - val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) - for ((luP, invMatrix) in seq) { - val (lu, pivots) = luP - luMatrixInv(lu.as2D(), pivots.as1D(), invMatrix.as2D()) - } - - return invTensor - } - - /** - * LUP decomposition - * - * Computes the LUP decomposition of a matrix or a batch of matrices. - * Given a tensor `input`, return tensors (P, L, U) satisfying ``P * input = L * U``, - * with `P` being a permutation matrix or batch of matrices, - * `L` being a lower triangular matrix or batch of matrices, - * `U` being an upper triangular matrix or batch of matrices. - * - * @param epsilon permissible error when comparing the determinant of a matrix with zero - * @return triple of P, L and U tensors - */ - public fun Tensor.lu(epsilon: Double = 1e-9): Triple { - val (lu, pivots) = this.luFactor(epsilon) - return luPivot(lu, pivots) - } - - override fun Tensor.lu(): Triple = lu(1e-9) - -} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index e5d41f856..cb06432d0 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -5,28 +5,34 @@ package space.kscience.kmath.tensors.core.algebras +import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra +import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.* -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.fold -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.foldDim -import space.kscience.kmath.tensors.core.broadcastOuterTensors -import space.kscience.kmath.tensors.core.checkBufferShapeConsistency -import space.kscience.kmath.tensors.core.checkEmptyDoubleBuffer -import space.kscience.kmath.tensors.core.checkEmptyShape -import space.kscience.kmath.tensors.core.checkShapesCompatible -import space.kscience.kmath.tensors.core.checkTranspose -import space.kscience.kmath.tensors.core.checkView -import space.kscience.kmath.tensors.core.dotHelper -import space.kscience.kmath.tensors.core.getRandomNormals -import space.kscience.kmath.tensors.core.minusIndexFrom -import kotlin.math.abs +import space.kscience.kmath.tensors.core.internal.dotHelper +import space.kscience.kmath.tensors.core.internal.getRandomNormals +import space.kscience.kmath.tensors.core.internal.* +import space.kscience.kmath.tensors.core.internal.broadcastOuterTensors +import space.kscience.kmath.tensors.core.internal.checkBufferShapeConsistency +import space.kscience.kmath.tensors.core.internal.checkEmptyDoubleBuffer +import space.kscience.kmath.tensors.core.internal.checkEmptyShape +import space.kscience.kmath.tensors.core.internal.checkShapesCompatible +import space.kscience.kmath.tensors.core.internal.checkSquareMatrix +import space.kscience.kmath.tensors.core.internal.checkTranspose +import space.kscience.kmath.tensors.core.internal.checkView +import space.kscience.kmath.tensors.core.internal.minusIndexFrom +import kotlin.math.* /** * Implementation of basic operations over double tensors and basic algebra operations on them. */ -public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { +public open class DoubleTensorAlgebra : + TensorPartialDivisionAlgebra, + AnalyticTensorAlgebra, + LinearOpsTensorAlgebra { public companion object : DoubleTensorAlgebra() @@ -311,9 +317,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart) } - override fun Tensor.viewAs(other: Tensor): DoubleTensor { - return tensor.view(other.shape) - } + override fun Tensor.viewAs(other: Tensor): DoubleTensor = + tensor.view(other.shape) override infix fun Tensor.dot(other: Tensor): DoubleTensor { if (tensor.shape.size == 1 && other.shape.size == 1) { @@ -565,4 +570,350 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { x.withIndex().maxByOrNull { it.value }?.index!!.toDouble() }, dim, keepDim) + + override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } + + override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + arr.sum() / shape[dim] + }, + dim, + keepDim + ) + + override fun Tensor.std(): Double = this.fold { arr -> + val mean = arr.sum() / tensor.numElements + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1)) + } + + override fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val mean = arr.sum() / shape[dim] + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) + }, + dim, + keepDim + ) + + override fun Tensor.variance(): Double = this.fold { arr -> + val mean = arr.sum() / tensor.numElements + arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1) + } + + override fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val mean = arr.sum() / shape[dim] + arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) + }, + dim, + keepDim + ) + + private fun cov(x: DoubleTensor, y:DoubleTensor): Double{ + val n = x.shape[0] + return ((x - x.mean()) * (y - y.mean())).mean() * n / (n - 1) + } + + override fun cov(tensors: List>): DoubleTensor { + check(tensors.isNotEmpty()) { "List must have at least 1 element" } + val n = tensors.size + val m = tensors[0].shape[0] + check(tensors.all { it.shape contentEquals intArrayOf(m) }) { "Tensors must have same shapes" } + val resTensor = DoubleTensor( + intArrayOf(n, n), + DoubleArray(n * n) {0.0} + ) + for (i in 0 until n){ + for (j in 0 until n){ + resTensor[intArrayOf(i, j)] = cov(tensors[i].tensor, tensors[j].tensor) + } + } + return resTensor + } + + override fun Tensor.exp(): DoubleTensor = tensor.map(::exp) + + override fun Tensor.ln(): DoubleTensor = tensor.map(::ln) + + override fun Tensor.sqrt(): DoubleTensor = tensor.map(::sqrt) + + override fun Tensor.cos(): DoubleTensor = tensor.map(::cos) + + override fun Tensor.acos(): DoubleTensor = tensor.map(::acos) + + override fun Tensor.cosh(): DoubleTensor = tensor.map(::cosh) + + override fun Tensor.acosh(): DoubleTensor = tensor.map(::acosh) + + override fun Tensor.sin(): DoubleTensor = tensor.map(::sin) + + override fun Tensor.asin(): DoubleTensor = tensor.map(::asin) + + override fun Tensor.sinh(): DoubleTensor = tensor.map(::sinh) + + override fun Tensor.asinh(): DoubleTensor = tensor.map(::asinh) + + override fun Tensor.tan(): DoubleTensor = tensor.map(::tan) + + override fun Tensor.atan(): DoubleTensor = tensor.map(::atan) + + override fun Tensor.tanh(): DoubleTensor = tensor.map(::tanh) + + override fun Tensor.atanh(): DoubleTensor = tensor.map(::atanh) + + override fun Tensor.ceil(): DoubleTensor = tensor.map(::ceil) + + override fun Tensor.floor(): DoubleTensor = tensor.map(::floor) + + override fun Tensor.inv(): DoubleTensor = invLU(1e-9) + + override fun Tensor.det(): DoubleTensor = detLU(1e-9) + + /** + * Computes the LU factorization of a matrix or batches of matrices `input`. + * Returns a tuple containing the LU factorization and pivots of `input`. + * + * @param epsilon permissible error when comparing the determinant of a matrix with zero + * @return pair of `factorization` and `pivots`. + * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. + * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. + */ + public fun Tensor.luFactor(epsilon: Double): Pair = + computeLU(tensor, epsilon) + ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") + + /** + * Computes the LU factorization of a matrix or batches of matrices `input`. + * Returns a tuple containing the LU factorization and pivots of `input`. + * Uses an error of ``1e-9`` when calculating whether a matrix is degenerate. + * + * @return pair of `factorization` and `pivots`. + * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. + * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. + */ + public fun Tensor.luFactor(): Pair = luFactor(1e-9) + + /** + * Unpacks the data and pivots from a LU factorization of a tensor. + * Given a tensor [luTensor], return tensors (P, L, U) satisfying ``P * luTensor = L * U``, + * with `P` being a permutation matrix or batch of matrices, + * `L` being a lower triangular matrix or batch of matrices, + * `U` being an upper triangular matrix or batch of matrices. + * + * @param luTensor the packed LU factorization data + * @param pivotsTensor the packed LU factorization pivots + * @return triple of P, L and U tensors + */ + public fun luPivot( + luTensor: Tensor, + pivotsTensor: Tensor + ): Triple { + checkSquareMatrix(luTensor.shape) + check( + luTensor.shape.dropLast(2).toIntArray() contentEquals pivotsTensor.shape.dropLast(1).toIntArray() || + luTensor.shape.last() == pivotsTensor.shape.last() - 1 + ) { "Inappropriate shapes of input tensors" } + + val n = luTensor.shape.last() + val pTensor = luTensor.zeroesLike() + pTensor + .matrixSequence() + .zip(pivotsTensor.tensor.vectorSequence()) + .forEach { (p, pivot) -> pivInit(p.as2D(), pivot.as1D(), n) } + + val lTensor = luTensor.zeroesLike() + val uTensor = luTensor.zeroesLike() + + lTensor.matrixSequence() + .zip(uTensor.matrixSequence()) + .zip(luTensor.tensor.matrixSequence()) + .forEach { (pairLU, lu) -> + val (l, u) = pairLU + luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) + } + + return Triple(pTensor, lTensor, uTensor) + } + + /** + * QR decomposition. + * + * Computes the QR decomposition of a matrix or a batch of matrices, and returns a pair `(Q, R)` of tensors. + * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q * R``, + * with `Q` being an orthogonal matrix or batch of orthogonal matrices + * and `R` being an upper triangular matrix or batch of upper triangular matrices. + * + * @param epsilon permissible error when comparing tensors for equality. + * Used when checking the positive definiteness of the input matrix or matrices. + * @return pair of Q and R tensors. + */ + public fun Tensor.cholesky(epsilon: Double): DoubleTensor { + checkSquareMatrix(shape) + checkPositiveDefinite(tensor, epsilon) + + val n = shape.last() + val lTensor = zeroesLike() + + for ((a, l) in tensor.matrixSequence().zip(lTensor.matrixSequence())) + for (i in 0 until n) choleskyHelper(a.as2D(), l.as2D(), n) + + return lTensor + } + + override fun Tensor.cholesky(): DoubleTensor = cholesky(1e-6) + + override fun Tensor.qr(): Pair { + checkSquareMatrix(shape) + val qTensor = zeroesLike() + val rTensor = zeroesLike() + tensor.matrixSequence() + .zip((qTensor.matrixSequence() + .zip(rTensor.matrixSequence()))).forEach { (matrix, qr) -> + val (q, r) = qr + qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) + } + + return qTensor to rTensor + } + + override fun Tensor.svd(): Triple = + svd(epsilon = 1e-10) + + /** + * Singular Value Decomposition. + * + * Computes the singular value decomposition of either a matrix or batch of matrices `input`. + * The singular value decomposition is represented as a triple `(U, S, V)`, + * such that ``input = U.dot(diagonalEmbedding(S).dot(V.T))``. + * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. + * + * @param epsilon permissible error when calculating the dot product of vectors, + * i.e. the precision with which the cosine approaches 1 in an iterative algorithm. + * @return triple `(U, S, V)`. + */ + public fun Tensor.svd(epsilon: Double): Triple { + val size = tensor.dimension + val commonShape = tensor.shape.sliceArray(0 until size - 2) + val (n, m) = tensor.shape.sliceArray(size - 2 until size) + val uTensor = zeros(commonShape + intArrayOf(min(n, m), n)) + val sTensor = zeros(commonShape + intArrayOf(min(n, m))) + val vTensor = zeros(commonShape + intArrayOf(min(n, m), m)) + + tensor.matrixSequence() + .zip(uTensor.matrixSequence() + .zip(sTensor.vectorSequence() + .zip(vTensor.matrixSequence()))).forEach { (matrix, USV) -> + val matrixSize = matrix.shape.reduce { acc, i -> acc * i } + val curMatrix = DoubleTensor( + matrix.shape, + matrix.mutableBuffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize) + .toDoubleArray() + ) + svdHelper(curMatrix, USV, m, n, epsilon) + } + + return Triple(uTensor.transpose(), sTensor, vTensor.transpose()) + } + + override fun Tensor.symEig(): Pair = + symEig(epsilon = 1e-15) + + /** + * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, + * represented by a pair (eigenvalues, eigenvectors). + * + * @param epsilon permissible error when comparing tensors for equality + * and when the cosine approaches 1 in the SVD algorithm. + * @return a pair (eigenvalues, eigenvectors) + */ + public fun Tensor.symEig(epsilon: Double): Pair { + checkSymmetric(tensor, epsilon) + val (u, s, v) = tensor.svd(epsilon) + val shp = s.shape + intArrayOf(1) + val utv = u.transpose() dot v + val n = s.shape.last() + for (matrix in utv.matrixSequence()) + cleanSymHelper(matrix.as2D(), n) + + val eig = (utv dot s.view(shp)).view(s.shape) + return eig to v + } + + /** + * Computes the determinant of a square matrix input, or of each square matrix in a batched input + * using LU factorization algorithm. + * + * @param epsilon error in the LU algorithm - permissible error when comparing the determinant of a matrix with zero + * @return the determinant. + */ + public fun Tensor.detLU(epsilon: Double = 1e-9): DoubleTensor { + + checkSquareMatrix(tensor.shape) + val luTensor = tensor.copy() + val pivotsTensor = tensor.setUpPivots() + + val n = shape.size + + val detTensorShape = IntArray(n - 1) { i -> shape[i] } + detTensorShape[n - 2] = 1 + val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } + + val detTensor = DoubleTensor( + detTensorShape, + resBuffer + ) + + luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (lu, pivots) -> + resBuffer[index] = if (luHelper(lu.as2D(), pivots.as1D(), epsilon)) + 0.0 else luMatrixDet(lu.as2D(), pivots.as1D()) + } + + return detTensor + } + + /** + * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input + * using LU factorization algorithm. + * Given a square matrix `a`, return the matrix `aInv` satisfying + * ``a.dot(aInv) = aInv.dot(a) = eye(a.shape[0])``. + * + * @param epsilon error in the LU algorithm - permissible error when comparing the determinant of a matrix with zero + * @return the multiplicative inverse of a matrix. + */ + public fun Tensor.invLU(epsilon: Double = 1e-9): DoubleTensor { + val (luTensor, pivotsTensor) = luFactor(epsilon) + val invTensor = luTensor.zeroesLike() + + val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) + for ((luP, invMatrix) in seq) { + val (lu, pivots) = luP + luMatrixInv(lu.as2D(), pivots.as1D(), invMatrix.as2D()) + } + + return invTensor + } + + /** + * LUP decomposition + * + * Computes the LUP decomposition of a matrix or a batch of matrices. + * Given a tensor `input`, return tensors (P, L, U) satisfying ``P * input = L * U``, + * with `P` being a permutation matrix or batch of matrices, + * `L` being a lower triangular matrix or batch of matrices, + * `U` being an upper triangular matrix or batch of matrices. + * + * @param epsilon permissible error when comparing the determinant of a matrix with zero + * @return triple of P, L and U tensors + */ + public fun Tensor.lu(epsilon: Double = 1e-9): Triple { + val (lu, pivots) = this.luFactor(epsilon) + return luPivot(lu, pivots) + } + + override fun Tensor.lu(): Triple = lu(1e-9) + } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt similarity index 94% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt index dfac054b5..6324dc242 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt @@ -1,5 +1,11 @@ -package space.kscience.kmath.tensors.core +/* + * 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.internal + +import space.kscience.kmath.tensors.core.DoubleTensor import kotlin.math.max internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt similarity index 83% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt index f8bd5027a..0221c961e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt @@ -1,7 +1,12 @@ -package space.kscience.kmath.tensors.core +/* + * 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.internal import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra @@ -50,7 +55,7 @@ internal fun DoubleTensorAlgebra.checkSymmetric( "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } -internal fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { +internal fun DoubleTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { checkSymmetric(tensor, epsilon) for (mat in tensor.matrixSequence()) check(mat.asTensor().detLU().value() > 0.0) { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt similarity index 91% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt index 8adbfad39..23909f81e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt @@ -1,12 +1,17 @@ -package space.kscience.kmath.tensors.core +/* + * 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.internal import space.kscience.kmath.nd.MutableStructure1D import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra +import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.math.abs import kotlin.math.min import kotlin.math.sign @@ -114,7 +119,7 @@ internal fun BufferedTensor.setUpPivots(): IntTensor { ) } -internal fun DoubleLinearOpsTensorAlgebra.computeLU( +internal fun DoubleTensorAlgebra.computeLU( tensor: DoubleTensor, epsilon: Double ): Pair? { @@ -218,7 +223,7 @@ internal fun luMatrixInv( } } -internal fun DoubleLinearOpsTensorAlgebra.qrHelper( +internal fun DoubleTensorAlgebra.qrHelper( matrix: DoubleTensor, q: DoubleTensor, r: MutableStructure2D @@ -241,14 +246,14 @@ internal fun DoubleLinearOpsTensorAlgebra.qrHelper( } } } - r[j, j] = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + r[j, j] = DoubleTensorAlgebra { (v dot v).sqrt().value() } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } } } -internal fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { +internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { val (n, m) = a.shape var v: DoubleTensor val b: DoubleTensor @@ -264,7 +269,7 @@ internal fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double while (true) { lastV = v v = b.dot(lastV) - val norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + val norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } v = v.times(1.0 / norm) if (abs(v.dot(lastV).value()) > 1 - epsilon) { return v @@ -272,7 +277,7 @@ internal fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double } } -internal fun DoubleLinearOpsTensorAlgebra.svdHelper( +internal fun DoubleTensorAlgebra.svdHelper( matrix: DoubleTensor, USV: Pair, Pair, BufferedTensor>>, m: Int, n: Int, epsilon: Double @@ -298,12 +303,12 @@ internal fun DoubleLinearOpsTensorAlgebra.svdHelper( if (n > m) { v = svd1d(a, epsilon) u = matrix.dot(v) - norm = DoubleAnalyticTensorAlgebra { (u dot u).sqrt().value() } + norm = DoubleTensorAlgebra { (u dot u).sqrt().value() } u = u.times(1.0 / norm) } else { u = svd1d(a, epsilon) v = matrix.transpose(0, 1).dot(u) - norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } v = v.times(1.0 / norm) } 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/internal/tensorCastsUtils.kt similarity index 88% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt index 70e3b9c61..67cb0b842 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt @@ -3,11 +3,14 @@ * 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 +package space.kscience.kmath.tensors.core.internal 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.BufferedTensor +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.IntTensor import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure internal fun BufferedTensor.asTensor(): IntTensor = diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt similarity index 91% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt index 0211342bb..0ffaf39e7 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt @@ -1,9 +1,16 @@ -package space.kscience.kmath.tensors.core +/* + * 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.internal import space.kscience.kmath.nd.as1D import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.* +import space.kscience.kmath.tensors.core.BufferedTensor +import space.kscience.kmath.tensors.core.DoubleTensor import kotlin.math.* /** 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 index 2743a5218..814a1bb9b 100644 --- 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 @@ -6,6 +6,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.api.Tensor +import space.kscience.kmath.tensors.core.internal.tensor /** * Casts [Tensor] to [DoubleTensor] diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 6e3b4df60..80c7ab13a 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -3,6 +3,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.internal.* import kotlin.test.Test import kotlin.test.assertTrue diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 3ea19da26..4dcc367ca 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -1,7 +1,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.math.* import kotlin.test.Test @@ -28,73 +27,73 @@ internal class TestDoubleAnalyticTensorAlgebra { } @Test - fun testExp() = DoubleAnalyticTensorAlgebra { + fun testExp() = DoubleTensorAlgebra { assertTrue { tensor.exp() eq expectedTensor(::exp) } } @Test - fun testLog() = DoubleAnalyticTensorAlgebra { + fun testLog() = DoubleTensorAlgebra { assertTrue { tensor.ln() eq expectedTensor(::ln) } } @Test - fun testSqrt() = DoubleAnalyticTensorAlgebra { + fun testSqrt() = DoubleTensorAlgebra { assertTrue { tensor.sqrt() eq expectedTensor(::sqrt) } } @Test - fun testCos() = DoubleAnalyticTensorAlgebra { + fun testCos() = DoubleTensorAlgebra { assertTrue { tensor.cos() eq expectedTensor(::cos) } } @Test - fun testCosh() = DoubleAnalyticTensorAlgebra { + fun testCosh() = DoubleTensorAlgebra { assertTrue { tensor.cosh() eq expectedTensor(::cosh) } } @Test - fun testAcosh() = DoubleAnalyticTensorAlgebra { + fun testAcosh() = DoubleTensorAlgebra { assertTrue { tensor.acosh() eq expectedTensor(::acosh) } } @Test - fun testSin() = DoubleAnalyticTensorAlgebra { + fun testSin() = DoubleTensorAlgebra { assertTrue { tensor.sin() eq expectedTensor(::sin) } } @Test - fun testSinh() = DoubleAnalyticTensorAlgebra { + fun testSinh() = DoubleTensorAlgebra { assertTrue { tensor.sinh() eq expectedTensor(::sinh) } } @Test - fun testAsinh() = DoubleAnalyticTensorAlgebra { + fun testAsinh() = DoubleTensorAlgebra { assertTrue { tensor.asinh() eq expectedTensor(::asinh) } } @Test - fun testTan() = DoubleAnalyticTensorAlgebra { + fun testTan() = DoubleTensorAlgebra { assertTrue { tensor.tan() eq expectedTensor(::tan) } } @Test - fun testAtan() = DoubleAnalyticTensorAlgebra { + fun testAtan() = DoubleTensorAlgebra { assertTrue { tensor.atan() eq expectedTensor(::atan) } } @Test - fun testTanh() = DoubleAnalyticTensorAlgebra { + fun testTanh() = DoubleTensorAlgebra { assertTrue { tensor.tanh() eq expectedTensor(::tanh) } } @Test - fun testCeil() = DoubleAnalyticTensorAlgebra { + fun testCeil() = DoubleTensorAlgebra { assertTrue { tensor.ceil() eq expectedTensor(::ceil) } } @Test - fun testFloor() = DoubleAnalyticTensorAlgebra { + fun testFloor() = DoubleTensorAlgebra { assertTrue { tensor.floor() eq expectedTensor(::floor) } } @@ -145,7 +144,7 @@ internal class TestDoubleAnalyticTensorAlgebra { } @Test - fun testMean() = DoubleAnalyticTensorAlgebra { + fun testMean() = DoubleTensorAlgebra { assertTrue { tensor2.mean() == 1.0 } assertTrue { tensor2.mean(0, true) eq fromArray( intArrayOf(1, 2), 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 65070af7f..77748b15e 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 @@ -1,7 +1,9 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.internal.array +import space.kscience.kmath.tensors.core.internal.svd1d import kotlin.math.abs import kotlin.test.Test import kotlin.test.assertEquals @@ -10,7 +12,7 @@ import kotlin.test.assertTrue internal class TestDoubleLinearOpsTensorAlgebra { @Test - fun testDetLU() = DoubleLinearOpsTensorAlgebra { + fun testDetLU() = DoubleTensorAlgebra { val tensor = fromArray( intArrayOf(2, 2, 2), doubleArrayOf( @@ -35,7 +37,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testDet() = DoubleLinearOpsTensorAlgebra { + fun testDet() = DoubleTensorAlgebra { val expectedValue = 0.019827417 val m = fromArray( intArrayOf(3, 3), doubleArrayOf( @@ -49,7 +51,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testDetSingle() = DoubleLinearOpsTensorAlgebra { + fun testDetSingle() = DoubleTensorAlgebra { val expectedValue = 48.151623 val m = fromArray( intArrayOf(1, 1), doubleArrayOf( @@ -61,7 +63,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testInvLU() = DoubleLinearOpsTensorAlgebra { + fun testInvLU() = DoubleTensorAlgebra { val tensor = fromArray( intArrayOf(2, 2, 2), doubleArrayOf( @@ -86,14 +88,14 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testScalarProduct() = DoubleLinearOpsTensorAlgebra { + fun testScalarProduct() = DoubleTensorAlgebra { val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) assertEquals(a.dot(b).value(), 59.92) } @Test - fun testQR() = DoubleLinearOpsTensorAlgebra { + fun testQR() = DoubleTensorAlgebra { val shape = intArrayOf(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, @@ -114,7 +116,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testLU() = DoubleLinearOpsTensorAlgebra { + fun testLU() = DoubleTensorAlgebra { val shape = intArrayOf(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, @@ -134,7 +136,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testCholesky() = DoubleLinearOpsTensorAlgebra { + fun testCholesky() = DoubleTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 5), 0) val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) @@ -145,7 +147,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testSVD1D() = DoubleLinearOpsTensorAlgebra { + fun testSVD1D() = DoubleTensorAlgebra { val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = svd1d(tensor2) @@ -156,13 +158,13 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testSVD() = DoubleLinearOpsTensorAlgebra{ + fun testSVD() = DoubleTensorAlgebra{ testSVDFor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } @Test - fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { + fun testBatchedSVD() = DoubleTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) @@ -170,7 +172,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { + fun testBatchedSymEig() = DoubleTensorAlgebra { val tensor = randomNormal(shape = intArrayOf(2, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() @@ -182,7 +184,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } -private fun DoubleLinearOpsTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10): Unit { +private fun DoubleTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10): Unit { val svd = tensor.svd() val tensorSVD = svd.first diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 132735cc7..c4f9f94b0 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -8,6 +8,10 @@ import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.toDoubleArray import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.internal.array +import space.kscience.kmath.tensors.core.internal.asTensor +import space.kscience.kmath.tensors.core.internal.matrixSequence +import space.kscience.kmath.tensors.core.internal.toBufferedTensor import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index d782d78d9..ed858259e 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -3,6 +3,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.internal.array import kotlin.test.Test import kotlin.test.assertFalse import kotlin.test.assertTrue From 0ef64130aeae0deb5543b9c6f73af3a46f465394 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 13:00:30 +0100 Subject: [PATCH 191/211] TensorLinearStructure made internal --- .../space/kscience/kmath/tensors/DataSetNormalization.kt | 2 +- .../kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt | 2 +- .../kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt | 4 ++-- .../main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt | 2 +- examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt | 2 +- .../core/{algebras => }/BroadcastDoubleTensorAlgebra.kt | 3 +-- .../space/kscience/kmath/tensors/core/BufferedTensor.kt | 5 +++-- .../kmath/tensors/core/{algebras => }/DoubleTensorAlgebra.kt | 3 +-- .../core/{algebras => internal}/TensorLinearStructure.kt | 4 ++-- .../space/kscience/kmath/tensors/core/internal/checks.kt | 2 +- .../space/kscience/kmath/tensors/core/internal/linUtils.kt | 2 +- .../kscience/kmath/tensors/core/internal/tensorCastsUtils.kt | 1 - .../space/kscience/kmath/tensors/core/TestBroadcasting.kt | 2 -- .../kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt | 1 - .../kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 1 - .../space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 1 - .../kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt | 1 - 17 files changed, 15 insertions(+), 23 deletions(-) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{algebras => }/BroadcastDoubleTensorAlgebra.kt (97%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{algebras => }/DoubleTensorAlgebra.kt (99%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{algebras => internal}/TensorLinearStructure.kt (91%) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt index d029348f2..6fbf16a91 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra // Dataset normalization diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index c0ece04ca..78370b517 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra // solving linear system with LUP decomposition diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt index 1998b8d16..874ac8034 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt @@ -7,8 +7,8 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.toDoubleArray import kotlin.math.sqrt diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 497f63b41..42a0a4ba1 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import kotlin.math.abs diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt index d29dbb094..f8ac13d3f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra // simple PCA diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt similarity index 97% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index bc7d90c28..b8530f637 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -3,10 +3,9 @@ * 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.algebras +package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.internal.array import space.kscience.kmath.tensors.core.internal.broadcastTensors import space.kscience.kmath.tensors.core.internal.broadcastTo 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 e8c0556c2..858532abc 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,8 +1,9 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.Strides import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure +import space.kscience.kmath.tensors.core.internal.TensorLinearStructure /** * Represents [Tensor] over a [MutableBuffer] intended to be used through [DoubleTensor] and [IntTensor] @@ -16,7 +17,7 @@ public open class BufferedTensor internal constructor( /** * Buffer strides based on [TensorLinearStructure] implementation */ - public val linearStructure: TensorLinearStructure + public val linearStructure: Strides get() = TensorLinearStructure(shape) /** diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt similarity index 99% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index cb06432d0..d4a0f1433 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -3,7 +3,7 @@ * 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.algebras +package space.kscience.kmath.tensors.core import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D @@ -11,7 +11,6 @@ import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.internal.dotHelper import space.kscience.kmath.tensors.core.internal.getRandomNormals import space.kscience.kmath.tensors.core.internal.* diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/TensorLinearStructure.kt similarity index 91% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/TensorLinearStructure.kt index f65e2b955..4bdd987db 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/TensorLinearStructure.kt @@ -3,7 +3,7 @@ * 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.algebras +package space.kscience.kmath.tensors.core.internal import space.kscience.kmath.nd.Strides import kotlin.math.max @@ -44,7 +44,7 @@ internal fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArra * * @param shape the shape of the tensor. */ -public class TensorLinearStructure(override val shape: IntArray) : Strides { +internal class TensorLinearStructure(override val shape: IntArray) : Strides { override val strides: IntArray get() = stridesFromShape(shape) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt index 0221c961e..f1c158770 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.tensors.core.internal import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra internal fun checkEmptyShape(shape: IntArray) = diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt index 23909f81e..ff78ca64c 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt @@ -11,7 +11,7 @@ import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.* -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import kotlin.math.abs import kotlin.math.min import kotlin.math.sign diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt index 67cb0b842..d965b6bcd 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt @@ -11,7 +11,6 @@ import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.BufferedTensor import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.IntTensor -import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure internal fun BufferedTensor.asTensor(): IntTensor = IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 80c7ab13a..672089a3c 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -1,8 +1,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.internal.* import kotlin.test.Test import kotlin.test.assertTrue diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 4dcc367ca..05fedaa09 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -1,7 +1,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.math.* import kotlin.test.Test import kotlin.test.assertTrue 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 77748b15e..fddb37251 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 @@ -1,7 +1,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.internal.array import space.kscience.kmath.tensors.core.internal.svd1d import kotlin.math.abs diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index c4f9f94b0..d39b5c365 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -7,7 +7,6 @@ import space.kscience.kmath.nd.as2D import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.toDoubleArray -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.internal.array import space.kscience.kmath.tensors.core.internal.asTensor import space.kscience.kmath.tensors.core.internal.matrixSequence diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index ed858259e..354840719 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -2,7 +2,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.internal.array import kotlin.test.Test import kotlin.test.assertFalse From d31726a0d90de41ced32d211d3d929dd46f5091c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 13:12:18 +0100 Subject: [PATCH 192/211] produce routine --- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) 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 d4a0f1433..052d8d97e 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 @@ -56,6 +56,17 @@ public open class DoubleTensorAlgebra : return DoubleTensor(shape, buffer, 0) } + /** + * Constructs a tensor with the specified shape and initializer. + * + * @param shape the desired shape for the tensor. + * @param initializer mapping tensor indices to values. + * @return tensor with the [shape] shape and data generated by initializer. + */ + public fun produce(shape: IntArray, initializer: (IntArray) -> Double): DoubleTensor = + fromArray(shape, + TensorLinearStructure(shape).indices().map(initializer).toMutableList().toDoubleArray()) + override operator fun Tensor.get(i: Int): DoubleTensor { val lastShape = tensor.shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) From e80eefa90f5832de6b3c81487b27e7a355d38358 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 13:12:55 +0100 Subject: [PATCH 193/211] typo corrected --- .../space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 052d8d97e..5baf6c7ad 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 @@ -61,7 +61,7 @@ public open class DoubleTensorAlgebra : * * @param shape the desired shape for the tensor. * @param initializer mapping tensor indices to values. - * @return tensor with the [shape] shape and data generated by initializer. + * @return tensor with the [shape] shape and data generated by the [initializer]. */ public fun produce(shape: IntArray, initializer: (IntArray) -> Double): DoubleTensor = fromArray(shape, From d73d03c0558348af0d8de282664206b99fccf681 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 13:36:15 +0100 Subject: [PATCH 194/211] valueOrNull added --- .../kmath/tensors/LinearSystemSolvingWithLUP.kt | 2 +- .../space/kscience/kmath/tensors/OLSWithSVD.kt | 2 +- .../kscience/kmath/tensors/api/TensorAlgebra.kt | 3 ++- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 10 ++++------ .../kmath/tensors/core/internal/checks.kt | 4 ++-- .../kmath/tensors/core/internal/linUtils.kt | 15 ++++++++------- .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 6 +++--- .../kmath/tensors/core/TestDoubleTensor.kt | 2 +- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index 78370b517..4494d6799 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -69,7 +69,7 @@ fun main () { val n = l.shape[0] val x = zeros(intArrayOf(n)) for (i in 0 until n){ - x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)] + x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).valueOrNull()!!) / l[intArrayOf(i, i)] } return x } diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 42a0a4ba1..5d1883e7c 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -60,7 +60,7 @@ fun main() { require(yTrue.shape contentEquals yPred.shape) val diff = yTrue - yPred - return diff.dot(diff).sqrt().value() + return diff.dot(diff).sqrt().valueOrNull()!! } println("MSE: ${mse(alpha, alphaOLS)}") diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index e7f8dc7ae..78a36e229 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -16,11 +16,12 @@ import space.kscience.kmath.operations.Algebra public interface TensorAlgebra: Algebra> { /** + * * Returns a single tensor value of unit dimension. The tensor shape must be equal to [1]. * * @return the value of a scalar tensor. */ - public fun Tensor.value(): T + public fun Tensor.valueOrNull(): T? /** * Each element of the tensor [other] is added to this value. 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 5baf6c7ad..bf27a2690 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 @@ -35,12 +35,10 @@ public open class DoubleTensorAlgebra : public companion object : DoubleTensorAlgebra() - override fun Tensor.value(): Double { - check(tensor.shape contentEquals intArrayOf(1)) { - "Inconsistent value for tensor of shape ${shape.toList()}" - } - return tensor.mutableBuffer.array()[tensor.bufferStart] - } + override fun Tensor.valueOrNull(): Double? = if(tensor.shape contentEquals intArrayOf(1)) { + // Inconsistent value for tensor of with this shape + tensor.mutableBuffer.array()[tensor.bufferStart] + } else null /** * Constructs a tensor with the specified shape and data. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt index f1c158770..bfbc6334d 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt @@ -58,7 +58,7 @@ internal fun DoubleTensorAlgebra.checkSymmetric( internal fun DoubleTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { checkSymmetric(tensor, epsilon) for (mat in tensor.matrixSequence()) - check(mat.asTensor().detLU().value() > 0.0) { - "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" + check(mat.asTensor().detLU().valueOrNull()!! > 0.0) { + "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().valueOrNull()!!}" } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt index ff78ca64c..5c120c05f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt @@ -12,6 +12,7 @@ import space.kscience.kmath.nd.as2D import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra.Companion.valueOrNull import kotlin.math.abs import kotlin.math.min import kotlin.math.sign @@ -239,14 +240,14 @@ internal fun DoubleTensorAlgebra.qrHelper( val vv = v.as1D() if (j > 0) { for (i in 0 until j) { - r[i, j] = (qT[i] dot matrixT[j]).value() + r[i, j] = (qT[i] dot matrixT[j]).valueOrNull()!! for (k in 0 until n) { val qTi = qT[i].as1D() vv[k] = vv[k] - r[i, j] * qTi[k] } } } - r[j, j] = DoubleTensorAlgebra { (v dot v).sqrt().value() } + r[j, j] = DoubleTensorAlgebra { (v dot v).sqrt().valueOrNull()!! } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } @@ -269,9 +270,9 @@ internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10) while (true) { lastV = v v = b.dot(lastV) - val norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } + val norm = DoubleTensorAlgebra { (v dot v).sqrt().valueOrNull()!! } v = v.times(1.0 / norm) - if (abs(v.dot(lastV).value()) > 1 - epsilon) { + if (abs(v.dot(lastV).valueOrNull()!!) > 1 - epsilon) { return v } } @@ -292,7 +293,7 @@ internal fun DoubleTensorAlgebra.svdHelper( val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) for (i in 0 until u.shape[0]) { for (j in 0 until v.shape[0]) { - outerProduct[i * v.shape[0] + j] = u[i].value() * v[j].value() + outerProduct[i * v.shape[0] + j] = u[i].valueOrNull()!! * v[j].valueOrNull()!! } } a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct)) @@ -303,12 +304,12 @@ internal fun DoubleTensorAlgebra.svdHelper( if (n > m) { v = svd1d(a, epsilon) u = matrix.dot(v) - norm = DoubleTensorAlgebra { (u dot u).sqrt().value() } + norm = DoubleTensorAlgebra { (u dot u).sqrt().valueOrNull()!! } u = u.times(1.0 / norm) } else { u = svd1d(a, epsilon) v = matrix.transpose(0, 1).dot(u) - norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } + norm = DoubleTensorAlgebra { (v dot v).sqrt().valueOrNull()!! } v = v.times(1.0 / norm) } 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 fddb37251..99f00edbf 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 @@ -46,7 +46,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) ) - assertTrue { abs(m.det().value() - expectedValue) < 1e-5 } + assertTrue { abs(m.det().valueOrNull()!! - expectedValue) < 1e-5 } } @Test @@ -58,7 +58,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) ) - assertTrue { abs(m.det().value() - expectedValue) < 1e-5 } + assertTrue { abs(m.det().valueOrNull()!! - expectedValue) < 1e-5 } } @Test @@ -90,7 +90,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testScalarProduct() = DoubleTensorAlgebra { val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) - assertEquals(a.dot(b).value(), 59.92) + assertEquals(a.dot(b).valueOrNull()!!, 59.92) } @Test diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index d39b5c365..1afdb2263 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -21,7 +21,7 @@ internal class TestDoubleTensor { fun testValue() = DoubleTensorAlgebra { val value = 12.5 val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) - assertEquals(tensor.value(), value) + assertEquals(tensor.valueOrNull()!!, value) } @Test From 5b725a087b81b8c4f9206a4f9098b2cc01c4cd54 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 7 May 2021 15:53:09 +0300 Subject: [PATCH 195/211] new cast --- .../kmath/tensors/core/tensorCasts.kt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) 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 index 814a1bb9b..921bcf97e 100644 --- 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 @@ -35,3 +35,35 @@ public fun IntTensor.toIntArray(): IntArray { mutableBuffer[bufferStart + i] } } + +/** + * Casts [Array] to [DoubleTensor] + */ +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) +} + +/** + * Casts [Array] to [IntTensor] + */ +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) +} From 21b5d45b96878e89c464020994b3c7d931464c7f Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 14:13:07 +0100 Subject: [PATCH 196/211] Throwable value method --- .../tensors/LinearSystemSolvingWithLUP.kt | 2 +- .../kscience/kmath/tensors/OLSWithSVD.kt | 2 +- .../kmath/tensors/api/TensorAlgebra.kt | 10 ++++- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 44 ++++++++++++------- .../kmath/tensors/core/internal/checks.kt | 4 +- .../kmath/tensors/core/internal/linUtils.kt | 14 +++--- .../core/TestDoubleLinearOpsAlgebra.kt | 6 +-- .../kmath/tensors/core/TestDoubleTensor.kt | 2 +- 8 files changed, 51 insertions(+), 33 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index 4494d6799..78370b517 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -69,7 +69,7 @@ fun main () { val n = l.shape[0] val x = zeros(intArrayOf(n)) for (i in 0 until n){ - x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).valueOrNull()!!) / l[intArrayOf(i, i)] + x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)] } return x } diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 5d1883e7c..42a0a4ba1 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -60,7 +60,7 @@ fun main() { require(yTrue.shape contentEquals yPred.shape) val diff = yTrue - yPred - return diff.dot(diff).sqrt().valueOrNull()!! + return diff.dot(diff).sqrt().value() } println("MSE: ${mse(alpha, alphaOLS)}") diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 78a36e229..4718b6a58 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -15,13 +15,21 @@ import space.kscience.kmath.operations.Algebra */ public interface TensorAlgebra: Algebra> { + /** + * + * Returns a single tensor value of unit dimension if tensor shape equals to [1]. + * + * @return a nullable value of a potentially scalar tensor. + */ + public fun Tensor.valueOrNull(): T? + /** * * Returns a single tensor value of unit dimension. The tensor shape must be equal to [1]. * * @return the value of a scalar tensor. */ - public fun Tensor.valueOrNull(): T? + public fun Tensor.value(): T /** * Each element of the tensor [other] is added to this value. 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 bf27a2690..c1694644f 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 @@ -35,10 +35,11 @@ public open class DoubleTensorAlgebra : public companion object : DoubleTensorAlgebra() - override fun Tensor.valueOrNull(): Double? = if(tensor.shape contentEquals intArrayOf(1)) { - // Inconsistent value for tensor of with this shape - tensor.mutableBuffer.array()[tensor.bufferStart] - } else null + override fun Tensor.valueOrNull(): Double? = if (tensor.shape contentEquals intArrayOf(1)) + tensor.mutableBuffer.array()[tensor.bufferStart] else null + + override fun Tensor.value(): Double = + valueOrNull() ?: throw IllegalArgumentException("Inconsistent value for tensor of with $shape shape") /** * Constructs a tensor with the specified shape and data. @@ -62,8 +63,10 @@ public open class DoubleTensorAlgebra : * @return tensor with the [shape] shape and data generated by the [initializer]. */ public fun produce(shape: IntArray, initializer: (IntArray) -> Double): DoubleTensor = - fromArray(shape, - TensorLinearStructure(shape).indices().map(initializer).toMutableList().toDoubleArray()) + fromArray( + shape, + TensorLinearStructure(shape).indices().map(initializer).toMutableList().toDoubleArray() + ) override operator fun Tensor.get(i: Int): DoubleTensor { val lastShape = tensor.shape.drop(1).toIntArray() @@ -621,7 +624,7 @@ public open class DoubleTensorAlgebra : keepDim ) - private fun cov(x: DoubleTensor, y:DoubleTensor): Double{ + private fun cov(x: DoubleTensor, y: DoubleTensor): Double { val n = x.shape[0] return ((x - x.mean()) * (y - y.mean())).mean() * n / (n - 1) } @@ -633,10 +636,10 @@ public open class DoubleTensorAlgebra : check(tensors.all { it.shape contentEquals intArrayOf(m) }) { "Tensors must have same shapes" } val resTensor = DoubleTensor( intArrayOf(n, n), - DoubleArray(n * n) {0.0} + DoubleArray(n * n) { 0.0 } ) - for (i in 0 until n){ - for (j in 0 until n){ + for (i in 0 until n) { + for (j in 0 until n) { resTensor[intArrayOf(i, j)] = cov(tensors[i].tensor, tensors[j].tensor) } } @@ -779,8 +782,10 @@ public open class DoubleTensorAlgebra : val qTensor = zeroesLike() val rTensor = zeroesLike() tensor.matrixSequence() - .zip((qTensor.matrixSequence() - .zip(rTensor.matrixSequence()))).forEach { (matrix, qr) -> + .zip( + (qTensor.matrixSequence() + .zip(rTensor.matrixSequence())) + ).forEach { (matrix, qr) -> val (q, r) = qr qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) } @@ -812,9 +817,13 @@ public open class DoubleTensorAlgebra : val vTensor = zeros(commonShape + intArrayOf(min(n, m), m)) tensor.matrixSequence() - .zip(uTensor.matrixSequence() - .zip(sTensor.vectorSequence() - .zip(vTensor.matrixSequence()))).forEach { (matrix, USV) -> + .zip( + uTensor.matrixSequence() + .zip( + sTensor.vectorSequence() + .zip(vTensor.matrixSequence()) + ) + ).forEach { (matrix, USV) -> val matrixSize = matrix.shape.reduce { acc, i -> acc * i } val curMatrix = DoubleTensor( matrix.shape, @@ -918,10 +927,11 @@ public open class DoubleTensorAlgebra : * @return triple of P, L and U tensors */ public fun Tensor.lu(epsilon: Double = 1e-9): Triple { - val (lu, pivots) = this.luFactor(epsilon) + val (lu, pivots) = tensor.luFactor(epsilon) return luPivot(lu, pivots) } override fun Tensor.lu(): Triple = lu(1e-9) - } + + diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt index bfbc6334d..f1c158770 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt @@ -58,7 +58,7 @@ internal fun DoubleTensorAlgebra.checkSymmetric( internal fun DoubleTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { checkSymmetric(tensor, epsilon) for (mat in tensor.matrixSequence()) - check(mat.asTensor().detLU().valueOrNull()!! > 0.0) { - "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().valueOrNull()!!}" + check(mat.asTensor().detLU().value() > 0.0) { + "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt index 5c120c05f..7d3617547 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt @@ -240,14 +240,14 @@ internal fun DoubleTensorAlgebra.qrHelper( val vv = v.as1D() if (j > 0) { for (i in 0 until j) { - r[i, j] = (qT[i] dot matrixT[j]).valueOrNull()!! + r[i, j] = (qT[i] dot matrixT[j]).value() for (k in 0 until n) { val qTi = qT[i].as1D() vv[k] = vv[k] - r[i, j] * qTi[k] } } } - r[j, j] = DoubleTensorAlgebra { (v dot v).sqrt().valueOrNull()!! } + r[j, j] = DoubleTensorAlgebra { (v dot v).sqrt().value() } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } @@ -270,9 +270,9 @@ internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10) while (true) { lastV = v v = b.dot(lastV) - val norm = DoubleTensorAlgebra { (v dot v).sqrt().valueOrNull()!! } + val norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } v = v.times(1.0 / norm) - if (abs(v.dot(lastV).valueOrNull()!!) > 1 - epsilon) { + if (abs(v.dot(lastV).value()) > 1 - epsilon) { return v } } @@ -293,7 +293,7 @@ internal fun DoubleTensorAlgebra.svdHelper( val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) for (i in 0 until u.shape[0]) { for (j in 0 until v.shape[0]) { - outerProduct[i * v.shape[0] + j] = u[i].valueOrNull()!! * v[j].valueOrNull()!! + outerProduct[i * v.shape[0] + j] = u[i].value() * v[j].value() } } a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct)) @@ -304,12 +304,12 @@ internal fun DoubleTensorAlgebra.svdHelper( if (n > m) { v = svd1d(a, epsilon) u = matrix.dot(v) - norm = DoubleTensorAlgebra { (u dot u).sqrt().valueOrNull()!! } + norm = DoubleTensorAlgebra { (u dot u).sqrt().value() } u = u.times(1.0 / norm) } else { u = svd1d(a, epsilon) v = matrix.transpose(0, 1).dot(u) - norm = DoubleTensorAlgebra { (v dot v).sqrt().valueOrNull()!! } + norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } v = v.times(1.0 / norm) } 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 99f00edbf..fddb37251 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 @@ -46,7 +46,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) ) - assertTrue { abs(m.det().valueOrNull()!! - expectedValue) < 1e-5 } + assertTrue { abs(m.det().value() - expectedValue) < 1e-5 } } @Test @@ -58,7 +58,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) ) - assertTrue { abs(m.det().valueOrNull()!! - expectedValue) < 1e-5 } + assertTrue { abs(m.det().value() - expectedValue) < 1e-5 } } @Test @@ -90,7 +90,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testScalarProduct() = DoubleTensorAlgebra { val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) - assertEquals(a.dot(b).valueOrNull()!!, 59.92) + assertEquals(a.dot(b).value(), 59.92) } @Test diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 1afdb2263..d39b5c365 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -21,7 +21,7 @@ internal class TestDoubleTensor { fun testValue() = DoubleTensorAlgebra { val value = 12.5 val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) - assertEquals(tensor.valueOrNull()!!, value) + assertEquals(tensor.value(), value) } @Test From a5b72f201617752033941b50c1789cd5598902ec Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 14:15:48 +0100 Subject: [PATCH 197/211] Doc typo --- .../kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 4718b6a58..2eb18ada6 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -16,7 +16,6 @@ import space.kscience.kmath.operations.Algebra public interface TensorAlgebra: Algebra> { /** - * * Returns a single tensor value of unit dimension if tensor shape equals to [1]. * * @return a nullable value of a potentially scalar tensor. @@ -24,7 +23,6 @@ public interface TensorAlgebra: Algebra> { public fun Tensor.valueOrNull(): T? /** - * * Returns a single tensor value of unit dimension. The tensor shape must be equal to [1]. * * @return the value of a scalar tensor. From dde1db7b0afa27162988fcb1b3543afe6187a4d6 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 7 May 2021 23:05:37 +0300 Subject: [PATCH 198/211] fixes --- .../kmath/tensors/core/tensorCasts.kt | 40 ++----------------- 1 file changed, 4 insertions(+), 36 deletions(-) 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 index 921bcf97e..4e43ed1e1 100644 --- 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 @@ -9,17 +9,17 @@ import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.internal.tensor /** - * Casts [Tensor] to [DoubleTensor] + * Casts [Tensor] iof [Double] to [DoubleTensor] */ public fun Tensor.toDoubleTensor(): DoubleTensor = this.tensor /** - * Casts [Tensor] to [IntTensor] + * Casts [Tensor] iof [Int] to [IntTensor] */ public fun Tensor.toIntTensor(): IntTensor = this.tensor /** - * @return [DoubleArray] of tensor elements + * Returns [DoubleArray] of tensor elements */ public fun DoubleTensor.toDoubleArray(): DoubleArray { return DoubleArray(numElements) { i -> @@ -28,42 +28,10 @@ public fun DoubleTensor.toDoubleArray(): DoubleArray { } /** - * @return [IntArray] of tensor elements + * Returns [IntArray] of tensor elements */ public fun IntTensor.toIntArray(): IntArray { return IntArray(numElements) { i -> mutableBuffer[bufferStart + i] } } - -/** - * Casts [Array] to [DoubleTensor] - */ -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) -} - -/** - * Casts [Array] to [IntTensor] - */ -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) -} From 11a1624e64d2b779e84d25bf120698b49b400cc1 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 7 May 2021 23:06:41 +0300 Subject: [PATCH 199/211] fixes --- .../kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index 4e43ed1e1..142cb2156 100644 --- 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 @@ -9,12 +9,12 @@ import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.internal.tensor /** - * Casts [Tensor] iof [Double] to [DoubleTensor] + * Casts [Tensor] of [Double] to [DoubleTensor] */ public fun Tensor.toDoubleTensor(): DoubleTensor = this.tensor /** - * Casts [Tensor] iof [Int] to [IntTensor] + * Casts [Tensor] of [Int] to [IntTensor] */ public fun Tensor.toIntTensor(): IntTensor = this.tensor From 33e27cd99262d64533ccde72bbdb10b47c75d9fe Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 7 May 2021 23:07:02 +0300 Subject: [PATCH 200/211] fixed --- .../space/kscience/kmath/tensors/core/TestBroadcasting.kt | 2 +- .../kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt | 2 +- .../kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 2 -- .../space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 2 +- .../kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt | 2 +- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 672089a3c..35e605fd9 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -102,4 +102,4 @@ internal class TestBroadcasting { assertTrue(tensor32.mutableBuffer.array() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) } -} \ No newline at end of file +} diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 05fedaa09..3b4c615b4 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -155,4 +155,4 @@ internal class TestDoubleAnalyticTensorAlgebra { )} } -} \ No newline at end of file +} 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 fddb37251..347bb683f 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 @@ -194,5 +194,3 @@ private fun DoubleTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double assertTrue(tensor.eq(tensorSVD, epsilon)) } - - diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index d39b5c365..a6c6a7618 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -86,4 +86,4 @@ internal class TestDoubleTensor { assertEquals(ndArray[intArrayOf(0)], 1.0) } -} \ No newline at end of file +} diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 354840719..e7e898008 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -164,4 +164,4 @@ internal class TestDoubleTensorAlgebra { assertFalse(tensor1.eq(tensor3)) } -} \ No newline at end of file +} From e4e661a3bf4946eabd364ac93f62c9a8998e24c3 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 8 May 2021 14:10:57 +0300 Subject: [PATCH 201/211] Update jupyter integration --- .../kscience/kmath/structures/NDField.kt | 2 + kmath-jupyter/build.gradle.kts | 5 +- .../kscience/kmath/jupyter/KMathJupyter.kt | 61 +++++++++++-------- settings.gradle.kts | 16 +++-- 4 files changed, 48 insertions(+), 36 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt index cc1f5f680..501bf98db 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.structures +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import org.nd4j.linalg.factory.Nd4j import space.kscience.kmath.nd.* @@ -22,6 +23,7 @@ internal inline fun measureAndPrint(title: String, block: () -> Unit) { println("$title completed in $time millis") } +@OptIn(DelicateCoroutinesApi::class) fun main() { // initializing Nd4j Nd4j.zeros(0) diff --git a/kmath-jupyter/build.gradle.kts b/kmath-jupyter/build.gradle.kts index 815cb9b8c..83a6a771a 100644 --- a/kmath-jupyter/build.gradle.kts +++ b/kmath-jupyter/build.gradle.kts @@ -7,7 +7,10 @@ dependencies { api(project(":kmath-ast")) api(project(":kmath-complex")) api(project(":kmath-for-real")) - implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.3") +} + +kscience{ + useHtml() } readme { diff --git a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt index e13c92f75..78b25af47 100644 --- a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt +++ b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt @@ -19,49 +19,58 @@ import space.kscience.kmath.operations.RingOperations import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asSequence +/** + * A function for conversion of number to MST for pretty print + */ +public fun Number.toMst(): MST.Numeric = MST.Numeric(this) + @JupyterLibrary internal class KMathJupyter : JupyterIntegration() { private val mathRender = FeaturedMathRendererWithPostProcess.Default private val syntaxRender = MathMLSyntaxRenderer + private fun MST.toDisplayResult(): DisplayResult = HTML(createHTML().div { + unsafe { + +syntaxRender.renderWithStringBuilder(mathRender.render(this@toDisplayResult)) + } + }) + + private fun Unsafe.appendCellValue(it: Any?) { + when (it) { + is Number -> { + val s = StringBuilder() + syntaxRender.renderPart(mathRender.render(MST.Numeric(it)), s) + +s.toString() + } + is MST -> { + val s = StringBuilder() + syntaxRender.renderPart(mathRender.render(it), s) + +s.toString() + } + else -> { + +"" + +it.toString() + +"" + } + } + } + override fun Builder.onLoaded() { import( "space.kscience.kmath.ast.*", "space.kscience.kmath.ast.rendering.*", + "space.kscience.kmath.structures.*", "space.kscience.kmath.operations.*", "space.kscience.kmath.expressions.*", + "space.kscience.kmath.nd.*", "space.kscience.kmath.misc.*", "space.kscience.kmath.real.*", ) - fun MST.toDisplayResult(): DisplayResult = HTML(createHTML().div { - unsafe { - +syntaxRender.renderWithStringBuilder(mathRender.render(this@toDisplayResult)) - } - }) + import("space.kscience.kmath.jupyter.toMst") render { it.toDisplayResult() } - render { MST.Numeric(it).toDisplayResult() } - - fun Unsafe.appendCellValue(it: Any?) { - when (it) { - is Number -> { - val s = StringBuilder() - syntaxRender.renderPart(mathRender.render(MST.Numeric(it)), s) - +s.toString() - } - is MST -> { - val s = StringBuilder() - syntaxRender.renderPart(mathRender.render(it), s) - +s.toString() - } - else -> { - +"" - +it.toString() - +"" - } - } - } + //render { MST.Numeric(it).toDisplayResult() } render> { structure -> HTML(createHTML().div { diff --git a/settings.gradle.kts b/settings.gradle.kts index 90cc4aef1..27e74c902 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,25 +1,23 @@ pluginManagement { repositories { - mavenLocal() mavenCentral() gradlePluginPortal() maven("https://repo.kotlin.link") } - val toolsVersion = "0.9.5-dev-2" - val kotlinVersion = "1.5.0-RC" + val toolsVersion = "0.9.6" + val kotlinVersion = "1.5.0" plugins { + id("ru.mipt.npm.gradle.project") version toolsVersion + id("ru.mipt.npm.gradle.mpp") version toolsVersion + id("ru.mipt.npm.gradle.jvm") version toolsVersion kotlin("multiplatform") version kotlinVersion kotlin("jvm") version kotlinVersion kotlin("plugin.allopen") version kotlinVersion id("org.jetbrains.kotlinx.benchmark") version "0.3.0" - id("ru.mipt.npm.gradle.project") version toolsVersion - id("ru.mipt.npm.gradle.mpp") version toolsVersion - id("ru.mipt.npm.gradle.jvm") version toolsVersion - kotlin("jupyter.api") version "0.9.0.12" - kotlin("jvm") version kotlinVersion - kotlin("plugin.allopen") version kotlinVersion + kotlin("jupyter.api") version "0.9.1-61" + } } From 7ce0829597af279f54d368c4ef4ce643e7fa6f5a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 8 May 2021 14:20:16 +0300 Subject: [PATCH 202/211] 0.3.0-dev-8. Cleanup --- CHANGELOG.md | 1 + build.gradle.kts | 2 +- .../space/kscience/kmath/tensors/NeuralNetwork.kt | 8 ++++---- .../kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt | 2 +- .../kotlin/space/kscience/kmath/complex/Complex.kt | 9 +++++---- .../kotlin/space/kscience/kmath/complex/Quaternion.kt | 10 +++++----- .../kscience/kmath/stat/CommonsDistributionsTest.kt | 5 ++--- 7 files changed, 19 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5542b6563..286511327 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ - `contentEquals` from Buffer. It moved to the companion. - MSTExpression - Expression algebra builders +- Comples and Quaternion no longer are elements. ### Fixed - Ring inherits RingOperations, not GroupOperations diff --git a/build.gradle.kts b/build.gradle.kts index 760bf1aee..406a46810 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.0-dev-7" + version = "0.3.0-dev-8" } subprojects { diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt index 874ac8034..5b3c2e1cd 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt @@ -6,8 +6,8 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.toDoubleArray import kotlin.math.sqrt @@ -106,6 +106,7 @@ fun accuracy(yPred: DoubleTensor, yTrue: DoubleTensor): Double { } // neural network class +@OptIn(ExperimentalStdlibApi::class) class NeuralNetwork(private val layers: List) { private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra { @@ -120,7 +121,7 @@ class NeuralNetwork(private val layers: List) { (-onesForAnswers + softmaxValue) / (yPred.shape[0].toDouble()) } - @OptIn(ExperimentalStdlibApi::class) + private fun forward(x: DoubleTensor): List { var input = x @@ -133,7 +134,6 @@ class NeuralNetwork(private val layers: List) { } } - @OptIn(ExperimentalStdlibApi::class) private fun train(xTrain: DoubleTensor, yTrain: DoubleTensor) { val layerInputs = buildList { add(xTrain) @@ -180,7 +180,7 @@ fun main() { val features = 5 val sampleSize = 250 val trainSize = 180 - val testSize = sampleSize - trainSize + //val testSize = sampleSize - trainSize // take sample of features from normal distribution val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5 diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 42a0a4ba1..b42602988 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -48,7 +48,7 @@ fun main() { // inverse Sigma matrix can be restored from singular values with diagonalEmbedding function - val sigma = diagonalEmbedding(singValues.map{ x -> if (abs(x) < 1e-3) 0.0 else 1.0/x }) + val sigma = diagonalEmbedding(singValues.map{ if (abs(it) < 1e-3) 0.0 else 1.0/it }) val alphaOLS = v dot sigma dot u.transpose() dot y println("Estimated alpha:\n" + diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt index 8d626c17d..8e28337f6 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt @@ -9,7 +9,10 @@ import space.kscience.kmath.memory.MemoryReader import space.kscience.kmath.memory.MemorySpec import space.kscience.kmath.memory.MemoryWriter import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.operations.Norm +import space.kscience.kmath.operations.NumbersAddOperations +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MemoryBuffer import space.kscience.kmath.structures.MutableBuffer @@ -180,12 +183,10 @@ public object ComplexField : ExtendedField, Norm, Num * @property im The imaginary part. */ @OptIn(UnstableKMathAPI::class) -public data class Complex(val re: Double, val im: Double) : FieldElement { +public data class Complex(val re: Double, val im: Double) { public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble()) public constructor(re: Number) : this(re.toDouble(), 0.0) - public override val context: ComplexField get() = ComplexField - public override fun toString(): String = "($re + i*$im)" public companion object : MemorySpec { diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index 382b5cc05..c59aabdcb 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -27,8 +27,10 @@ public val Quaternion.conjugate: Quaternion */ public val Quaternion.reciprocal: Quaternion get() { - val n = QuaternionField { norm(this@reciprocal) } - return conjugate / (n * n) + QuaternionField { + val n = norm(this@reciprocal) + return conjugate / (n * n) + } } /** @@ -198,7 +200,7 @@ public object QuaternionField : Field, Norm, @OptIn(UnstableKMathAPI::class) public data class Quaternion( val w: Double, val x: Double, val y: Double, val z: Double, -) : FieldElement { +) { public constructor(w: Number, x: Number, y: Number, z: Number) : this( w.toDouble(), x.toDouble(), @@ -219,8 +221,6 @@ public data class Quaternion( require(!z.isNaN()) { "x-component of quaternion is not-a-number" } } - public override val context: QuaternionField get() = QuaternionField - /** * Returns a string representation of this quaternion. */ diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt index 066fd69e6..19c01e099 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -5,15 +5,14 @@ package space.kscience.kmath.stat -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import space.kscience.kmath.samplers.GaussianSampler internal class CommonsDistributionsTest { @Test - fun testNormalDistributionSuspend() = GlobalScope.launch { + fun testNormalDistributionSuspend() = runBlocking { val distribution = GaussianSampler(7.0, 2.0) val generator = RandomGenerator.default(1) val sample = distribution.sample(generator).nextBuffer(1000) From 6d78bb8d91a0236bb4f962c66a40ea74becdbcea Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 8 May 2021 14:36:37 +0300 Subject: [PATCH 203/211] 0.3.0-dev-8. Readme update --- README.md | 4 +- kmath-ast/README.md | 24 +- kmath-complex/README.md | 6 +- kmath-core/README.md | 6 +- kmath-ejml/README.md | 6 +- kmath-for-real/README.md | 6 +- kmath-functions/README.md | 6 +- kmath-nd4j/README.md | 6 +- kmath-tensors/README.md | 25 +- license/COPYRIGHT.txt | 15 - license/COPYRIGHT_HEADER.txt | 4 - license/LICENSE.txt | 201 ----------- license/README.md | 63 ---- license/third_party/cm_license.txt | 457 -------------------------- license/third_party/crng_license.txt | 275 ---------------- license/third_party/numky_license.txt | 201 ----------- 16 files changed, 47 insertions(+), 1258 deletions(-) delete mode 100644 license/COPYRIGHT.txt delete mode 100644 license/COPYRIGHT_HEADER.txt delete mode 100644 license/LICENSE.txt delete mode 100644 license/README.md delete mode 100644 license/third_party/cm_license.txt delete mode 100644 license/third_party/crng_license.txt delete mode 100644 license/third_party/numky_license.txt diff --git a/README.md b/README.md index 8796d7aac..c8da21b64 100644 --- a/README.md +++ b/README.md @@ -288,8 +288,8 @@ repositories { } dependencies { - api("space.kscience:kmath-core:0.3.0-dev-7") - // api("space.kscience:kmath-core-jvm:0.3.0-dev-7") for jvm-specific version + api("space.kscience:kmath-core:0.3.0-dev-8") + // api("space.kscience:kmath-core-jvm:0.3.0-dev-8") for jvm-specific version } ``` diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 26ee98ba5..646ab4306 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -10,7 +10,7 @@ Performance and visualization extensions to MST API. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-8`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0-dev-7' + implementation 'space.kscience:kmath-ast:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0-dev-7") + implementation("space.kscience:kmath-ast:0.3.0-dev-8") } ``` @@ -144,7 +144,7 @@ import space.kscience.kmath.misc.* @OptIn(UnstableKMathAPI::class) public fun main() { - val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath() + val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(12)+x^(2/3)".parseMath() val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst) val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax) println("LaTeX:") @@ -158,9 +158,9 @@ public fun main() { Result LaTeX: -![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{-12}) +![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3}) -Result MathML (embedding MathML is not allowed by GitHub Markdown): +Result MathML (can be used with MathJax or other renderers):
@@ -211,10 +211,20 @@ Result MathML (embedding MathML is not allowed by GitHub Markdown): - - 12 + + + + + x + + + 2 + / + 3 + + ``` diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 06e10fa7a..ee5ad416f 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-8`. **Gradle:** ```gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0-dev-7' + implementation 'space.kscience:kmath-complex:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0-dev-7") + implementation("space.kscience:kmath-complex:0.3.0-dev-8") } ``` diff --git a/kmath-core/README.md b/kmath-core/README.md index 36b30efcc..7283a18ce 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-8`. **Gradle:** ```gradle @@ -25,7 +25,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0-dev-7' + implementation 'space.kscience:kmath-core:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -36,6 +36,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0-dev-7") + implementation("space.kscience:kmath-core:0.3.0-dev-8") } ``` diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index 97c5ae115..cb12ef98d 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-8`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0-dev-7' + implementation 'space.kscience:kmath-ejml:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0-dev-7") + implementation("space.kscience:kmath-ejml:0.3.0-dev-8") } ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index a77f9d98b..8b3b8e9e0 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-8`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0-dev-7' + implementation 'space.kscience:kmath-for-real:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0-dev-7") + implementation("space.kscience:kmath-for-real:0.3.0-dev-8") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 2090ede3e..4f592c845 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-8`. **Gradle:** ```gradle @@ -21,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0-dev-7' + implementation 'space.kscience:kmath-functions:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0-dev-7") + implementation("space.kscience:kmath-functions:0.3.0-dev-8") } ``` diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index b4b586ea9..5f33c1db1 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-8`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0-dev-7' + implementation 'space.kscience:kmath-nd4j:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -30,7 +30,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0-dev-7") + implementation("space.kscience:kmath-nd4j:0.3.0-dev-8") } ``` diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index a81b7277c..7ece44217 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -1,40 +1,35 @@ # Module kmath-tensors -Common operations on tensors, the API consists of: +Common linear algebra operations on tensors. + + - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) + - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. + - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. - - [TensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic algebra operations on tensors (plus, dot, etc.) - - [TensorPartialDivisionAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt) : Emulates an algebra over a field - - [LinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Linear algebra operations including LU, QR, Cholesky LL and SVD decompositions - - [AnalyticTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt) : Element-wise analytic operations -The library offers a multiplatform implementation for this interface over the `Double`'s. As a highlight, the user can find: - - [BroadcastDoubleTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic algebra operations implemented with broadcasting. - - [DoubleLinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt) : Contains the power method for SVD and the spectrum of symmetric matrices. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-8`. **Gradle:** ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { - implementation 'space.kscience:kmath-tensors:0.3.0-dev-7' + implementation 'space.kscience:kmath-tensors:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { - implementation("space.kscience:kmath-tensors:0.3.0-dev-7") + implementation("space.kscience:kmath-tensors:0.3.0-dev-8") } ``` diff --git a/license/COPYRIGHT.txt b/license/COPYRIGHT.txt deleted file mode 100644 index 7bf2faffd..000000000 --- a/license/COPYRIGHT.txt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ \ No newline at end of file diff --git a/license/COPYRIGHT_HEADER.txt b/license/COPYRIGHT_HEADER.txt deleted file mode 100644 index 3e7d28489..000000000 --- a/license/COPYRIGHT_HEADER.txt +++ /dev/null @@ -1,4 +0,0 @@ -/* - * 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. - */ \ No newline at end of file diff --git a/license/LICENSE.txt b/license/LICENSE.txt deleted file mode 100644 index 84b106a07..000000000 --- a/license/LICENSE.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2018-2021 KMath contributors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/license/README.md b/license/README.md deleted file mode 100644 index cfef3de79..000000000 --- a/license/README.md +++ /dev/null @@ -1,63 +0,0 @@ -The Apache 2 license (given in full in LICENSE.txt) applies to all code in this repository, which is copyright by the -contributors of KMath. The following sections of the repository contain third-party code, to which different licenses -may apply: - -## KMath Libraries - -The following modules contain third-party code and are incorporated into the KMath Libraries: - -- Path: kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt - - License: Apache 2 ([cm](third_party/cm_license.txt)) - - Origin: Derived from Apache Commons Math, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt - - License: Apache 2 ([cm](third_party/cm_license.txt)) - - Origin: Derived from Apache Commons Math, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LoessInterpolator.kt - - License: Apache 2 ([cm](third_party/cm_license.txt)) - - Origin: Derived from Apache Commons Math, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt - - License: Apache 2 ([cm](third_party/cm_license.txt)) - - Origin: Derived from Apache Commons Math, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt - - License: Apache 2 ([numky](third_party/numky_license.txt)) - - Origin: Initial implementation was taken from Numky -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation - \ No newline at end of file diff --git a/license/third_party/cm_license.txt b/license/third_party/cm_license.txt deleted file mode 100644 index 6172c3fb2..000000000 --- a/license/third_party/cm_license.txt +++ /dev/null @@ -1,457 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - -Apache Commons Math includes the following code provided to the ASF under the -Apache License 2.0: - - - The inverse error function implementation in the Erf class is based on CUDA - code developed by Mike Giles, Oxford-Man Institute of Quantitative Finance, - and published in GPU Computing Gems, volume 2, 2010 (grant received on - March 23th 2013) - - The LinearConstraint, LinearObjectiveFunction, LinearOptimizer, - RelationShip, SimplexSolver and SimplexTableau classes in package - org.apache.commons.math3.optimization.linear include software developed by - Benjamin McCann (http://www.benmccann.com) and distributed with - the following copyright: Copyright 2009 Google Inc. (grant received on - March 16th 2009) - - The class "org.apache.commons.math3.exception.util.LocalizedFormatsTest" which - is an adapted version of "OrekitMessagesTest" test class for the Orekit library - - The "org.apache.commons.math3.analysis.interpolation.HermiteInterpolator" - has been imported from the Orekit space flight dynamics library. - -=============================================================================== - - - -APACHE COMMONS MATH DERIVATIVE WORKS: - -The Apache commons-math library includes a number of subcomponents -whose implementation is derived from original sources written -in C or Fortran. License terms of the original sources -are reproduced below. - -=============================================================================== -For the lmder, lmpar and qrsolv Fortran routine from minpack and translated in -the LevenbergMarquardtOptimizer class in package -org.apache.commons.math3.optimization.general -Original source copyright and license statement: - -Minpack Copyright Notice (1999) University of Chicago. All rights reserved - -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the -following conditions are met: - -1. Redistributions of source code must retain the above -copyright notice, this list of conditions and the following -disclaimer. - -2. Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following -disclaimer in the documentation and/or other materials -provided with the distribution. - -3. The end-user documentation included with the -redistribution, if any, must include the following -acknowledgment: - - "This product includes software developed by the - University of Chicago, as Operator of Argonne National - Laboratory. - -Alternately, this acknowledgment may appear in the software -itself, if and wherever such third-party acknowledgments -normally appear. - -4. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" -WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE -UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND -THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE -OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY -OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR -USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF -THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4) -DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION -UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL -BE CORRECTED. - -5. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT -HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF -ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT, -INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF -ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF -PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER -SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT -(INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE, -EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE -POSSIBILITY OF SUCH LOSS OR DAMAGES. -=============================================================================== - -Copyright and license statement for the odex Fortran routine developed by -E. Hairer and G. Wanner and translated in GraggBulirschStoerIntegrator class -in package org.apache.commons.math3.ode.nonstiff: - - -Copyright (c) 2004, Ernst Hairer - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -- Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -=============================================================================== - -Copyright and license statement for the original Mersenne twister C -routines translated in MersenneTwister class in package -org.apache.commons.math3.random: - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -=============================================================================== - -The initial code for shuffling an array (originally in class -"org.apache.commons.math3.random.RandomDataGenerator", now replaced by -a method in class "org.apache.commons.math3.util.MathArrays") was -inspired from the algorithm description provided in -"Algorithms", by Ian Craw and John Pulham (University of Aberdeen 1999). -The textbook (containing a proof that the shuffle is uniformly random) is -available here: - http://citeseerx.ist.psu.edu/viewdoc/download;?doi=10.1.1.173.1898&rep=rep1&type=pdf - -=============================================================================== -License statement for the direction numbers in the resource files for Sobol sequences. - ------------------------------------------------------------------------------ -Licence pertaining to sobol.cc and the accompanying sets of direction numbers - ------------------------------------------------------------------------------ -Copyright (c) 2008, Frances Y. Kuo and Stephen Joe -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the names of the copyright holders nor the names of the - University of New South Wales and the University of Waikato - and its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -=============================================================================== - -The initial commit of package "org.apache.commons.math3.ml.neuralnet" is -an adapted version of code developed in the context of the Data Processing -and Analysis Consortium (DPAC) of the "Gaia" project of the European Space -Agency (ESA). -=============================================================================== - -The initial commit of the class "org.apache.commons.math3.special.BesselJ" is -an adapted version of code translated from the netlib Fortran program, rjbesl -http://www.netlib.org/specfun/rjbesl by R.J. Cody at Argonne National -Laboratory (USA). There is no license or copyright statement included with the -original Fortran sources. -=============================================================================== - - -The BracketFinder (package org.apache.commons.math3.optimization.univariate) -and PowellOptimizer (package org.apache.commons.math3.optimization.general) -classes are based on the Python code in module "optimize.py" (version 0.5) -developed by Travis E. Oliphant for the SciPy library (http://www.scipy.org/) -Copyright © 2003-2009 SciPy Developers. - -SciPy license -Copyright © 2001, 2002 Enthought, Inc. -All rights reserved. - -Copyright © 2003-2013 SciPy Developers. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of Enthought nor the names of the SciPy Developers may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -=============================================================================== diff --git a/license/third_party/crng_license.txt b/license/third_party/crng_license.txt deleted file mode 100644 index dec0e2a5c..000000000 --- a/license/third_party/crng_license.txt +++ /dev/null @@ -1,275 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -================================================================================ - -Class "org.apache.commons.rng.core.source64.MersenneTwister64" contains -Java code partly ported from the reference implementation in C. -That source file contained the following notice: - - Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -================================================================================ - -Class "org.apache.commons.rng.core.source32.MersenneTwister" contains -Java code partly ported from the reference implementation in C. -That source file contained the following notice: - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -================================================================================ \ No newline at end of file diff --git a/license/third_party/numky_license.txt b/license/third_party/numky_license.txt deleted file mode 100644 index f49a4e16e..000000000 --- a/license/third_party/numky_license.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file From bbef697b7dc553281af826ece76373af469fab0e Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 9 May 2021 18:10:06 +0700 Subject: [PATCH 204/211] Document and change retention for UnstableKMathAPI --- .../kotlin/space/kscience/kmath/misc/annotations.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt index 206e4e000..7f53d96ce 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt @@ -5,5 +5,13 @@ package space.kscience.kmath.misc +/** + * Marks declarations that are still experimental in the KMath APIs, which means that the design of the corresponding + * declarations has open issues which may (or may not) lead to their changes in the future. Roughly speaking, there is + * a chance that those declarations will be deprecated in the near future or the semantics of their behavior may change + * in some way that may break some code. + */ +@MustBeDocumented +@Retention(value = AnnotationRetention.BINARY) @RequiresOptIn("This API is unstable and could change in future", RequiresOptIn.Level.WARNING) public annotation class UnstableKMathAPI From e2920ed68390bf29ee0854da85d69efd53c6a5a3 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 9 May 2021 16:40:10 +0700 Subject: [PATCH 205/211] Promote kmath-kotlingrad to experimental alongside minor documentation and API changes --- CHANGELOG.md | 3 +- README.md | 9 +++-- kmath-kotlingrad/README.md | 34 +++++++++++++++++++ kmath-kotlingrad/build.gradle.kts | 20 +++++++++-- kmath-kotlingrad/docs/README-TEMPLATE.md | 7 ++++ .../kotlingrad/DifferentiableMstExpression.kt | 17 +++++----- .../kscience/kmath/kotlingrad/KMathNumber.kt | 25 +++++++++----- .../kmath/kotlingrad/ScalarsAdapters.kt | 26 +++++++------- .../kmath/kotlingrad/AdaptingTests.kt | 6 +--- 9 files changed, 106 insertions(+), 41 deletions(-) create mode 100644 kmath-kotlingrad/README.md create mode 100644 kmath-kotlingrad/docs/README-TEMPLATE.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 286511327..4fba361d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - Move MST to core - Separated benchmarks and examples - Rewritten EJML module without ejml-simple +- Stability of kmath-ast and kmath-kotilngrad promoted to EXPERIMENTAL. ### Deprecated @@ -35,7 +36,7 @@ - `contentEquals` from Buffer. It moved to the companion. - MSTExpression - Expression algebra builders -- Comples and Quaternion no longer are elements. +- Complex and Quaternion no longer are elements. ### Fixed - Ring inherits RingOperations, not GroupOperations diff --git a/README.md b/README.md index c8da21b64..3b4387c1b 100644 --- a/README.md +++ b/README.md @@ -207,9 +207,14 @@ One can still use generic algebras though.
* ### [kmath-kotlingrad](kmath-kotlingrad) -> +> Functions, integration and interpolation > -> **Maturity**: PROTOTYPE +> **Maturity**: EXPERIMENTAL +> +> **Features:** +> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : MST based DifferentiableExpression. +> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : Conversions between Kotlin∇'s SFun and MST +
* ### [kmath-memory](kmath-memory) diff --git a/kmath-kotlingrad/README.md b/kmath-kotlingrad/README.md new file mode 100644 index 000000000..686df3271 --- /dev/null +++ b/kmath-kotlingrad/README.md @@ -0,0 +1,34 @@ +# Module kmath-kotlingrad + +[Kotlin∇](https://github.com/breandan/kotlingrad) integration module. + + - [differentiable-mst-expression](src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : MST based DifferentiableExpression. + - [differentiable-mst-expression](src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : Conversions between Kotlin∇'s SFun and MST + + +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0-dev-8`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + mavenCentral() +} + +dependencies { + implementation 'space.kscience:kmath-kotlingrad:0.3.0-dev-8' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + mavenCentral() +} + +dependencies { + implementation("space.kscience:kmath-kotlingrad:0.3.0-dev-8") +} +``` diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index ed5b5bcb4..0e8e49971 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -4,11 +4,27 @@ plugins { } dependencies { - api("com.github.breandan:kaliningraph:0.1.4") + api("com.github.breandan:kaliningraph:0.1.6") api("com.github.breandan:kotlingrad:0.4.5") api(project(":kmath-ast")) } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + description = "Functions, integration and interpolation" + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + + feature( + "differentiable-mst-expression", + "src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt", + ) { + "MST based DifferentiableExpression." + } + + feature( + "differentiable-mst-expression", + "src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt", + ) { + "Conversions between Kotlin∇'s SFun and MST" + } } diff --git a/kmath-kotlingrad/docs/README-TEMPLATE.md b/kmath-kotlingrad/docs/README-TEMPLATE.md new file mode 100644 index 000000000..ac38c849b --- /dev/null +++ b/kmath-kotlingrad/docs/README-TEMPLATE.md @@ -0,0 +1,7 @@ +# Module kmath-kotlingrad + +[Kotlin∇](https://www.htmlsymbols.xyz/unicode/U+2207) integration module. + +${features} + +${artifact} diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt index 222145d2d..8c6745c79 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.api.SFun +import edu.umontreal.kotlingrad.api.SVar import space.kscience.kmath.expressions.DifferentiableExpression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MstAlgebra @@ -14,20 +15,20 @@ import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.NumericAlgebra /** - * Represents wrapper of [MstExpression] implementing [DifferentiableExpression]. + * Represents [MST] based [DifferentiableExpression]. * - * The principle of this API is converting the [mst] to an [SFun], differentiating it with Kotlin∇, then converting - * [SFun] back to [MST]. + * The principle of this API is converting the [mst] to an [SFun], differentiating it with + * [Kotlin∇](https://github.com/breandan/kotlingrad), then converting [SFun] back to [MST]. * - * @param T the type of number. - * @param A the [NumericAlgebra] of [T]. - * @property expr the underlying [MstExpression]. + * @param T The type of number. + * @param A The [NumericAlgebra] of [T]. + * @property algebra The [A] instance. + * @property mst The [MST] node. */ public class DifferentiableMstExpression>( public val algebra: A, public val mst: MST, ) : DifferentiableExpression> { - public override fun invoke(arguments: Map): T = mst.interpret(algebra, arguments) public override fun derivativeOrNull(symbols: List): DifferentiableMstExpression = @@ -35,7 +36,7 @@ public class DifferentiableMstExpression>( algebra, symbols.map(Symbol::identity) .map(MstAlgebra::bindSymbol) - .map { it.toSVar>() } + .map>>(MST.Symbolic::toSVar) .fold(mst.toSFun(), SFun>::d) .toMst(), ) diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt index 0c3768dcc..9c9d07b81 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt @@ -5,19 +5,26 @@ package space.kscience.kmath.kotlingrad -import edu.umontreal.kotlingrad.api.RealNumber import edu.umontreal.kotlingrad.api.SConst import space.kscience.kmath.operations.NumericAlgebra /** - * Implements [RealNumber] by delegating its functionality to [NumericAlgebra]. + * Implements [SConst] by delegating its functionality to [NumericAlgebra]. * - * @param T the type of number. - * @param A the [NumericAlgebra] of [T]. - * @property algebra the algebra. - * @param value the value of this number. + * @param T The type of number. + * @param A The [NumericAlgebra] over [T]. + * @property algebra The algebra. + * @property value The value of this number. */ -public class KMathNumber(public val algebra: A, value: T) : - RealNumber, T>(value) where T : Number, A : NumericAlgebra { - public override fun wrap(number: Number): SConst> = SConst(algebra.number(number)) +public class KMathNumber(public val algebra: A, public override val value: T) : + SConst>(value) where T : Number, A : NumericAlgebra { + /** + * Returns a string representation of the [value]. + */ + public override fun toString(): String = value.toString() + + /** + * Wraps [Number] to [KMathNumber]. + */ + public override fun wrap(number: Number): KMathNumber = KMathNumber(algebra, algebra.number(number)) } diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt index f65d2948d..bee2c9e3e 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -15,16 +15,16 @@ import space.kscience.kmath.operations.* /** * Maps [SVar] to [MST.Symbolic] directly. * - * @receiver the variable. - * @return a node. + * @receiver The variable. + * @returnAa node. */ public fun > SVar.toMst(): MST.Symbolic = MstAlgebra.bindSymbol(name) /** * Maps [SVar] to [MST.Numeric] directly. * - * @receiver the constant. - * @return a node. + * @receiver The constant. + * @return A node. */ public fun > SConst.toMst(): MST.Numeric = MstAlgebra.number(doubleValue) @@ -49,8 +49,8 @@ public fun > SConst.toMst(): MST.Numeric = MstAlgebra.number(doub * - [VSumAll] is requested to be evaluated; * - [Derivative] is requested to be evaluated. * - * @receiver the scalar function. - * @return a node. + * @receiver The scalar function. + * @return A node. */ public fun > SFun.toMst(): MST = MstExtendedField { when (this@toMst) { @@ -74,17 +74,16 @@ public fun > SFun.toMst(): MST = MstExtendedField { /** * Maps [MST.Numeric] to [SConst] directly. * - * @receiver the node. - * @return a new constant. + * @receiver The node. + * @return A new constant. */ public fun > MST.Numeric.toSConst(): SConst = SConst(value) /** * Maps [MST.Symbolic] to [SVar] directly. * - * @receiver the node. - * @param proto the prototype instance. - * @return a new variable. + * @receiver The node. + * @return A new variable. */ internal fun > MST.Symbolic.toSVar(): SVar = SVar(value) @@ -98,9 +97,8 @@ internal fun > MST.Symbolic.toSVar(): SVar = SVar(value) * - [MST.Unary] -> [Negative], [Sine], [Cosine], [Tangent], [Power], [Log]; * - [MST.Binary] -> [Sum], [Prod], [Power]. * - * @receiver the node. - * @param proto the prototype instance. - * @return a scalar function. + * @receiver The node. + * @return A scalar function. */ public fun > MST.toSFun(): SFun = when (this) { is MST.Numeric -> toSConst() diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index 3ed73451d..85c964c58 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -10,7 +10,7 @@ import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.MstAlgebra import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol +import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals @@ -65,8 +65,4 @@ internal class AdaptingTests { assertEquals(actualDerivative(x to 0.1), expectedDerivative(x to 0.1)) } - - private companion object { - private val x by symbol - } } From e5f3ee75be375f457c342ab5fc02ff0f324c6490 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 12 May 2021 19:40:10 +0100 Subject: [PATCH 206/211] tensors readme fix --- README.md | 7 ++++--- kmath-tensors/README.md | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3b4387c1b..c3def902b 100644 --- a/README.md +++ b/README.md @@ -247,9 +247,10 @@ One can still use generic algebras though. > **Maturity**: PROTOTYPE > > **Features:** -> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) -> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. -> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. +> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Interface for basic linear algebra operations on tensors (plus, dot, etc.) +> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Interface for advanced linear algebra operations like LU decomposition, SVD, etc. +> - [tensor algebra over Double](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s +> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting for tensors over `Double`'s.
diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 7ece44217..586bb8ac6 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -2,10 +2,10 @@ Common linear algebra operations on tensors. - - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) - - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. - - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. - + - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Interface for basic linear algebra operations on tensors (plus, dot, etc.) + - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Interface for advanced linear algebra operations like LU decomposition, SVD, etc. + - [tensor algebra over Double](src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s + - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting for tensors over `Double`'s. ## Artifact: From d721c4b5976072dae740243b2f1cefee5fcbe2b2 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 12 May 2021 19:43:08 +0100 Subject: [PATCH 207/211] typo found --- README.md | 2 +- kmath-tensors/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c3def902b..519472a69 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,7 @@ One can still use generic algebras though. > **Features:** > - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Interface for basic linear algebra operations on tensors (plus, dot, etc.) > - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Interface for advanced linear algebra operations like LU decomposition, SVD, etc. -> - [tensor algebra over Double](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s +> - [tensor algebra over Double](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s. > - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting for tensors over `Double`'s.
diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 586bb8ac6..affdad665 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -4,7 +4,7 @@ Common linear algebra operations on tensors. - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Interface for basic linear algebra operations on tensors (plus, dot, etc.) - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Interface for advanced linear algebra operations like LU decomposition, SVD, etc. - - [tensor algebra over Double](src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s + - [tensor algebra over Double](src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s. - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting for tensors over `Double`'s. ## Artifact: From 97c4b817173637818f1b496580afc688af8825d2 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 13 May 2021 11:02:20 +0300 Subject: [PATCH 208/211] Introduce PerformancePitfall annotation --- CHANGELOG.md | 1 + LICENSE | 201 ------------------ .../space/kscience/kmath/data/ColumnarData.kt | 2 + .../kscience/kmath/data/XYColumnarData.kt | 2 + .../kmath/linear/BufferedLinearSpace.kt | 3 + .../space/kscience/kmath/misc/annotations.kt | 12 ++ .../space/kscience/kmath/nd/BufferND.kt | 2 + .../space/kscience/kmath/nd/Structure1D.kt | 21 +- .../space/kscience/kmath/nd/Structure2D.kt | 8 +- .../space/kscience/kmath/nd/StructureND.kt | 4 + .../kmath/linear/DoubleLUSolverTest.kt | 2 + .../space/kscience/kmath/linear/MatrixTest.kt | 2 + .../kmath/structures/NumberNDFieldTest.kt | 2 + .../kmath/structures/LazyStructureND.kt | 2 + .../kscience/kmath/ejml/EjmlMatrixTest.kt | 2 + .../space/kscience/kmath/real/RealMatrix.kt | 4 + .../kaceince/kmath/real/DoubleMatrixTest.kt | 2 + .../kscience/kmath/jupyter/KMathJupyter.kt | 4 +- .../kscience/kmath/nd4j/Nd4jArrayStructure.kt | 2 + .../kmath/tensors/core/BufferedTensor.kt | 6 +- .../kmath/viktor/ViktorStructureND.kt | 2 + 21 files changed, 75 insertions(+), 211 deletions(-) delete mode 100644 LICENSE diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fba361d5..286be25e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Integration for any Field element - Extended operations for ND4J fields - Jupyter Notebook integration module (kmath-jupyter) +- `@PerformancePitfall` annotation to mark possibly slow API ### Changed - Exponential operations merged with hyperbolic functions diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt index abbb46583..febf615a8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.data +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D @@ -25,6 +26,7 @@ public interface ColumnarData { * A zero-copy method to represent a [Structure2D] as a two-column x-y data. * There could more than two columns in the structure. */ +@OptIn(PerformancePitfall::class) @UnstableKMathAPI public fun Structure2D.asColumnarData(mapping: Map): ColumnarData { require(shape[1] >= mapping.maxOf { it.value }) { "Column index out of bounds" } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt index 663908e90..56bb59826 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.data +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D @@ -49,6 +50,7 @@ public fun XYColumnarData(x: Buffer, y: Buffer): XYColum * A zero-copy method to represent a [Structure2D] as a two-column x-y data. * There could more than two columns in the structure. */ +@OptIn(PerformancePitfall::class) @UnstableKMathAPI public fun Structure2D.asXYData(xIndex: Int = 0, yIndex: Int = 1): XYColumnarData { require(shape[1] >= max(xIndex, yIndex)) { "Column index out of bounds" } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt index 62d2408e3..9b4451a62 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.linear +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.invoke @@ -50,6 +51,7 @@ public class BufferedLinearSpace>( this } + @OptIn(PerformancePitfall::class) override fun Matrix.dot(other: Matrix): Matrix { require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } return elementAlgebra { @@ -67,6 +69,7 @@ public class BufferedLinearSpace>( } } + @OptIn(PerformancePitfall::class) override fun Matrix.dot(vector: Point): Point { require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } return elementAlgebra { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt index 7f53d96ce..18718de97 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt @@ -15,3 +15,15 @@ package space.kscience.kmath.misc @Retention(value = AnnotationRetention.BINARY) @RequiresOptIn("This API is unstable and could change in future", RequiresOptIn.Level.WARNING) public annotation class UnstableKMathAPI + +/** + * Marks API which could cause performance problems. The code, marked by this API is not necessary slow, but could cause + * slow-down in some cases. Refer to the documentation and benchmark it to be sure. + */ +@MustBeDocumented +@Retention(value = AnnotationRetention.BINARY) +@RequiresOptIn( + "Refer to the documentation to use this API in performance-critical code", + RequiresOptIn.Level.WARNING +) +public annotation class PerformancePitfall diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt index 1f608f478..425808aeb 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.MutableBuffer @@ -32,6 +33,7 @@ public open class BufferND( override val shape: IntArray get() = strides.shape + @PerformancePitfall override fun elements(): Sequence> = strides.indices().map { it to this[it] } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 8ea6d0f02..cc0528793 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.asMutableBuffer @@ -46,6 +47,8 @@ private value class Structure1DWrapper(val structure: StructureND) : Struc override val size: Int get() = structure.shape[0] override operator fun get(index: Int): T = structure[index] + + @PerformancePitfall override fun elements(): Sequence> = structure.elements() } @@ -55,6 +58,8 @@ private value class Structure1DWrapper(val structure: StructureND) : Struc private class MutableStructure1DWrapper(val structure: MutableStructureND) : MutableStructure1D { override val shape: IntArray get() = structure.shape override val size: Int get() = structure.shape[0] + + @PerformancePitfall override fun elements(): Sequence> = structure.elements() override fun get(index: Int): T = structure[index] @@ -62,8 +67,8 @@ private class MutableStructure1DWrapper(val structure: MutableStructureND) structure[intArrayOf(index)] = value } - override fun copy(): MutableBuffer = - structure.elements().map { it.second }.toMutableList().asMutableBuffer() + @PerformancePitfall + override fun copy(): MutableBuffer = structure.elements().map { it.second }.toMutableList().asMutableBuffer() } @@ -75,8 +80,10 @@ private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D { override val shape: IntArray get() = intArrayOf(buffer.size) override val size: Int get() = buffer.size - override fun elements(): Sequence> = - buffer.asSequence().mapIndexed { index, value -> intArrayOf(index) to value } + @PerformancePitfall + override fun elements(): Sequence> = buffer.asSequence().mapIndexed { index, value -> + intArrayOf(index) to value + } override operator fun get(index: Int): T = buffer[index] } @@ -85,8 +92,10 @@ internal class MutableBuffer1DWrapper(val buffer: MutableBuffer) : Mutable override val shape: IntArray get() = intArrayOf(buffer.size) override val size: Int get() = buffer.size - override fun elements(): Sequence> = - buffer.asSequence().mapIndexed { index, value -> intArrayOf(index) to value } + @PerformancePitfall + override fun elements(): Sequence> = buffer.asSequence().mapIndexed { index, value -> + intArrayOf(index) to value + } override operator fun get(index: Int): T = buffer[index] override fun set(index: Int, value: T) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 28ae07a3c..8dce4ad6b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -5,10 +5,11 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.VirtualBuffer import space.kscience.kmath.structures.MutableListBuffer +import space.kscience.kmath.structures.VirtualBuffer import kotlin.jvm.JvmInline import kotlin.reflect.KClass @@ -33,12 +34,14 @@ public interface Structure2D : StructureND { /** * The buffer of rows of this structure. It gets elements from the structure dynamically. */ + @PerformancePitfall public val rows: List> get() = List(rowNum) { i -> VirtualBuffer(colNum) { j -> get(i, j) } } /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ + @PerformancePitfall public val columns: List> get() = List(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } } @@ -80,12 +83,14 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { /** * The buffer of rows of this structure. It gets elements from the structure dynamically. */ + @PerformancePitfall override val rows: List> get() = List(rowNum) { i -> MutableBuffer1DWrapper(MutableListBuffer(colNum) { j -> get(i, j) })} /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ + @PerformancePitfall override val columns: List> get() = List(colNum) { j -> MutableBuffer1DWrapper(MutableListBuffer(rowNum) { i -> get(i, j) }) } } @@ -105,6 +110,7 @@ private value class Structure2DWrapper(val structure: StructureND) : Struc @UnstableKMathAPI override fun getFeature(type: KClass): F? = structure.getFeature(type) + @PerformancePitfall override fun elements(): Sequence> = structure.elements() } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index a3331d71a..b9f1a063a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory @@ -48,6 +49,7 @@ public interface StructureND { * * @return the lazy sequence of pairs of indices to values. */ + @PerformancePitfall public fun elements(): Sequence> /** @@ -61,6 +63,7 @@ public interface StructureND { /** * Indicates whether some [StructureND] is equal to another one. */ + @PerformancePitfall public fun contentEquals(st1: StructureND, st2: StructureND): Boolean { if (st1 === st2) return true @@ -169,6 +172,7 @@ public interface MutableStructureND : StructureND { /** * Transform a structure element-by element in place. */ +@OptIn(PerformancePitfall::class) public inline fun MutableStructureND.mapInPlace(action: (IntArray, T) -> T): Unit = elements().forEach { (index, oldValue) -> this[index] = action(index, oldValue) } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt index ebbbbe392..2d2a0952b 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt @@ -5,12 +5,14 @@ package space.kscience.kmath.linear +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue +@OptIn(PerformancePitfall::class) fun assertMatrixEquals(expected: StructureND, actual: StructureND) { assertTrue { StructureND.contentEquals(expected, actual) } } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt index 250fa3433..170f9caf4 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.linear +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.as2D @@ -13,6 +14,7 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue @UnstableKMathAPI +@OptIn(PerformancePitfall::class) @Suppress("UNUSED_VARIABLE") class MatrixTest { @Test diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt index 99743d879..57393fadd 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.structures import space.kscience.kmath.linear.LinearSpace +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.invoke @@ -74,6 +75,7 @@ class NumberNDFieldTest { } object L2Norm : Norm, Double> { + @OptIn(PerformancePitfall::class) override fun norm(arg: StructureND): Double = kotlin.math.sqrt(arg.elements().sumOf { it.second.toDouble() }) } diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt index e2ecb4b2f..1cd16054a 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt @@ -7,6 +7,7 @@ package space.kscience.kmath.structures import kotlinx.coroutines.* import space.kscience.kmath.coroutines.Math +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.DefaultStrides import space.kscience.kmath.nd.StructureND @@ -24,6 +25,7 @@ public class LazyStructureND( public suspend fun await(index: IntArray): T = deferred(index).await() public override operator fun get(index: IntArray): T = runBlocking { deferred(index).await() } + @OptIn(PerformancePitfall::class) public override fun elements(): Sequence> { val strides = DefaultStrides(shape) val res = runBlocking { strides.indices().toList().map { index -> index to await(index) } } diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt index 485c53c38..50675bdac 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -12,12 +12,14 @@ import org.ejml.dense.row.factory.DecompositionFactory_DDRM import space.kscience.kmath.linear.DeterminantFeature import space.kscience.kmath.linear.LupDecompositionFeature import space.kscience.kmath.linear.getFeature +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import kotlin.random.Random import kotlin.random.asJavaRandom import kotlin.test.* +@OptIn(PerformancePitfall::class) fun assertMatrixEquals(expected: StructureND, actual: StructureND) { assertTrue { StructureND.contentEquals(expected, actual) } } diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt index c4656dd8a..8023236ea 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt @@ -3,9 +3,13 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:OptIn(PerformancePitfall::class) +@file:Suppress("unused") + package space.kscience.kmath.real import space.kscience.kmath.linear.* +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.Buffer diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt index 84e604b18..b3e129c2e 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt @@ -7,6 +7,7 @@ package kaceince.kmath.real import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.matrix +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import space.kscience.kmath.real.* @@ -15,6 +16,7 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue +@OptIn(PerformancePitfall::class) fun assertMatrixEquals(expected: StructureND, actual: StructureND) { assertTrue { StructureND.contentEquals(expected, actual) } } diff --git a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt index 78b25af47..f3d553f2e 100644 --- a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt +++ b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt @@ -8,11 +8,12 @@ import org.jetbrains.kotlinx.jupyter.api.DisplayResult import org.jetbrains.kotlinx.jupyter.api.HTML import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration -import space.kscience.kmath.expressions.MST import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer import space.kscience.kmath.ast.rendering.renderWithStringBuilder import space.kscience.kmath.complex.Complex +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.operations.GroupOperations import space.kscience.kmath.operations.RingOperations @@ -55,6 +56,7 @@ internal class KMathJupyter : JupyterIntegration() { } } + @OptIn(PerformancePitfall::class) override fun Builder.onLoaded() { import( "space.kscience.kmath.ast.*", diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt index 79db86fcc..d37c91cb6 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.MutableStructureND import space.kscience.kmath.nd.StructureND @@ -24,6 +25,7 @@ public sealed class Nd4jArrayStructure : MutableStructureND { internal abstract fun elementsIterator(): Iterator> internal fun indicesIterator(): Iterator = ndArray.indicesIterator() + @PerformancePitfall public override fun elements(): Sequence> = Sequence(::elementsIterator) } 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 858532abc..315dc4505 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,7 +1,8 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.Strides -import space.kscience.kmath.structures.* +import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.internal.TensorLinearStructure @@ -32,7 +33,8 @@ public open class BufferedTensor internal constructor( mutableBuffer[bufferStart + linearStructure.offset(index)] = value } + @PerformancePitfall override fun elements(): Sequence> = linearStructure.indices().map { - it to this[it] + it to get(it) } } diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt index dc1b45f5d..b7abf4304 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.viktor import org.jetbrains.bio.viktor.F64Array +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleField @@ -23,6 +24,7 @@ public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructur f64Buffer.set(*index, value = value) } + @PerformancePitfall public override fun elements(): Sequence> = DefaultStrides(shape).indices().map { it to get(it) } } From f5289abdc3e6c636ff2411f04141eddd4847a5f8 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 13 May 2021 11:09:49 +0300 Subject: [PATCH 209/211] Introduce PerformancePitfall annotation --- kmath-core/api/kmath-core.api | 3 +++ .../commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt | 2 ++ .../kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt | 4 +--- .../kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt | 4 +--- .../space/kscience/kmath/histogram/IndexedHistogramSpace.kt | 5 ++--- .../kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 2 ++ .../kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt | 4 +++- .../space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt | 2 ++ .../space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 2 ++ 9 files changed, 18 insertions(+), 10 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 7dd459104..14bc70a2a 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -674,6 +674,9 @@ public final class space/kscience/kmath/misc/CumulativeKt { public static final fun cumulativeSumOfLong (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; } +public abstract interface annotation class space/kscience/kmath/misc/PerformancePitfall : java/lang/annotation/Annotation { +} + public final class space/kscience/kmath/misc/StringSymbol : space/kscience/kmath/misc/Symbol { public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/misc/StringSymbol; public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 8dce4ad6b..5b8183699 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -59,6 +59,7 @@ public interface Structure2D : StructureND { return get(index[0], index[1]) } + @PerformancePitfall override fun elements(): Sequence> = sequence { for (i in 0 until rowNum) for (j in 0 until colNum) yield(intArrayOf(i, j) to get(i, j)) @@ -134,6 +135,7 @@ private class MutableStructure2DWrapper(val structure: MutableStructureND) structure[intArrayOf(i, j)] = value } + @PerformancePitfall override fun elements(): Sequence> = structure.elements() override fun equals(other: Any?): Boolean = false diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt index 3604fda31..2a4837ee0 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt @@ -7,16 +7,14 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.GroupElement import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import kotlin.math.sqrt @OptIn(UnstableKMathAPI::class) -public interface Vector2D : Point, Vector, GroupElement { +public interface Vector2D : Point, Vector{ public val x: Double public val y: Double - public override val context: Euclidean2DSpace get() = Euclidean2DSpace public override val size: Int get() = 2 public override operator fun get(index: Int): Double = when (index) { diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt index 8643b2dbb..37e7d2cb2 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt @@ -7,17 +7,15 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.GroupElement import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import kotlin.math.sqrt @OptIn(UnstableKMathAPI::class) -public interface Vector3D : Point, Vector, GroupElement { +public interface Vector3D : Point, Vector { public val x: Double public val y: Double public val z: Double - public override val context: Euclidean3DSpace get() = Euclidean3DSpace public override val size: Int get() = 3 public override operator fun get(index: Int): Double = when (index) { diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt index 818d81ab0..e5f6830c5 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt @@ -12,7 +12,6 @@ import space.kscience.kmath.nd.FieldND import space.kscience.kmath.nd.Strides import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.Group -import space.kscience.kmath.operations.GroupElement import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke @@ -26,9 +25,9 @@ public data class DomainBin>( @OptIn(UnstableKMathAPI::class) public class IndexedHistogram, V : Any>( - override val context: IndexedHistogramSpace, + public val context: IndexedHistogramSpace, public val values: StructureND, -) : Histogram>, GroupElement, IndexedHistogramSpace> { +) : Histogram> { override fun get(point: Point): Bin? { val index = context.getIndex(point) ?: return null diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index 0205f1c87..3cac44c47 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -10,6 +10,7 @@ import org.nd4j.linalg.api.ops.impl.scalar.Pow import org.nd4j.linalg.api.ops.impl.transforms.strict.* import org.nd4j.linalg.factory.Nd4j import org.nd4j.linalg.ops.transforms.Transforms +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* @@ -52,6 +53,7 @@ public interface Nd4jArrayAlgebra> : AlgebraND { return struct } + @PerformancePitfall public override fun StructureND.map(transform: C.(T) -> T): Nd4jArrayStructure { val newStruct = ndArray.dup().wrap() newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) } diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt index b6c524cc6..c80a1d771 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.factory.Nd4j +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.invoke import kotlin.math.PI @@ -14,6 +15,7 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue import kotlin.test.fail +@OptIn(PerformancePitfall::class) internal class Nd4jArrayAlgebraTest { @Test fun testProduce() { @@ -28,7 +30,7 @@ internal class Nd4jArrayAlgebraTest { @Test fun testMap() { - val res = with(IntNd4jArrayRing(intArrayOf(2, 2))) { one.map() { it + it * 2 } } + val res = with(IntNd4jArrayRing(intArrayOf(2, 2))) { one.map { it + it * 2 } } val expected = (Nd4j.create(2, 2) ?: fail()).asIntStructure() expected[intArrayOf(0, 0)] = 3 expected[intArrayOf(0, 1)] = 3 diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt index d59e04194..bdfec2ba6 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.factory.Nd4j +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.get import kotlin.test.Test import kotlin.test.assertEquals @@ -13,6 +14,7 @@ import kotlin.test.assertNotEquals import kotlin.test.fail internal class Nd4jArrayStructureTest { + @OptIn(PerformancePitfall::class) @Test fun testElements() { val nd = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index a6c6a7618..a176abdd4 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.DefaultStrides import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.nd.as1D @@ -24,6 +25,7 @@ internal class TestDoubleTensor { assertEquals(tensor.value(), value) } + @OptIn(PerformancePitfall::class) @Test fun testStrides() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) From feb5743f58616af3c46917ce098c63778191e5db Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 13 May 2021 11:10:59 +0300 Subject: [PATCH 210/211] Change signature of one of integrate helpers --- .../kscience/kmath/commons/integration/IntegrationTest.kt | 6 +++--- .../space/kscience/kmath/integration/UnivariateIntegrand.kt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt index 9d475d04d..97dc94d1d 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt @@ -19,16 +19,16 @@ internal class IntegrationTest { @Test fun simpson() { - val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function) + val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function = function) assertTrue { abs(res) < 1e-3 } } @Test fun customSimpson() { - val res = CMIntegrator.simpson().integrate(0.0..PI, function) { + val res = CMIntegrator.simpson().integrate(0.0..PI, { targetRelativeAccuracy = 1e-4 targetAbsoluteAccuracy = 1e-4 - } + }, function) assertTrue { abs(res - 2) < 1e-3 } assertTrue { abs(res - 2) > 1e-12 } } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index bcd5005c4..51ea57a33 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -57,8 +57,8 @@ public fun UnivariateIntegrator.integrate( @UnstableKMathAPI public fun UnivariateIntegrator.integrate( range: ClosedRange, + featureBuilder: MutableList.() -> Unit = {}, function: (Double) -> Double, - featureBuilder: (MutableList.() -> Unit) = {}, ): Double { //TODO use dedicated feature builder class instead or add extensions to MutableList val features = buildList { From fcb960533823090eff6fae936ffa0058db65ff88 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 13 May 2021 22:59:35 +0700 Subject: [PATCH 211/211] Special rendering of Quaternion #330 --- .../space/kscience/kmath/complex/Complex.kt | 2 +- .../kscience/kmath/jupyter/KMathJupyter.kt | 24 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt index 8e28337f6..a96d046c9 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt @@ -187,7 +187,7 @@ public data class Complex(val re: Double, val im: Double) { public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble()) public constructor(re: Number) : this(re.toDouble(), 0.0) - public override fun toString(): String = "($re + i*$im)" + public override fun toString(): String = "($re + i * $im)" public companion object : MemorySpec { public override val objectSize: Int diff --git a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt index f3d553f2e..e3767e13c 100644 --- a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt +++ b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt @@ -12,18 +12,19 @@ import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer import space.kscience.kmath.ast.rendering.renderWithStringBuilder import space.kscience.kmath.complex.Complex +import space.kscience.kmath.complex.Quaternion import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.Structure2D -import space.kscience.kmath.operations.GroupOperations -import space.kscience.kmath.operations.RingOperations +import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asSequence /** * A function for conversion of number to MST for pretty print */ -public fun Number.toMst(): MST.Numeric = MST.Numeric(this) +public fun Number.toMst(): MST.Numeric = MST.Numeric(this) @JupyterLibrary internal class KMathJupyter : JupyterIntegration() { @@ -121,11 +122,18 @@ internal class KMathJupyter : JupyterIntegration() { } render { - MST.Binary( - operation = GroupOperations.PLUS_OPERATION, - left = MST.Numeric(it.re), - right = MST.Binary(RingOperations.TIMES_OPERATION, MST.Numeric(it.im), MST.Symbolic("i")), - ).toDisplayResult() + MstRing { + number(it.re) + number(it.im) * bindSymbol("i") + }.toDisplayResult() + } + + render { + MstRing { + number(it.w) + + number(it.x) * bindSymbol("i") + + number(it.x) * bindSymbol("j") + + number(it.x) * bindSymbol("k") + }.toDisplayResult() } } }